diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2008-08-20 19:37:56 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2008-08-20 23:20:09 +0100 |
commit | b47c772934571ffcabc3ec9b3468f4ef1a6d6863 (patch) | |
tree | 647fe50e04fcd4d05325438c9da9ef1cc76039d3 | |
parent | 186e7a2602cf140ac03b730b95ed10f25f9319c6 (diff) |
[test/bufferdiff] Move unused code.
Only imagediff calls png_diff, so it makes sense to move that function out
of the cairo-test and into the utility.
-rw-r--r-- | test/buffer-diff.c | 295 | ||||
-rw-r--r-- | test/buffer-diff.h | 36 | ||||
-rw-r--r-- | test/imagediff.c | 217 |
3 files changed, 216 insertions, 332 deletions
diff --git a/test/buffer-diff.c b/test/buffer-diff.c index b656b112..f37ef6e4 100644 --- a/test/buffer-diff.c +++ b/test/buffer-diff.c @@ -46,16 +46,6 @@ * claims that the images are identical */ #define PERCEPTUAL_DIFF_THRESHOLD 25 -static void -xunlink (const cairo_test_context_t *ctx, const char *pathname) -{ - if (unlink (pathname) < 0 && errno != ENOENT) { - cairo_test_log (ctx, " Error: Cannot remove %s: %s\n", - pathname, strerror (errno)); - exit (CAIRO_TEST_FAILURE); - } -} - /* Compare two buffers, returning the number of pixels that are * different and the maximum difference of any single color channel in * result_ret. @@ -202,88 +192,6 @@ buffer_diff_noalpha (const unsigned char *buf_a, result); } -static cairo_status_t -stdio_write_func (void *closure, const unsigned char *data, unsigned int length) -{ - FILE *file = closure; - - if (fwrite (data, 1, length, file) != length) - return CAIRO_STATUS_WRITE_ERROR; - - return CAIRO_STATUS_SUCCESS; -} - -/* Flatten an ARGB surface by blending it over white. The resulting - * surface, (still in ARGB32 format, but with only alpha==1.0 - * everywhere) is returned in the same surface pointer. - * - * The original surface will be destroyed. - * - * The (x,y) value specify an origin of interest for the original - * image. The flattened image will be generated only from the box - * extending from (x,y) to (width,height). - */ -static void -flatten_surface (const cairo_test_context_t *ctx, - cairo_surface_t **surface, - int x, int y) -{ - cairo_surface_t *flat; - cairo_t *cr; - - flat = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - cairo_image_surface_get_width (*surface) - x, - cairo_image_surface_get_height (*surface) - y); - cairo_surface_set_device_offset (flat, -x, -y); - - cr = cairo_create (flat); - cairo_surface_destroy (flat); - - cairo_set_source_rgb (cr, 1, 1, 1); - cairo_paint (cr); - - cairo_set_source_surface (cr, *surface, 0, 0); - cairo_surface_destroy (*surface); - cairo_paint (cr); - - *surface = cairo_surface_reference (cairo_get_target (cr)); - cairo_destroy (cr); -} - -/* Given an image surface, create a new surface that has the same - * contents as the sub-surface with its origin at x,y. - * - * The original surface will be destroyed. - */ -static void -extract_sub_surface (const cairo_test_context_t *ctx, - cairo_surface_t **surface, - int x, int y) -{ - cairo_surface_t *sub; - cairo_t *cr; - - sub = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - cairo_image_surface_get_width (*surface) - x, - cairo_image_surface_get_height (*surface) - y); - - /* We don't use a device offset like flatten_surface. That's not - * for any important reason, (the results should be - * identical). This style just seemed more natural to me this - * time, so I'm leaving both here so I can look at both to see - * which I like better. */ - cr = cairo_create (sub); - cairo_surface_destroy (sub); - - cairo_set_source_surface (cr, *surface, -x, -y); - cairo_surface_destroy (*surface); - cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); - cairo_paint (cr); - - *surface = cairo_surface_reference (cairo_get_target (cr)); - cairo_destroy (cr); -} - static cairo_bool_t same_size (cairo_surface_t *a, cairo_surface_t *b) { @@ -341,206 +249,3 @@ image_diff (const cairo_test_context_t *ctx, return CAIRO_STATUS_SUCCESS; } - -static cairo_status_t -write_png (cairo_surface_t *surface, const char *filename) -{ - cairo_status_t status; - FILE *png_file; - - if (filename != NULL) { - png_file = fopen (filename, "wb"); - if (png_file == NULL) { - switch (errno) { - case ENOMEM: - return CAIRO_STATUS_NO_MEMORY; - default: - return CAIRO_STATUS_WRITE_ERROR; - } - } - } else - png_file = stdout; - - status = cairo_surface_write_to_png_stream (surface, - stdio_write_func, - png_file); - - if (png_file != stdout) - fclose (png_file); - - return status; -} - - - -cairo_status_t -png_diff (const cairo_test_context_t *ctx, - const char *filename_a, - const char *filename_b, - const char *filename_diff, - int ax, - int ay, - int bx, - int by, - buffer_diff_result_t *result) -{ - cairo_surface_t *surface_a; - cairo_surface_t *surface_b; - cairo_surface_t *surface_diff; - cairo_status_t status; - - surface_a = cairo_image_surface_create_from_png (filename_a); - status = cairo_surface_status (surface_a); - if (status) { - cairo_test_log (ctx, "Error: Failed to create surface from %s: %s\n", - filename_a, cairo_status_to_string (status)); - return status; - } - - surface_b = cairo_image_surface_create_from_png (filename_b); - status = cairo_surface_status (surface_b); - if (status) { - cairo_test_log (ctx, "Error: Failed to create surface from %s: %s\n", - filename_b, cairo_status_to_string (status)); - cairo_surface_destroy (surface_a); - return status; - } - - if (ax || ay) { - extract_sub_surface (ctx, &surface_a, ax, ay); - ax = ay = 0; - } - - if (bx || by) { - extract_sub_surface (ctx, &surface_b, bx, by); - bx = by = 0; - } - - status = cairo_surface_status (surface_a); - if (status) { - cairo_test_log (ctx, "Error: Failed to extract surface from %s: %s\n", - filename_a, cairo_status_to_string (status)); - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - return status; - } - status = cairo_surface_status (surface_b); - if (status) { - cairo_test_log (ctx, "Error: Failed to extract surface from %s: %s\n", - filename_b, cairo_status_to_string (status)); - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - return status; - } - - surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - cairo_image_surface_get_width (surface_a), - cairo_image_surface_get_height (surface_a)); - status = cairo_surface_status (surface_diff); - if (status) { - cairo_test_log (ctx, "Error: Failed to allocate surface to hold differences\n"); - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - return CAIRO_STATUS_NO_MEMORY; - } - - status = image_diff (ctx, - surface_a, surface_b, surface_diff, - result); - - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - cairo_surface_destroy (surface_diff); - - xunlink (ctx, filename_diff); - if (status == CAIRO_STATUS_SUCCESS && - result->pixels_changed) - { - status = write_png (surface_diff, filename_diff); - } - - - return status; -} - -cairo_status_t -png_diff_flattened (const cairo_test_context_t *ctx, - const char *filename_a, - const char *filename_b, - const char *filename_diff, - int ax, - int ay, - int bx, - int by, - buffer_diff_result_t *result) -{ - cairo_surface_t *surface_a; - cairo_surface_t *surface_b; - cairo_surface_t *surface_diff; - cairo_status_t status; - - surface_a = cairo_image_surface_create_from_png (filename_a); - status = cairo_surface_status (surface_a); - if (status) { - cairo_test_log (ctx, "Error: Failed to create surface from %s: %s\n", - filename_a, cairo_status_to_string (status)); - return status; - } - - surface_b = cairo_image_surface_create_from_png (filename_b); - status = cairo_surface_status (surface_b); - if (status) { - cairo_test_log (ctx, "Error: Failed to create surface from %s: %s\n", - filename_b, cairo_status_to_string (status)); - cairo_surface_destroy (surface_a); - return status; - } - - flatten_surface (ctx, &surface_a, ax, ay); - flatten_surface (ctx, &surface_b, bx, by); - - status = cairo_surface_status (surface_a); - if (status) { - cairo_test_log (ctx, "Error: Failed to extract surface from %s: %s\n", - filename_a, cairo_status_to_string (status)); - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - return status; - } - status = cairo_surface_status (surface_b); - if (status) { - cairo_test_log (ctx, "Error: Failed to extract surface from %s: %s\n", - filename_b, cairo_status_to_string (status)); - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - return status; - } - - surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - cairo_image_surface_get_width (surface_a), - cairo_image_surface_get_height (surface_a)); - status = cairo_surface_status (surface_diff); - if (status) { - cairo_test_log (ctx, "Error: Failed to allocate surface to hold differences\n"); - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - return CAIRO_STATUS_NO_MEMORY; - } - - status = image_diff (ctx, - surface_a, surface_b, surface_diff, - result); - - xunlink (ctx, filename_diff); - if (status == CAIRO_STATUS_SUCCESS && - result->pixels_changed) - { - status = write_png (surface_diff, filename_diff); - } - - cairo_surface_destroy (surface_a); - cairo_surface_destroy (surface_b); - cairo_surface_destroy (surface_diff); - - return status; -} diff --git a/test/buffer-diff.h b/test/buffer-diff.h index 64bce920..c09bc646 100644 --- a/test/buffer-diff.h +++ b/test/buffer-diff.h @@ -53,42 +53,6 @@ buffer_diff_noalpha (const unsigned char *buf_a, int stride, buffer_diff_result_t *result); -/* Compares two image buffers ignoring the alpha channel. A return - * value of CAIRO_STATUS_SUCCESS indicates that a comparison was made, - * (but the images may or may not differ). Failure modes include - * CAIRO_STATUS_FILE_NOT_FOUND, CAIRO_STATUS_READ_ERROR, - * CAIRO_STATUS_NO_MEMORY, and CAIRO_STATUS_SURFACE_TYPE_MISMATCH - * (which is used if the image sizes differ). - * - * Provides number of pixels changed and maximum single-channel - * difference in result. - * - * Also saves a "diff" image intended to visually show where the - * images differ. - */ -cairo_status_t -png_diff (const cairo_test_context_t *ctx, - const char *filename_a, - const char *filename_b, - const char *filename_diff, - int ax, - int ay, - int bx, - int by, - buffer_diff_result_t *result); - -/* Like png_diff, but blending the contents of b over white first. */ -cairo_status_t -png_diff_flattened (const cairo_test_context_t *ctx, - const char *filename_a, - const char *filename_b, - const char *filename_diff, - int ax, - int ay, - int bx, - int by, - buffer_diff_result_t *result); - /* The central algorithm to compare two images, and return the differences * in the surface_diff. * diff --git a/test/imagediff.c b/test/imagediff.c index 64042426..73e46292 100644 --- a/test/imagediff.c +++ b/test/imagediff.c @@ -23,12 +23,227 @@ * * Author: Richard D. Worth <richard@theworths.org> */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include <stdio.h> #include <stdlib.h> +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif +#include <errno.h> #include "buffer-diff.h" #include "xmalloc.h" +static void +_xunlink (const char *pathname) +{ + if (unlink (pathname) < 0 && errno != ENOENT) { + fprintf (stderr, " Error: Cannot remove %s: %s\n", + pathname, strerror (errno)); + exit (1); + } +} + +/* Flatten an ARGB surface by blending it over white. The resulting + * surface, (still in ARGB32 format, but with only alpha==1.0 + * everywhere) is returned in the same surface pointer. + * + * The original surface will be destroyed. + * + * The (x,y) value specify an origin of interest for the original + * image. The flattened image will be generated only from the box + * extending from (x,y) to (width,height). + */ +static void +flatten_surface (cairo_surface_t **surface, int x, int y) +{ + cairo_surface_t *flat; + cairo_t *cr; + + flat = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + cairo_image_surface_get_width (*surface) - x, + cairo_image_surface_get_height (*surface) - y); + cairo_surface_set_device_offset (flat, -x, -y); + + cr = cairo_create (flat); + cairo_surface_destroy (flat); + + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + + cairo_set_source_surface (cr, *surface, 0, 0); + cairo_surface_destroy (*surface); + cairo_paint (cr); + + *surface = cairo_surface_reference (cairo_get_target (cr)); + cairo_destroy (cr); +} + +/* Given an image surface, create a new surface that has the same + * contents as the sub-surface with its origin at x,y. + * + * The original surface will be destroyed. + */ +static void +extract_sub_surface (cairo_surface_t **surface, int x, int y) +{ + cairo_surface_t *sub; + cairo_t *cr; + + sub = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + cairo_image_surface_get_width (*surface) - x, + cairo_image_surface_get_height (*surface) - y); + + /* We don't use a device offset like flatten_surface. That's not + * for any important reason, (the results should be + * identical). This style just seemed more natural to me this + * time, so I'm leaving both here so I can look at both to see + * which I like better. */ + cr = cairo_create (sub); + cairo_surface_destroy (sub); + + cairo_set_source_surface (cr, *surface, -x, -y); + cairo_surface_destroy (*surface); + cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); + cairo_paint (cr); + + *surface = cairo_surface_reference (cairo_get_target (cr)); + cairo_destroy (cr); +} + +static cairo_status_t +stdio_write_func (void *closure, const unsigned char *data, unsigned int length) +{ + FILE *file = closure; + + if (fwrite (data, 1, length, file) != length) + return CAIRO_STATUS_WRITE_ERROR; + + return CAIRO_STATUS_SUCCESS; +} + +static cairo_status_t +write_png (cairo_surface_t *surface, const char *filename) +{ + cairo_status_t status; + FILE *png_file; + + if (filename != NULL) { + png_file = fopen (filename, "wb"); + if (png_file == NULL) { + switch (errno) { + case ENOMEM: + return CAIRO_STATUS_NO_MEMORY; + default: + return CAIRO_STATUS_WRITE_ERROR; + } + } + } else + png_file = stdout; + + status = cairo_surface_write_to_png_stream (surface, + stdio_write_func, + png_file); + + if (png_file != stdout) + fclose (png_file); + + return status; +} + +static cairo_status_t +png_diff (const char *filename_a, + const char *filename_b, + const char *filename_diff, + int ax, + int ay, + int bx, + int by, + buffer_diff_result_t *result) +{ + cairo_surface_t *surface_a; + cairo_surface_t *surface_b; + cairo_surface_t *surface_diff; + cairo_status_t status; + + surface_a = cairo_image_surface_create_from_png (filename_a); + status = cairo_surface_status (surface_a); + if (status) { + fprintf (stderr, "Error: Failed to create surface from %s: %s\n", + filename_a, cairo_status_to_string (status)); + return status; + } + + surface_b = cairo_image_surface_create_from_png (filename_b); + status = cairo_surface_status (surface_b); + if (status) { + fprintf (stderr, "Error: Failed to create surface from %s: %s\n", + filename_b, cairo_status_to_string (status)); + cairo_surface_destroy (surface_a); + return status; + } + + if (ax || ay) { + extract_sub_surface (&surface_a, ax, ay); + ax = ay = 0; + } + + if (bx || by) { + extract_sub_surface (&surface_b, bx, by); + bx = by = 0; + } + + status = cairo_surface_status (surface_a); + if (status) { + fprintf (stderr, "Error: Failed to extract surface from %s: %s\n", + filename_a, cairo_status_to_string (status)); + cairo_surface_destroy (surface_a); + cairo_surface_destroy (surface_b); + return status; + } + status = cairo_surface_status (surface_b); + if (status) { + fprintf (stderr, "Error: Failed to extract surface from %s: %s\n", + filename_b, cairo_status_to_string (status)); + cairo_surface_destroy (surface_a); + cairo_surface_destroy (surface_b); + return status; + } + + surface_diff = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + cairo_image_surface_get_width (surface_a), + cairo_image_surface_get_height (surface_a)); + status = cairo_surface_status (surface_diff); + if (status) { + fprintf (stderr, + "Error: Failed to allocate surface to hold differences\n"); + cairo_surface_destroy (surface_a); + cairo_surface_destroy (surface_b); + return CAIRO_STATUS_NO_MEMORY; + } + + status = image_diff (NULL, + surface_a, surface_b, surface_diff, + result); + + cairo_surface_destroy (surface_a); + cairo_surface_destroy (surface_b); + cairo_surface_destroy (surface_diff); + + _xunlink (filename_diff); + if (status == CAIRO_STATUS_SUCCESS && + result->pixels_changed) + { + status = write_png (surface_diff, filename_diff); + } + + + return status; +} + int main (int argc, char *argv[]) { @@ -54,7 +269,7 @@ main (int argc, char *argv[]) ax = ay = bx = by = 0; } - status = png_diff (NULL, argv[1], argv[2], NULL, ax, ay, bx, by, &result); + status = png_diff (argv[1], argv[2], NULL, ax, ay, bx, by, &result); if (status) { fprintf (stderr, "Error comparing images: %s\n", |