[cairo] [PATCH 1/2] buffer_diff rewrite

Jeff Muizelaar jeff at infidigm.net
Thu Aug 4 19:13:10 PDT 2005


The following patch replaces buffer_diff with buffer_diff_core.
buffer_diff_core is a rewrite of the original buffer_diff in a endian
safe maner and with a comparison mask parameter.

The patch also creates two wrappers around the new buffer_diff_core
function. buffer_diff, which is the same as the old buffer_diff function
and buffer_diff_noalpha which ignores the alpha channel when comparing. 

I also changed the api documentation to reflect the fact that
buffer_diff never returns -1 on error.


Index: test/buffer-diff.c
===================================================================
RCS file: /cvs/cairo/cairo/test/buffer-diff.c,v
retrieving revision 1.6
diff -u -r1.6 buffer-diff.c
--- test/buffer-diff.c	15 Jul 2005 17:39:59 -0000	1.6
+++ test/buffer-diff.c	5 Aug 2005 01:51:10 -0000
@@ -27,6 +27,7 @@
 #include <unistd.h>
 #include <errno.h>
 #include <string.h>
+#include <pixman.h>
 
 #include "cairo-test.h"
 
@@ -45,18 +46,23 @@
     }
 }
 
-int
-buffer_diff (unsigned char *buf_a,
-	     unsigned char *buf_b,
-	     unsigned char *buf_diff,
-	     int	    width,
-	     int	    height,
-	     int	    stride)
+static int
+buffer_diff_core (unsigned char *_buf_a,
+		  unsigned char *_buf_b,
+		  unsigned char *_buf_diff,
+		  int		width,
+		  int		height,
+		  int		stride,
+		  pixman_bits_t mask)
 {
     int x, y;
-    unsigned char *row_a, *row_b, *row;
+    pixman_bits_t *row_a, *row_b, *row;
     int pixels_changed = 0;
+    pixman_bits_t *buf_a = (pixman_bits_t*)_buf_a;
+    pixman_bits_t *buf_b = (pixman_bits_t*)_buf_b;
+    pixman_bits_t *buf_diff = (pixman_bits_t*)_buf_diff;
 
+    stride /= sizeof(pixman_bits_t);
     for (y = 0; y < height; y++)
     {
 	row_a = buf_a + y * stride;
@@ -64,33 +70,54 @@
 	row = buf_diff + y * stride;
 	for (x = 0; x < width; x++)
 	{
-	    int channel;
-	    unsigned char value_a, value_b;
-	    int pixel_differs = 0;
-	    for (channel = 0; channel < 4; channel++)
-	    {
-		double diff;
-		value_a = row_a[x * 4 + channel];
-		value_b = row_b[x * 4 + channel];
-		if (value_a != value_b)
-		    pixel_differs = 1;
-		diff = value_a - value_b;
-		row[x * 4 + channel] = 128 + diff / 3.0;
-	    }
-	    if (pixel_differs) {
+	    /* check if the pixels are the same */
+	    if ((row_a[x] & mask) != (row_b[x] & mask)) {
+		int channel;
+		pixman_bits_t diff_pixel = 0;
+
+		/* calculate a difference value for all 4 channels */
+		for (channel = 0; channel < 4; channel++) {
+		    unsigned char value_a = (row_a[x] >> (channel*8));
+		    unsigned char value_b = (row_b[x] >> (channel*8));
+		    double diff;
+		    diff = value_a - value_b;
+		    diff_pixel |= (unsigned char)(128 + diff / 3.0) << (channel*8);
+		}
+
 		pixels_changed++;
+		row[x] = diff_pixel;
 	    } else {
-		row[x*4+0] = 0;
-		row[x*4+1] = 0;
-		row[x*4+2] = 0;
+		row[x] = 0;
 	    }
-	    row[x * 4 + 3] = 0xff; /* Set ALPHA to 100% (opaque) */
+	    row[x] |= 0xff000000; /* Set ALPHA to 100% (opaque) */
 	}
     }
 
     return pixels_changed;
 }
 
+int
+buffer_diff (unsigned char *buf_a,
+	     unsigned char *buf_b,
+	     unsigned char *buf_diff,
+	     int	   width,
+	     int	   height,
+	     int	   stride)
+{
+    return buffer_diff_core(buf_a, buf_b, buf_diff, width, height, stride, 0xffffffff);
+}
+
+int
+buffer_diff_noalpha (unsigned char *buf_a,
+		     unsigned char *buf_b,
+		     unsigned char *buf_diff,
+		     int	   width,
+		     int	   height,
+		     int	   stride)
+{
+    return buffer_diff_core(buf_a, buf_b, buf_diff, width, height, stride, 0x00ffffff);
+}
+
 /* Image comparison code courtesy of Richard Worth <richard at theworths.org>
  * Returns number of pixels changed, (or -1 on error).
  * Also saves a "diff" image intended to visually show where the
Index: test/buffer-diff.h
===================================================================
RCS file: /cvs/cairo/cairo/test/buffer-diff.h,v
retrieving revision 1.3
diff -u -r1.3 buffer-diff.h
--- test/buffer-diff.h	27 Apr 2005 20:33:25 -0000	1.3
+++ test/buffer-diff.h	5 Aug 2005 01:51:10 -0000
@@ -26,7 +26,7 @@
 #ifndef BUFFER_DIFF_H
 #define BUFFER_DIFF_H
 
-/* Returns number of pixels changed, (or -1 on error).
+/* Returns number of pixels changed.
  * Also fills in a "diff" buffer intended to visually show where the
  * images differ.
  */
@@ -38,6 +38,18 @@
 	     int	    height,
 	     int	    stride);
 
+/* Returns number of pixels changed ignoring the alpha channel.
+ * Also fills in a "diff" buffer intended to visually show where the
+ * images differ.
+ */
+int
+buffer_diff_noalpha (unsigned char *buf_a,
+		     unsigned char *buf_b,
+		     unsigned char *buf_diff,
+		     int	    width,
+		     int	    height,
+		     int	    stride);
+
 /* Returns number of pixels changed, (or -1 on error).
  * Also saves a "diff" image intended to visually show where the
  * images differ.



More information about the cairo mailing list