diff options
Diffstat (limited to 'pixman')
-rw-r--r-- | pixman/.gitignore | 2 | ||||
-rw-r--r-- | pixman/demos/Makefile.am | 4 | ||||
-rw-r--r-- | pixman/demos/srgb-test.c | 96 | ||||
-rw-r--r-- | pixman/pixman/Makefile.sources | 5 | ||||
-rw-r--r-- | pixman/pixman/make-srgb.pl | 112 | ||||
-rw-r--r-- | pixman/pixman/pixman-access.c | 134 | ||||
-rw-r--r-- | pixman/pixman/pixman-image.c | 3 | ||||
-rw-r--r-- | pixman/pixman/pixman-private.h | 15 | ||||
-rw-r--r-- | pixman/pixman/pixman.c | 1 | ||||
-rw-r--r-- | pixman/pixman/pixman.h | 4 | ||||
-rw-r--r-- | pixman/test/composite.c | 76 | ||||
-rw-r--r-- | pixman/test/stress-test.c | 1 | ||||
-rw-r--r-- | pixman/test/utils.c | 36 | ||||
-rw-r--r-- | pixman/test/utils.h | 6 |
14 files changed, 476 insertions, 19 deletions
diff --git a/pixman/.gitignore b/pixman/.gitignore index b9853b117..a4d9f99a7 100644 --- a/pixman/.gitignore +++ b/pixman/.gitignore @@ -36,12 +36,14 @@ demos/gradient-test demos/quad2quad demos/radial-test demos/screen-test +demos/srgb-test demos/trap-test demos/tri-test pixman/pixman-combine32.c pixman/pixman-combine32.h pixman/pixman-combine64.c pixman/pixman-combine64.h +pixman/pixman-srgb.c pixman/pixman-version.h test/a1-trap-test test/affine-test diff --git a/pixman/demos/Makefile.am b/pixman/demos/Makefile.am index 9aac1f5e9..d8fb0dab2 100644 --- a/pixman/demos/Makefile.am +++ b/pixman/demos/Makefile.am @@ -20,7 +20,8 @@ DEMOS = \ trap-test \ tri-test \ quad2quad \ - checkerboard + checkerboard \ + srgb-test EXTRA_DIST = parrot.c parrot.jpg @@ -35,6 +36,7 @@ convolution_test_SOURCES = convolution-test.c $(GTK_UTILS) radial_test_SOURCES = radial-test.c $(GTK_UTILS) tri_test_SOURCES = tri-test.c $(GTK_UTILS) checkerboard_SOURCES = checkerboard.c $(GTK_UTILS) +srgb_test_SOURCES = srgb-test.c $(GTK_UTILS) noinst_PROGRAMS = $(DEMOS) diff --git a/pixman/demos/srgb-test.c b/pixman/demos/srgb-test.c new file mode 100644 index 000000000..bc073491e --- /dev/null +++ b/pixman/demos/srgb-test.c @@ -0,0 +1,96 @@ +#include <math.h> + +#include "pixman.h" +#include "gtk-utils.h" + +static uint32_t +linear_argb_to_premult_argb (float a, + float r, + float g, + float b) +{ + r *= a; + g *= a; + b *= a; + return (uint32_t) (a * 255.0f + 0.5f) << 24 + | (uint32_t) (r * 255.0f + 0.5f) << 16 + | (uint32_t) (g * 255.0f + 0.5f) << 8 + | (uint32_t) (b * 255.0f + 0.5f) << 0; +} + +static float +lin2srgb (float linear) +{ + if (linear < 0.0031308f) + return linear * 12.92f; + else + return 1.055f * powf (linear, 1.0f/2.4f) - 0.055f; +} + +static uint32_t +linear_argb_to_premult_srgb_argb (float a, + float r, + float g, + float b) +{ + r = lin2srgb (r * a); + g = lin2srgb (g * a); + b = lin2srgb (b * a); + return (uint32_t) (a * 255.0f + 0.5f) << 24 + | (uint32_t) (r * 255.0f + 0.5f) << 16 + | (uint32_t) (g * 255.0f + 0.5f) << 8 + | (uint32_t) (b * 255.0f + 0.5f) << 0; +} + +int +main (int argc, char **argv) +{ +#define WIDTH 400 +#define HEIGHT 200 + int y, x, p; + float alpha; + + uint32_t *dest = malloc (WIDTH * HEIGHT * 4); + uint32_t *src1 = malloc (WIDTH * HEIGHT * 4); + pixman_image_t *dest_img, *src1_img; + + dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8_sRGB, + WIDTH, HEIGHT, + dest, + WIDTH * 4); + src1_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, + WIDTH, HEIGHT, + src1, + WIDTH * 4); + + for (y = 0; y < HEIGHT; y ++) + { + p = WIDTH * y; + for (x = 0; x < WIDTH; x ++) + { + alpha = (float) x / WIDTH; + src1[p + x] = linear_argb_to_premult_argb (alpha, 1, 0, 1); + dest[p + x] = linear_argb_to_premult_srgb_argb (1-alpha, 0, 1, 0); + } + } + + pixman_image_composite (PIXMAN_OP_ADD, src1_img, NULL, dest_img, + 0, 0, 0, 0, 0, 0, WIDTH, HEIGHT); + pixman_image_unref (src1_img); + free (src1); + + pixman_image_unref (dest_img); + + /* Now that the picture has been correctly constructed, + * we hand it over to our support library as argb which it + * knows how to handle (it doesn't understand _sRGB format). */ + dest_img = pixman_image_create_bits (PIXMAN_a8r8g8b8, + WIDTH, HEIGHT, + dest, + WIDTH * 4); + show_image (dest_img); + pixman_image_unref (dest_img); + free (dest); + + return 0; +} diff --git a/pixman/pixman/Makefile.sources b/pixman/pixman/Makefile.sources index 6472994c4..cf7040f33 100644 --- a/pixman/pixman/Makefile.sources +++ b/pixman/pixman/Makefile.sources @@ -25,6 +25,7 @@ libpixman_sources = \ pixman-region16.c \ pixman-region32.c \ pixman-solid-fill.c \ + pixman-srgb.c \ pixman-timer.c \ pixman-trap.c \ pixman-utils.c \ @@ -46,8 +47,12 @@ BUILT_SOURCES = \ pixman-combine32.h \ pixman-combine64.c \ pixman-combine64.h \ + pixman-srgb.c \ $(NULL) +pixman-srgb.c: make-srgb.pl + $(PERL) $< > $@ || ($(RM) $@; exit 1) + pixman-combine32.c: pixman-combine.c.template make-combine.pl $(PERL) $(lastword $+) 8 < $< > $@ || ($(RM) $@; exit 1) pixman-combine32.h: pixman-combine.h.template make-combine.pl diff --git a/pixman/pixman/make-srgb.pl b/pixman/pixman/make-srgb.pl new file mode 100644 index 000000000..ebde2eac6 --- /dev/null +++ b/pixman/pixman/make-srgb.pl @@ -0,0 +1,112 @@ +#!/usr/bin/perl -w + +use strict; + +sub linear_to_srgb +{ + my ($c) = @_; + + if ($c < 0.0031308) + { + return $c * 12.92; + } + else + { + return 1.055 * $c ** (1.0/2.4) - 0.055; + } +} + +sub srgb_to_linear +{ + my ($c) = @_; + + if ($c < 0.04045) + { + return $c / 12.92; + } + else + { + return (($c + 0.055) / 1.055) ** 2.4 + } +} + +my @linear_to_srgb; +for my $linear (0 .. 4095) +{ + my $srgb = int(linear_to_srgb($linear / 4095.0) * 255.0 + 0.5); + push @linear_to_srgb, $srgb; +} + +my @srgb_to_linear; +for my $srgb (0 .. 255) +{ + my $linear = int(srgb_to_linear($srgb / 255.0) * 65535.0 + 0.5); + push @srgb_to_linear, $linear; +} + +# Ensure that we have a lossless sRGB and back conversion loop. +# some of the darkest shades need a little bias -- maximum is just +# 5 increments out of 16. This gives us useful property with +# least amount of error in the sRGB-to-linear table, and keeps the actual +# table lookup in the other direction as simple as possible. +for my $srgb (0 .. $#srgb_to_linear) +{ + my $add = 0; + while (1) + { + my $linear = $srgb_to_linear[$srgb]; + my $srgb_lossy = $linear_to_srgb[$linear >> 4]; + last if $srgb == $srgb_lossy; + + # Add slight bias to this component until it rounds correctly + $srgb_to_linear[$srgb] ++; + $add ++; + } + die "Too many adds at $srgb" if $add > 5; +} + +print <<"PROLOG"; +/* WARNING: This file is generated by $0. + * Please edit that file instead of this one. + */ + +#include <stdint.h> + +#include "config.h" +#include "pixman-private.h" + +PROLOG + +print "const uint8_t linear_to_srgb[" . @linear_to_srgb . "] =\n"; +print "{\n"; +for my $linear (0 .. $#linear_to_srgb) +{ + if (($linear % 10) == 0) + { + print "\t"; + } + print sprintf("%d, ", $linear_to_srgb[$linear]); + if (($linear % 10) == 9) + { + print "\n"; + } +} +print "\n};\n"; +print "\n"; + +print "const uint16_t srgb_to_linear[" . @srgb_to_linear . "] =\n"; +print "{\n"; +for my $srgb (0 .. $#srgb_to_linear) +{ + if (($srgb % 10) == 0) + { + print "\t"; + } + print sprintf("%d, ", $srgb_to_linear[$srgb]); + if (($srgb % 10) == 9) + { + print "\n"; + } +} +print "\n};\n"; + diff --git a/pixman/pixman/pixman-access.c b/pixman/pixman/pixman-access.c index 6743887d0..9feafc49d 100644 --- a/pixman/pixman/pixman-access.c +++ b/pixman/pixman/pixman-access.c @@ -32,8 +32,8 @@ #include <string.h> #include <assert.h> -#include "pixman-private.h" #include "pixman-accessor.h" +#include "pixman-private.h" #define CONVERT_RGB24_TO_Y15(s) \ (((((s) >> 16) & 0xff) * 153 + \ @@ -210,6 +210,7 @@ get_shifts (pixman_format_code_t format, break; case PIXMAN_TYPE_ARGB: + case PIXMAN_TYPE_ARGB_SRGB: *b = 0; *g = *b + PIXMAN_FORMAT_B (format); *r = *g + PIXMAN_FORMAT_G (format); @@ -1027,6 +1028,130 @@ fetch_pixel_generic_64 (bits_image_t *image, return result; } +/* The 32_sRGB paths should be deleted after narrow processing + * is no longer invoked for formats that are considered wide. + * (Also see fetch_pixel_generic_lossy_32) */ +static void +fetch_scanline_a8r8g8b8_32_sRGB (pixman_image_t *image, + int x, + int y, + int width, + uint32_t *buffer, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint32_t tmp; + + while (pixel < end) + { + tmp = READ (image, pixel++); + *buffer++ = (tmp >> 24) << 24 + | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 + | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 + | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; + } +} + +static void +fetch_scanline_a8r8g8b8_64_sRGB (pixman_image_t *image, + int x, + int y, + int width, + uint32_t *b, + const uint32_t *mask) +{ + const uint32_t *bits = image->bits.bits + y * image->bits.rowstride; + const uint32_t *pixel = (uint32_t *)bits + x; + const uint32_t *end = pixel + width; + uint64_t *buffer = (uint64_t *)b; + uint32_t tmp; + + while (pixel < end) + { + tmp = READ (image, pixel++); + *buffer++ = (uint64_t) ((tmp >> 24) * 257) << 48 + | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 + | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 + | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; + } +} + +static uint32_t +fetch_pixel_a8r8g8b8_32_sRGB (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t tmp = READ (image, bits + offset); + return (tmp >> 24) << 24 + | (srgb_to_linear[(tmp >> 16) & 0xff] >> 8) << 16 + | (srgb_to_linear[(tmp >> 8) & 0xff] >> 8) << 8 + | (srgb_to_linear[(tmp >> 0) & 0xff] >> 8) << 0; +} + +static uint64_t +fetch_pixel_a8r8g8b8_64_sRGB (bits_image_t *image, + int offset, + int line) +{ + uint32_t *bits = image->bits + line * image->rowstride; + uint32_t tmp = READ (image, bits + offset); + return (uint64_t) ((tmp >> 24) * 257) << 48 + | (uint64_t) srgb_to_linear[(tmp >> 16) & 0xff] << 32 + | (uint64_t) srgb_to_linear[(tmp >> 8) & 0xff] << 16 + | (uint64_t) srgb_to_linear[(tmp >> 0) & 0xff] << 0; +} + +static void +store_scanline_a8r8g8b8_32_sRGB (bits_image_t *image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + uint64_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + tmp = values[i]; + WRITE (image, pixel++, + ((uint32_t) (tmp >> 24 ) << 24) + | (linear_to_srgb[(tmp >> 16 << 4) & 0xfff] << 16) + | (linear_to_srgb[(tmp >> 8 << 4) & 0xfff] << 8) + | (linear_to_srgb[(tmp >> 0 << 4) & 0xfff] << 0)); + } +} + +static void +store_scanline_a8r8g8b8_64_sRGB (bits_image_t *image, + int x, + int y, + int width, + const uint32_t *v) +{ + uint32_t *bits = image->bits + image->rowstride * y; + uint64_t *values = (uint64_t *)v; + uint32_t *pixel = bits + x; + uint64_t tmp; + int i; + + for (i = 0; i < width; ++i) + { + tmp = values[i]; + WRITE (image, pixel++, + ((uint32_t) (tmp >> 56) << 24) + | (linear_to_srgb[(tmp >> 36) & 0xfff] << 16) + | (linear_to_srgb[(tmp >> 20) & 0xfff] << 8) + | (linear_to_srgb[(tmp >> 4) & 0xfff] << 0)); + } +} + /* * XXX: The transformed fetch path only works at 32-bpp so far. When all * paths have wide versions, this can be removed. @@ -1079,6 +1204,13 @@ static const format_info_t accessors[] = FORMAT_INFO (r8g8b8x8), FORMAT_INFO (x14r6g6b6), +/* sRGB formats */ + { PIXMAN_a8r8g8b8_sRGB, + fetch_scanline_a8r8g8b8_32_sRGB, + fetch_scanline_a8r8g8b8_64_sRGB, + fetch_pixel_a8r8g8b8_32_sRGB, fetch_pixel_a8r8g8b8_64_sRGB, + store_scanline_a8r8g8b8_32_sRGB, store_scanline_a8r8g8b8_64_sRGB }, + /* 24bpp formats */ FORMAT_INFO (r8g8b8), FORMAT_INFO (b8g8r8), diff --git a/pixman/pixman/pixman-image.c b/pixman/pixman/pixman-image.c index 8b634a7dc..15597bd61 100644 --- a/pixman/pixman/pixman-image.c +++ b/pixman/pixman/pixman-image.c @@ -909,7 +909,8 @@ _pixman_image_get_solid (pixman_implementation_t *imp, } /* If necessary, convert RGB <--> BGR. */ - if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB) + if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB + && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB) { result = (((result & 0xff000000) >> 0) | ((result & 0x00ff0000) >> 16) | diff --git a/pixman/pixman/pixman-private.h b/pixman/pixman/pixman-private.h index 4d8f64d3b..d5e6a72ee 100644 --- a/pixman/pixman/pixman-private.h +++ b/pixman/pixman/pixman-private.h @@ -887,7 +887,8 @@ pixman_list_move_to_front (pixman_list_t *list, pixman_link_t *link) (PIXMAN_FORMAT_A (f) > 8 || \ PIXMAN_FORMAT_R (f) > 8 || \ PIXMAN_FORMAT_G (f) > 8 || \ - PIXMAN_FORMAT_B (f) > 8) + PIXMAN_FORMAT_B (f) > 8 || \ + PIXMAN_FORMAT_TYPE (f) == PIXMAN_TYPE_ARGB_SRGB) #ifdef WORDS_BIGENDIAN # define SCREEN_SHIFT_LEFT(x,n) ((x) << (n)) @@ -1083,6 +1084,18 @@ void pixman_timer_register (pixman_timer_t *timer); #endif /* PIXMAN_TIMERS */ +/* sRGB<->linear conversion tables. Linear color space is the same + * as sRGB but the components are in linear light (gamma 1.0). + * + * linear_to_srgb maps linear value from 0 to 4095 ([0.0, 1.0]) + * and returns 8-bit sRGB value. + * + * srgb_to_linear maps 8-bit sRGB value to 16-bit linear value + * with range 0 to 65535 ([0.0, 1.0]). + */ +extern const uint8_t linear_to_srgb[4096]; +extern const uint16_t srgb_to_linear[256]; + #endif /* __ASSEMBLER__ */ #endif /* PIXMAN_PRIVATE_H */ diff --git a/pixman/pixman/pixman.c b/pixman/pixman/pixman.c index 0137c3cab..994ef388c 100644 --- a/pixman/pixman/pixman.c +++ b/pixman/pixman/pixman.c @@ -1017,6 +1017,7 @@ pixman_format_supported_source (pixman_format_code_t format) case PIXMAN_a2r10g10b10: case PIXMAN_x2r10g10b10: case PIXMAN_a8r8g8b8: + case PIXMAN_a8r8g8b8_sRGB: case PIXMAN_x8r8g8b8: case PIXMAN_a8b8g8r8: case PIXMAN_x8b8g8r8: diff --git a/pixman/pixman/pixman.h b/pixman/pixman/pixman.h index 7233ceb8a..e1cb90a7d 100644 --- a/pixman/pixman/pixman.h +++ b/pixman/pixman/pixman.h @@ -653,6 +653,7 @@ struct pixman_indexed #define PIXMAN_TYPE_YV12 7 #define PIXMAN_TYPE_BGRA 8 #define PIXMAN_TYPE_RGBA 9 +#define PIXMAN_TYPE_ARGB_SRGB 10 #define PIXMAN_FORMAT_COLOR(f) \ (PIXMAN_FORMAT_TYPE(f) == PIXMAN_TYPE_ARGB || \ @@ -676,6 +677,9 @@ typedef enum { PIXMAN_x2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,0,10,10,10), PIXMAN_a2b10g10r10 = PIXMAN_FORMAT(32,PIXMAN_TYPE_ABGR,2,10,10,10), +/* sRGB formats */ + PIXMAN_a8r8g8b8_sRGB = PIXMAN_FORMAT(32,PIXMAN_TYPE_ARGB_SRGB,8,8,8,8), + /* 24bpp formats */ PIXMAN_r8g8b8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ARGB,0,8,8,8), PIXMAN_b8g8r8 = PIXMAN_FORMAT(24,PIXMAN_TYPE_ABGR,0,8,8,8), diff --git a/pixman/test/composite.c b/pixman/test/composite.c index bdecd75a7..2930fb75b 100644 --- a/pixman/test/composite.c +++ b/pixman/test/composite.c @@ -99,6 +99,9 @@ static const format_t formats[] = P(x2b10g10r10), P(a2r10g10b10), P(a2b10g10r10), + + /* sRGB formats */ + P(a8r8g8b8_sRGB), /* 24 bpp formats */ P(r8g8b8), @@ -524,17 +527,8 @@ composite_test (image_t *dst, pixman_bool_t component_alpha, int testno) { - pixman_color_t fill; color_t expected, tdst, tsrc, tmsk; pixel_checker_t checker; - pixman_image_t *solid; - - /* Initialize dst */ - compute_pixman_color (dst->color, &fill); - solid = pixman_image_create_solid_fill (&fill); - pixman_image_composite32 (PIXMAN_OP_SRC, solid, NULL, dst->image, - 0, 0, 0, 0, 0, 0, dst->size, dst->size); - pixman_image_unref (solid); if (mask) { @@ -553,17 +547,56 @@ composite_test (image_t *dst, } tdst = *dst->color; - round_color (dst->format->format, &tdst); - tsrc = *src->color; - if (src->size) - round_color (src->format->format, &tsrc); if (mask) { tmsk = *mask->color; - if (mask->size) + } + + /* It turns out that by construction all source, mask etc. colors are + * linear because they are made from fills, and fills are always in linear + * color space. However, if they have been converted to bitmaps, we need + * to simulate the sRGB approximation to pass the test cases. + */ + if (src->size) + { + if (PIXMAN_FORMAT_TYPE (src->format->format) == PIXMAN_TYPE_ARGB_SRGB) + { + tsrc.r = convert_linear_to_srgb (tsrc.r); + tsrc.g = convert_linear_to_srgb (tsrc.g); + tsrc.b = convert_linear_to_srgb (tsrc.b); + round_color (src->format->format, &tsrc); + tsrc.r = convert_srgb_to_linear (tsrc.r); + tsrc.g = convert_srgb_to_linear (tsrc.g); + tsrc.b = convert_srgb_to_linear (tsrc.b); + } + else + { + round_color (src->format->format, &tsrc); + } + } + + if (mask && mask->size) + { + if (PIXMAN_FORMAT_TYPE (mask->format->format) == PIXMAN_TYPE_ARGB_SRGB) + { + tmsk.r = convert_linear_to_srgb (tmsk.r); + tmsk.g = convert_linear_to_srgb (tmsk.g); + tmsk.b = convert_linear_to_srgb (tmsk.b); round_color (mask->format->format, &tmsk); + tmsk.r = convert_srgb_to_linear (tmsk.r); + tmsk.g = convert_srgb_to_linear (tmsk.g); + tmsk.b = convert_srgb_to_linear (tmsk.b); + } + else + { + round_color (mask->format->format, &tmsk); + } + } + + if (mask) + { if (component_alpha && PIXMAN_FORMAT_R (mask->format->format) == 0) { /* Ax component-alpha masks expand alpha into @@ -573,6 +606,21 @@ composite_test (image_t *dst, } } + if (PIXMAN_FORMAT_TYPE (dst->format->format) == PIXMAN_TYPE_ARGB_SRGB) + { + tdst.r = convert_linear_to_srgb (tdst.r); + tdst.g = convert_linear_to_srgb (tdst.g); + tdst.b = convert_linear_to_srgb (tdst.b); + round_color (dst->format->format, &tdst); + tdst.r = convert_srgb_to_linear (tdst.r); + tdst.g = convert_srgb_to_linear (tdst.g); + tdst.b = convert_srgb_to_linear (tdst.b); + } + else + { + round_color (dst->format->format, &tdst); + } + do_composite (op->op, &tsrc, mask? &tmsk : NULL, diff --git a/pixman/test/stress-test.c b/pixman/test/stress-test.c index 9280802bd..54ab1c5a9 100644 --- a/pixman/test/stress-test.c +++ b/pixman/test/stress-test.c @@ -25,6 +25,7 @@ static const pixman_format_code_t image_formats[] = PIXMAN_x14r6g6b6, PIXMAN_r8g8b8, PIXMAN_b8g8r8, + PIXMAN_a8r8g8b8_sRGB, PIXMAN_r5g6b5, PIXMAN_b5g6r5, PIXMAN_x2r10g10b10, diff --git a/pixman/test/utils.c b/pixman/test/utils.c index 563b33d52..85b58d038 100644 --- a/pixman/test/utils.c +++ b/pixman/test/utils.c @@ -1,6 +1,7 @@ #define _GNU_SOURCE #include "utils.h" +#include <math.h> #include <signal.h> #include <stdlib.h> @@ -765,6 +766,24 @@ aligned_malloc (size_t align, size_t size) (((c) >> 8) & 0xff) * 301 + \ (((c) ) & 0xff) * 58) >> 2)) +double +convert_srgb_to_linear (double c) +{ + if (c <= 0.04045) + return c / 12.92; + else + return powf ((c + 0.055) / 1.055, 2.4); +} + +double +convert_linear_to_srgb (double c) +{ + if (c <= 0.0031308) + return c * 12.92; + else + return 1.055 * powf (c, 1.0/2.4) - 0.055; +} + void initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb) { @@ -868,6 +887,7 @@ pixel_checker_init (pixel_checker_t *checker, pixman_format_code_t format) break; case PIXMAN_TYPE_ARGB: + case PIXMAN_TYPE_ARGB_SRGB: checker->bs = 0; checker->gs = checker->bs + PIXMAN_FORMAT_B (format); checker->rs = checker->gs + PIXMAN_FORMAT_G (format); @@ -968,11 +988,25 @@ pixel_checker_get_min (const pixel_checker_t *checker, color_t *color, pixman_bool_t pixel_checker_check (const pixel_checker_t *checker, uint32_t pixel, - color_t *color) + color_t *color_in) { int32_t a_lo, a_hi, r_lo, r_hi, g_lo, g_hi, b_lo, b_hi; int32_t ai, ri, gi, bi; pixman_bool_t result; + color_t tmp, *color; + + if (PIXMAN_FORMAT_TYPE (checker->format) == PIXMAN_TYPE_ARGB_SRGB) + { + tmp.a = color_in->a; + tmp.r = convert_linear_to_srgb (color_in->r); + tmp.g = convert_linear_to_srgb (color_in->g); + tmp.b = convert_linear_to_srgb (color_in->b); + color = &tmp; + } + else + { + color = color_in; + } pixel_checker_get_min (checker, color, &a_lo, &r_lo, &g_lo, &b_lo); pixel_checker_get_max (checker, color, &a_hi, &r_hi, &g_hi, &b_hi); diff --git a/pixman/test/utils.h b/pixman/test/utils.h index ac2decd11..faf427f0a 100644 --- a/pixman/test/utils.h +++ b/pixman/test/utils.h @@ -163,6 +163,12 @@ write_png (pixman_image_t *image, const char *filename); void * aligned_malloc (size_t align, size_t size); +double +convert_srgb_to_linear (double component); + +double +convert_linear_to_srgb (double component); + void initialize_palette (pixman_indexed_t *palette, uint32_t depth, int is_rgb); |