staticvoid
bits_image_fetch_pixel_separable_convolution (bits_image_t *image,
pixman_fixed_t x,
pixman_fixed_t y,
get_pixel_t get_pixel, void *out,
accumulate_pixel_t accum,
reduce_pixel_t reduce)
{
pixman_fixed_t *params = image->common.filter_params;
pixman_repeat_t repeat_mode = image->common.repeat; int width = image->width; int height = image->height; int cwidth = pixman_fixed_to_int (params[0]); int cheight = pixman_fixed_to_int (params[1]); int x_phase_bits = pixman_fixed_to_int (params[2]); int y_phase_bits = pixman_fixed_to_int (params[3]); int x_phase_shift = 16 - x_phase_bits; int y_phase_shift = 16 - y_phase_bits; int x_off = ((cwidth << 16) - pixman_fixed_1) >> 1; int y_off = ((cheight << 16) - pixman_fixed_1) >> 1;
pixman_fixed_t *y_params; unsignedint srtot, sgtot, sbtot, satot;
int32_t x1, x2, y1, y2;
int32_t px, py; int i, j;
/* Round x and y to the middle of the closest phase before continuing. This * ensures that the convolution matrix is aligned right, since it was * positioned relative to a particular phase (and not relative to whatever * exact fraction we happen to get here).
*/
x = ((x >> x_phase_shift) << x_phase_shift) + ((1 << x_phase_shift) >> 1);
y = ((y >> y_phase_shift) << y_phase_shift) + ((1 << y_phase_shift) >> 1);
static force_inline void
bits_image_fetch_pixel_filtered (bits_image_t *image,
pixman_bool_t wide,
pixman_fixed_t x,
pixman_fixed_t y,
get_pixel_t get_pixel, void *out)
{ switch (image->common.filter)
{ case PIXMAN_FILTER_NEAREST: case PIXMAN_FILTER_FAST:
bits_image_fetch_pixel_nearest (image, x, y, get_pixel, out); break;
case PIXMAN_FILTER_BILINEAR: case PIXMAN_FILTER_GOOD: case PIXMAN_FILTER_BEST: if (wide)
bits_image_fetch_pixel_bilinear_float (image, x, y, get_pixel, out); else
bits_image_fetch_pixel_bilinear_32 (image, x, y, get_pixel, out); break;
case PIXMAN_FILTER_CONVOLUTION: if (wide)
{
bits_image_fetch_pixel_convolution (image, x, y,
get_pixel, out,
accum_float,
reduce_float);
} else
{
bits_image_fetch_pixel_convolution (image, x, y,
get_pixel, out,
accum_32, reduce_32);
} break;
case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: if (wide)
{
bits_image_fetch_pixel_separable_convolution (image, x, y,
get_pixel, out,
accum_float,
reduce_float);
} else
{
bits_image_fetch_pixel_separable_convolution (image, x, y,
get_pixel, out,
accum_32, reduce_32);
} break;
default:
assert (0); break;
}
}
static uint32_t *
__bits_image_fetch_affine_no_alpha (pixman_iter_t * iter,
pixman_bool_t wide, const uint32_t * mask)
{
pixman_image_t *image = iter->image; int offset = iter->x; int line = iter->y++; int width = iter->width;
uint32_t * buffer = iter->buffer;
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
if (image->common.transform)
{ if (!pixman_transform_point_3d (image->common.transform, &v)) return iter->buffer;
ux = image->common.transform->matrix[0][0];
uy = image->common.transform->matrix[1][0];
} else
{
ux = pixman_fixed_1;
uy = 0;
}
x = v.vector[0];
y = v.vector[1];
for (i = 0; i < width; ++i)
{ if (!mask || (!wide && mask[i]) ||
(wide && memcmp(&mask[4 * i], wide_zero, 16) != 0))
{
bits_image_fetch_pixel_filtered (
&image->bits, wide, x, y, get_pixel, buffer);
}
const uint32_t wide_zero[4] = {0};
pixman_fixed_t x, y, w;
pixman_fixed_t ux, uy, uw;
pixman_vector_t v; int i;
/* reference point is the center of the pixel */
v.vector[0] = pixman_int_to_fixed (offset) + pixman_fixed_1 / 2;
v.vector[1] = pixman_int_to_fixed (line) + pixman_fixed_1 / 2;
v.vector[2] = pixman_fixed_1;
if (image->common.transform)
{ if (!pixman_transform_point_3d (image->common.transform, &v)) return buffer;
staticvoid
replicate_pixel_32 (bits_image_t * bits, int x, int y, int width,
uint32_t * buffer)
{
uint32_t color;
uint32_t *end;
color = bits->fetch_pixel_32 (bits, x, y);
end = buffer + width; while (buffer < end)
*(buffer++) = color;
}
staticvoid
replicate_pixel_float (bits_image_t * bits, int x, int y, int width,
uint32_t * b)
{
argb_t color;
argb_t *buffer = (argb_t *)b;
argb_t *end;
color = bits->fetch_pixel_float (bits, x, y);
end = buffer + width; while (buffer < end)
*(buffer++) = color;
}
staticvoid
bits_image_fetch_untransformed_repeat_none (bits_image_t *image,
pixman_bool_t wide, int x, int y, int width,
uint32_t * buffer)
{
uint32_t w;
staticvoid
bits_image_fetch_untransformed_repeat_normal (bits_image_t *image,
pixman_bool_t wide, int x, int y, int width,
uint32_t * buffer)
{
uint32_t w;
while (y < 0)
y += image->height;
while (y >= image->height)
y -= image->height;
if (image->width == 1)
{ if (wide)
replicate_pixel_float (image, 0, y, width, buffer); else
replicate_pixel_32 (image, 0, y, width, buffer);
return;
}
while (width)
{ while (x < 0)
x += image->width; while (x >= image->width)
x -= image->width;
w = MIN (width, image->width - x);
if (wide)
image->fetch_scanline_float (image, x, y, w, buffer, NULL); else
image->fetch_scanline_32 (image, x, y, w, buffer, NULL);
buffer += w * (wide? 4 : 1);
x += w;
width -= w;
}
}
static uint32_t *
bits_image_fetch_untransformed_32 (pixman_iter_t * iter, const uint32_t *mask)
{
pixman_image_t *image = iter->image; int x = iter->x; int y = iter->y; int width = iter->width;
uint32_t * buffer = iter->buffer;
if (image->common.repeat == PIXMAN_REPEAT_NONE)
{
bits_image_fetch_untransformed_repeat_none (
&image->bits, FALSE, x, y, width, buffer);
} else
{
bits_image_fetch_untransformed_repeat_normal (
&image->bits, FALSE, x, y, width, buffer);
}
iter->y++; return buffer;
}
static uint32_t *
bits_image_fetch_untransformed_float (pixman_iter_t * iter, const uint32_t *mask)
{
pixman_image_t *image = iter->image; int x = iter->x; int y = iter->y; int width = iter->width;
uint32_t * buffer = iter->buffer;
if (image->common.repeat == PIXMAN_REPEAT_NONE)
{
bits_image_fetch_untransformed_repeat_none (
&image->bits, TRUE, x, y, width, buffer);
} else
{
bits_image_fetch_untransformed_repeat_normal (
&image->bits, TRUE, x, y, width, buffer);
}
/* Just in case we somehow didn't find a scanline function */
iter->get_scanline = _pixman_iter_get_scanline_noop;
}
static uint32_t *
dest_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
{
pixman_image_t *image = iter->image; int x = iter->x; int y = iter->y; int width = iter->width;
uint32_t * buffer = iter->buffer;
image->bits.fetch_scanline_32 (&image->bits, x, y, width, buffer, mask); if (image->common.alpha_map)
{
uint32_t *alpha;
if ((alpha = malloc (width * sizeof (uint32_t))))
{ int i;
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
image->common.alpha_map->fetch_scanline_32 (
image->common.alpha_map, x, y, width, alpha, mask);
for (i = 0; i < width; ++i)
{
buffer[i] &= ~0xff000000;
buffer[i] |= (alpha[i] & 0xff000000);
}
free (alpha);
}
}
return iter->buffer;
}
static uint32_t *
dest_get_scanline_wide (pixman_iter_t *iter, const uint32_t *mask)
{
bits_image_t * image = &iter->image->bits; int x = iter->x; int y = iter->y; int width = iter->width;
argb_t * buffer = (argb_t *)iter->buffer;
image->fetch_scanline_float (
image, x, y, width, (uint32_t *)buffer, mask); if (image->common.alpha_map)
{
argb_t *alpha;
if ((alpha = malloc (width * sizeof (argb_t))))
{ int i;
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
image->common.alpha_map->fetch_scanline_float (
image->common.alpha_map, x, y, width, (uint32_t *)alpha, mask);
for (i = 0; i < width; ++i)
buffer[i].a = alpha[i].a;
free (alpha);
}
}
return iter->buffer;
}
staticvoid
dest_write_back_narrow (pixman_iter_t *iter)
{
bits_image_t * image = &iter->image->bits; int x = iter->x; int y = iter->y; int width = iter->width; const uint32_t *buffer = iter->buffer;
image->store_scanline_32 (image, x, y, width, buffer);
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
image->common.alpha_map->store_scanline_32 (
image->common.alpha_map, x, y, width, buffer);
}
iter->y++;
}
staticfloat
dither_factor_blue_noise_64 (int x, int y)
{ float m = dither_blue_noise_64x64[((y & 0x3f) << 6) | (x & 0x3f)]; return m * (1. / 4096.f) + (1. / 8192.f);
}
staticfloat
dither_factor_bayer_8 (int x, int y)
{
uint32_t m;
y ^= x;
/* Compute reverse(interleave(xor(x mod n, y mod n), x mod n)) * Here n = 8 and `mod n` is the bottom 3 bits.
*/
m = ((y & 0x1) << 5) | ((x & 0x1) << 4) |
((y & 0x2) << 2) | ((x & 0x2) << 1) |
((y & 0x4) >> 1) | ((x & 0x4) >> 2);
/* m is in range [0, 63]. We scale it to [0, 63.0f/64.0f], then * shift it to to [1.0f/128.0f, 127.0f/128.0f] so that 0 < d < 1. * This ensures exact values are not changed by dithering.
*/ return (float)(m) * (1 / 64.0f) + (1.0f / 128.0f);
}
typedeffloat (* dither_factor_t)(int x, int y);
static force_inline float
dither_apply_channel (float f, float d, float s)
{ /* float_to_unorm splits the [0, 1] segment in (1 << n_bits) * subsections of equal length; however unorm_to_float does not * map to the center of those sections. In fact, pixel value u is * mapped to: * * u u u 1 * -------------- = ---------- + -------------- * ---------- * 2^n_bits - 1 2^n_bits 2^n_bits - 1 2^n_bits * * Hence if f = u / (2^n_bits - 1) is exactly representable on a * n_bits palette, all the numbers between * * u * ---------- = f - f * 2^n_bits = f + (0 - f) * 2^n_bits * 2^n_bits * * and * * u + 1 * ---------- = f - (f - 1) * 2^n_bits = f + (1 - f) * 2^n_bits * 2^n_bits * * are also mapped back to u. * * Hence the following calculation ensures that we add as much * noise as possible without perturbing values which are exactly * representable in the target colorspace. Note that this corresponds to * mixing the original color with noise with a ratio of `1 / 2^n_bits`.
*/ return f + (d - f) * s;
}
static force_inline float
dither_compute_scale (int n_bits)
{ // No dithering for wide formats if (n_bits == 0 || n_bits >= 32) return 0.f;
return 1.f / (float)(1 << n_bits);
}
staticconst uint32_t *
dither_apply_ordered (pixman_iter_t *iter, dither_factor_t factor)
{
bits_image_t *image = &iter->image->bits; int x = iter->x + image->dither_offset_x; int y = iter->y + image->dither_offset_y; int width = iter->width;
argb_t *buffer = (argb_t *)iter->buffer;
pixman_format_code_t format = image->format; int a_size = PIXMAN_FORMAT_A (format); int r_size = PIXMAN_FORMAT_R (format); int g_size = PIXMAN_FORMAT_G (format); int b_size = PIXMAN_FORMAT_B (format);
staticvoid
dest_write_back_wide (pixman_iter_t *iter)
{
bits_image_t * image = &iter->image->bits; int x = iter->x; int y = iter->y; int width = iter->width; const uint32_t *buffer = iter->buffer;
switch (image->dither)
{ case PIXMAN_DITHER_NONE: break;
case PIXMAN_DITHER_GOOD: case PIXMAN_DITHER_BEST: case PIXMAN_DITHER_ORDERED_BLUE_NOISE_64:
buffer = dither_apply_ordered (iter, dither_factor_blue_noise_64); break;
case PIXMAN_DITHER_FAST: case PIXMAN_DITHER_ORDERED_BAYER_8:
buffer = dither_apply_ordered (iter, dither_factor_bayer_8); break;
}
image->store_scanline_float (image, x, y, width, buffer);
if (image->common.alpha_map)
{
x -= image->common.alpha_origin_x;
y -= image->common.alpha_origin_y;
image->common.alpha_map->store_scanline_float (
image->common.alpha_map, x, y, width, buffer);
}
static uint32_t *
create_bits (pixman_format_code_t format, int width, int height, int * rowstride_bytes,
pixman_bool_t clear)
{ int stride;
size_t buf_size; int bpp;
/* what follows is a long-winded way, avoiding any possibility of integer * overflows, of saying: * stride = ((width * bpp + 0x1f) >> 5) * sizeof (uint32_t);
*/
bpp = PIXMAN_FORMAT_BPP (format); if (_pixman_multiply_overflows_int (width, bpp)) return NULL;
static pixman_image_t *
create_bits_image_internal (pixman_format_code_t format, int width, int height,
uint32_t * bits, int rowstride_bytes,
pixman_bool_t clear)
{
pixman_image_t *image;
/* must be a whole number of uint32_t's
*/
return_val_if_fail (
bits == NULL || (rowstride_bytes % sizeof (uint32_t)) == 0, NULL);
if (!_pixman_bits_image_init (image, format, width, height, bits,
rowstride_bytes / (int) sizeof (uint32_t),
clear))
{
free (image); return NULL;
}
return image;
}
/* If bits is NULL, a buffer will be allocated and initialized to 0 */
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits (pixman_format_code_t format, int width, int height,
uint32_t * bits, int rowstride_bytes)
{ return create_bits_image_internal (
format, width, height, bits, rowstride_bytes, TRUE);
}
/* If bits is NULL, a buffer will be allocated and _not_ initialized */
PIXMAN_EXPORT pixman_image_t *
pixman_image_create_bits_no_clear (pixman_format_code_t format, int width, int height,
uint32_t * bits, int rowstride_bytes)
{ return create_bits_image_internal (
format, width, height, bits, rowstride_bytes, FALSE);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.