From: Søren Sandmann Pedersen Date: Mon, 28 May 2012 20:14:12 +0000 (-0400) Subject: Add support for alpha maps to compute_crc32_for_image(). X-Git-Tag: pixman-0.27.2~58 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=dc9237472789b0b45393f6f7eeafa057a86280c4;p=platform%2Fupstream%2Fpixman.git Add support for alpha maps to compute_crc32_for_image(). 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. V2: Shifting by 32 is undefined in C --- diff --git a/test/utils.c b/test/utils.c index fcf9a36..0abc32c 100644 --- a/test/utils.c +++ b/test/utils.c @@ -135,41 +135,103 @@ 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)); } - for (i = 0; i * PIXMAN_FORMAT_BPP (fmt) < 32; i++) - mask |= mask << (i * PIXMAN_FORMAT_BPP (fmt)); + mask &= m; + } + + /* mask alpha channel */ + if (remove_alpha && PIXMAN_FORMAT_A (fmt)) + { + uint32_t m; + + if (PIXMAN_FORMAT_BPP (fmt) == 32) + m = 0xffffffff; + else + 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); + } + + 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); + + 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; + } - for (i = 0; i < stride * height / 4; i++) - data[i] &= mask; + 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; }