Add sRGB blending demo program
authorAntti S. Lankila <alankila@bel.fi>
Sun, 29 Jul 2012 18:56:18 +0000 (21:56 +0300)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Mon, 30 Jul 2012 19:40:16 +0000 (15:40 -0400)
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
demos/Makefile.am
demos/srgb-test.c [new file with mode: 0644]

index 3cdf3c1..a4d9f99 100644 (file)
@@ -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
index 9aac1f5..d8fb0da 100644 (file)
@@ -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 (file)
index 0000000..bc07349
--- /dev/null
@@ -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;
+}