[Pixman] [PATCH 4/8] Add support for alpha maps to compute_crc32_for_image().

Søren Sandmann sandmann at cs.au.dk
Wed May 30 16:41:41 PDT 2012


From: Søren Sandmann Pedersen <ssp at redhat.com>

When a destination image I has an alpha map A, the following rules apply:

   - If I has an alpha channel itself, the content of that channel is
     undefined

   - If A has RGB channels, the content of those channels is
     undefined.

Hence in order to compute the CRC32 for such an image, we have to mask
off the alpha channel of the image, and the RGB channels of the alpha
map.
---
 test/utils.c |   84 +++++++++++++++++++++++++++++++++++++++++++++++++---------
 1 file changed, 71 insertions(+), 13 deletions(-)

diff --git a/test/utils.c b/test/utils.c
index fcf9a36..4147adf 100644
--- a/test/utils.c
+++ b/test/utils.c
@@ -135,41 +135,99 @@ compute_crc32 (uint32_t    in_crc32,
     return (crc32 ^ 0xFFFFFFFF);
 }
 
-uint32_t
-compute_crc32_for_image (uint32_t        in_crc32,
-			 pixman_image_t *img)
+static uint32_t
+compute_crc32_for_image_internal (uint32_t        crc32,
+				  pixman_image_t *img,
+				  pixman_bool_t	  remove_alpha,
+				  pixman_bool_t	  remove_rgb)
 {
     pixman_format_code_t fmt = pixman_image_get_format (img);
     uint32_t *data = pixman_image_get_data (img);
     int stride = pixman_image_get_stride (img);
     int height = pixman_image_get_height (img);
-    uint32_t crc32;
-    
+    uint32_t mask = 0xffffffff;
+    int i;
+
     /* mask unused 'x' part */
     if (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt) &&
 	PIXMAN_FORMAT_DEPTH (fmt) != 0)
     {
-	uint32_t mask = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
-	int i;
+	uint32_t m = (1 << PIXMAN_FORMAT_DEPTH (fmt)) - 1;
 
 	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
 	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
 	{
-	    mask <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
+	    m <<= (PIXMAN_FORMAT_BPP (fmt) - PIXMAN_FORMAT_DEPTH (fmt));
+	}
+
+	mask &= m;
+    }
+
+    /* mask alpha channel */
+    if (remove_alpha && PIXMAN_FORMAT_A (fmt))
+    {
+	uint32_t m;
+
+	m = (1 << PIXMAN_FORMAT_BPP (fmt)) - 1;
+	m >>= PIXMAN_FORMAT_A (fmt);
+
+	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
+	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA ||
+	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_A)
+	{
+	    /* Alpha is at the bottom of the pixel */
+	    m <<= PIXMAN_FORMAT_A (fmt);
 	}
 
-	for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++)
-	    mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
+	mask &= m;
+    }
+
+    /* mask rgb channels */
+    if (remove_rgb && PIXMAN_FORMAT_RGB (fmt))
+    {
+	uint32_t m = ((uint32_t)~0) >> (32 - PIXMAN_FORMAT_BPP (fmt));
+	uint32_t size = PIXMAN_FORMAT_R (fmt) + PIXMAN_FORMAT_G (fmt) + PIXMAN_FORMAT_B (fmt);
+
+	m &= ~((1 << size) - 1);
 
-	for (i = 0; i < stride * height / 4; i++)
-	    data[i] &= mask;
+	if (PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_BGRA ||
+	    PIXMAN_FORMAT_TYPE (fmt) == PIXMAN_TYPE_RGBA)
+	{
+	    /* RGB channels are at the top of the pixel */
+	    m >>= size;
+	}
+
+	mask &= m;
     }
 
+    for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++)
+	mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt));
+
+    for (i = 0; i < stride * height / 4; i++)
+	data[i] &= mask;
+
     /* swap endiannes in order to provide identical results on both big
      * and litte endian systems
      */
     image_endian_swap (img);
-    crc32 = compute_crc32 (in_crc32, data, stride * height);
+
+    return compute_crc32 (crc32, data, stride * height);
+}
+
+uint32_t
+compute_crc32_for_image (uint32_t        crc32,
+			 pixman_image_t *img)
+{
+    if (img->common.alpha_map)
+    {
+	crc32 = compute_crc32_for_image_internal (crc32, img, TRUE, FALSE);
+	crc32 = compute_crc32_for_image_internal (
+	    crc32, (pixman_image_t *)img->common.alpha_map, FALSE, TRUE);
+    }
+    else
+    {
+	crc32 = compute_crc32_for_image_internal (crc32, img, FALSE, FALSE);
+    }
 
     return crc32;
 }
-- 
1.7.10.2



More information about the Pixman mailing list