[PATCH weston 11/11] tests: implement visualize_image_difference()
Pekka Paalanen
ppaalanen at gmail.com
Thu Jun 16 14:13:30 UTC 2016
From: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
Useful for pointing out where the image comparisons fail.
Internal-screenshot-test is modified to save the visualization if the
test fails.
Signed-off-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
tests/internal-screenshot-test.c | 7 +++
tests/weston-test-client-helper.c | 99 +++++++++++++++++++++++++++++++++++++++
tests/weston-test-client-helper.h | 4 ++
3 files changed, 110 insertions(+)
diff --git a/tests/internal-screenshot-test.c b/tests/internal-screenshot-test.c
index 3507d11..b8f6ffe 100644
--- a/tests/internal-screenshot-test.c
+++ b/tests/internal-screenshot-test.c
@@ -68,6 +68,7 @@ TEST(internal_screenshot)
struct buffer *screenshot = NULL;
pixman_image_t *reference_good = NULL;
pixman_image_t *reference_bad = NULL;
+ pixman_image_t *diffimg;
struct rectangle clip;
const char *fname;
bool match = false;
@@ -121,6 +122,12 @@ TEST(internal_screenshot)
printf("Clip: %d,%d %d x %d\n", clip.x, clip.y, clip.width, clip.height);
match = check_images_match(screenshot->image, reference_good, &clip);
printf("Screenshot %s reference image in clipped area\n", match? "matches" : "doesn't match");
+ if (!match) {
+ diffimg = visualize_image_difference(screenshot->image, reference_good, &clip);
+ fname = screenshot_output_filename("internal-screenshot-error", 0);
+ write_image_as_png(diffimg, fname);
+ pixman_image_unref(diffimg);
+ }
pixman_image_unref(reference_good);
/* Test dumping of non-matching images */
diff --git a/tests/weston-test-client-helper.c b/tests/weston-test-client-helper.c
index 421edb9..1056f41 100644
--- a/tests/weston-test-client-helper.c
+++ b/tests/weston-test-client-helper.c
@@ -1130,6 +1130,105 @@ check_images_match(pixman_image_t *img_a, pixman_image_t *img_b,
}
/**
+ * Tint a color
+ *
+ * \param src Source pixel as x8r8g8b8.
+ * \param add The tint as x8r8g8b8, x8 must be zero; r8, g8 and b8 must be
+ * no greater than 0xc0 to avoid overflow to another channel.
+ * \return The tinted pixel color as x8r8g8b8, x8 guaranteed to be 0xff.
+ *
+ * The source pixel RGB values are divided by 4, and then the tint is added.
+ * To achieve colors outside of the range of src, a tint color channel must be
+ * at least 0x40. (0xff / 4 = 0x3f, 0xff - 0x3f = 0xc0)
+ */
+static uint32_t
+tint(uint32_t src, uint32_t add)
+{
+ uint32_t v;
+
+ v = ((src & 0xfcfcfcfc) >> 2) | 0xff000000;
+
+ return v + add;
+}
+
+/**
+ * Create a visualization of image differences.
+ *
+ * \param img_a First image, which is used as the basis for the output.
+ * \param img_b Second image.
+ * \param clip_rect The region of interest, or NULL for comparing the whole
+ * images.
+ * \return A new image with the differences highlighted.
+ *
+ * Regions outside of the region of interest are shaded with black, matching
+ * pixels are shaded with green, and differing pixels are shaded with
+ * bright red.
+ *
+ * This function hard-fails if clip_rect is not inside both images. If clip_rect
+ * is given, the images do not have to match in size, otherwise size mismatch
+ * will be a hard failure.
+ */
+pixman_image_t *
+visualize_image_difference(pixman_image_t *img_a, pixman_image_t *img_b,
+ const struct rectangle *clip_rect)
+{
+ pixman_image_t *diffimg;
+ pixman_image_t *shade;
+ struct image_iterator it_a;
+ struct image_iterator it_b;
+ struct image_iterator it_d;
+ int width;
+ int height;
+ pixman_box32_t box;
+ int x, y;
+ uint32_t *pix_a;
+ uint32_t *pix_b;
+ uint32_t *pix_d;
+ pixman_color_t shade_color = { 0, 0, 0, 32768 };
+
+ width = pixman_image_get_width(img_a);
+ height = pixman_image_get_height(img_a);
+ box = image_check_get_roi(img_a, img_b, clip_rect);
+
+ diffimg = pixman_image_create_bits_no_clear(PIXMAN_x8r8g8b8,
+ width, height, NULL, 0);
+
+ /* Fill diffimg with a black-shaded copy of img_a, and then fill
+ * the clip_rect area with original img_a.
+ */
+ shade = pixman_image_create_solid_fill(&shade_color);
+ pixman_image_composite32(PIXMAN_OP_SRC, img_a, shade, diffimg,
+ 0, 0, 0, 0, 0, 0, width, height);
+ pixman_image_unref(shade);
+ pixman_image_composite32(PIXMAN_OP_SRC, img_a, NULL, diffimg,
+ box.x1, box.y1, 0, 0, box.x1, box.y1,
+ box.x2 - box.x1, box.y2 - box.y1);
+
+ image_iter_init(&it_a, img_a);
+ image_iter_init(&it_b, img_b);
+ image_iter_init(&it_d, diffimg);
+
+ for (y = box.y1; y < box.y2; y++) {
+ pix_a = image_iter_get_row(&it_a, y) + box.x1;
+ pix_b = image_iter_get_row(&it_b, y) + box.x1;
+ pix_d = image_iter_get_row(&it_d, y) + box.x1;
+
+ for (x = box.x1; x < box.x2; x++) {
+ if (*pix_a == *pix_b)
+ *pix_d = tint(*pix_d, 0x00008000); /* green */
+ else
+ *pix_d = tint(*pix_d, 0x00c00000); /* red */
+
+ pix_a++;
+ pix_b++;
+ pix_d++;
+ }
+ }
+
+ return diffimg;
+}
+
+/**
* Write an image into a PNG file.
*
* \param image The image.
diff --git a/tests/weston-test-client-helper.h b/tests/weston-test-client-helper.h
index 794abb3..d6ecb5f 100644
--- a/tests/weston-test-client-helper.h
+++ b/tests/weston-test-client-helper.h
@@ -201,6 +201,10 @@ bool
check_images_match(pixman_image_t *img_a, pixman_image_t *img_b,
const struct rectangle *clip);
+pixman_image_t *
+visualize_image_difference(pixman_image_t *img_a, pixman_image_t *img_b,
+ const struct rectangle *clip_rect);
+
bool
write_image_as_png(pixman_image_t *image, const char *fname);
--
2.7.3
More information about the wayland-devel
mailing list