From a161a6ba2394aed68148304de83b8f2c185f4c32 Mon Sep 17 00:00:00 2001 From: "Antti S. Lankila" Date: Sun, 29 Jul 2012 21:56:18 +0300 Subject: [PATCH] Add sRGB blending demo program Simple sRGB color blender test can be used to determine if the sRGB processing works as expected. It blends alpha ramps of purple and green together such that at midpoint of image, 50 % blend of both is realized. At that point, sRGB-aware processing yields a result close to #bbb rather than #888, which is the linear light blending result. The demo also contains the sample computation for sRGB premultiplied alpha. --- .gitignore | 1 + demos/Makefile.am | 4 ++- demos/srgb-test.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 demos/srgb-test.c diff --git a/.gitignore b/.gitignore index 3cdf3c1..a4d9f99 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ demos/gradient-test demos/quad2quad demos/radial-test demos/screen-test +demos/srgb-test demos/trap-test demos/tri-test pixman/pixman-combine32.c diff --git a/demos/Makefile.am b/demos/Makefile.am index 9aac1f5..d8fb0da 100644 --- a/demos/Makefile.am +++ b/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/demos/srgb-test.c b/demos/srgb-test.c new file mode 100644 index 0000000..bc07349 --- /dev/null +++ b/demos/srgb-test.c @@ -0,0 +1,96 @@ +#include + +#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; +} -- 2.7.4