[gs-commits] rev 10929 - trunk/gs/toolbin

robin at ghostscript.com robin at ghostscript.com
Wed Mar 17 17:30:27 UTC 2010


Author: robin
Date: 2010-03-17 17:30:27 +0000 (Wed, 17 Mar 2010)
New Revision: 10929

Modified:
   trunk/gs/toolbin/bmpcmp.c
Log:
Revised bmpcmp.
 * Redone command line handling
 * Ability to read PAMs (so we can read CMYK stuff now)
 * "Fuzzy" behaviour (both compatible and exhaustive modes)
 * New behaviour using map bitmap to avoid rediffing multiple times.
 * CMYK -> RGB conversion as last step before PNG/BMP writing.

Still to do:
 * Output number of fuzzy matches etc to the meta file.



Modified: trunk/gs/toolbin/bmpcmp.c
===================================================================
--- trunk/gs/toolbin/bmpcmp.c	2010-03-15 19:18:55 UTC (rev 10928)
+++ trunk/gs/toolbin/bmpcmp.c	2010-03-17 17:30:27 UTC (rev 10929)
@@ -5,33 +5,97 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stddef.h>
 #include <ctype.h>
 
 #ifdef HAVE_LIBPNG
 #include <png.h>
 #endif
 
+/* Values in map field:
+ *
+ *  0 means Completely unchanged pixel
+ *  Bit 0 set means: Pixel is not an exact 1:1 match with original.
+ *  Bit 1,2,3 set means: Pixel does not match with another within the window.
+ *
+ * In detail mode:
+ *  0 means Completely unchanged pixel
+ *  Bit 0 set means: Pixel is not an exact 1:1 match with original.
+ *  Bit 1 set means: Pixel does not match exactly with another within the
+ *                   window.
+ *  Bit 2 set means: Pixel is not a thresholded match with original.
+ *  Bit 3 set means: Pixel is not a thresholded match with another within the
+ *                   window.
+ *
+ * Colors:
+ *   0 => Greyscale  Unchanged pixel
+ *   1 => Green      Translated within window
+ *   3 => Cyan       Thresholded match (no translation)
+ *   5 => Yellow     Both Exact translated, and Thresholded match
+ *   7 => Orange     Thresholded match
+ *   15=> Red        No Match
+ */
+
 #define MINX (300)
 #define MINY (320)
 #define MAXX (600)
 #define MAXY (960)
 
-typedef struct {
+typedef struct
+{
     int xmin;
     int ymin;
     int xmax;
     int ymax;
 } BBox;
 
+typedef struct
+{
+    /* Read from the command line */
+    int   window;
+    int   threshold;
+    int   exhaustive;
+    int   basenum;
+    int   maxdiffs;
+    char *filename1;
+    char *filename2;
+    char *outroot;
+    /* Fuzzy table */
+    int   wTabLen;
+    int  *wTab;
+    /* Image details */
+    int   width;
+    int   height;
+    int   span;
+    int   bpp;
+} Params;
+
 typedef struct ImageReader
 {
-  FILE *file;
-  void *(*read)(struct ImageReader *, int *w, int *h, int *s, int *bpp);
+    FILE *file;
+    void *(*read)(struct ImageReader *,
+                  int                *w,
+                  int                *h,
+                  int                *s,
+                  int                *bpp,
+                  int                *cmyk);
 } ImageReader;
 
+/*
+ * Generic diff function type. Diff bmp and bmp2, both of geometry (width,
+ * height, span (bytes), bpp). Return the changed bbox area in bbox.
+ * Make a map of changes in map
+ */
+typedef void (DiffFn)(unsigned char *bmp,
+                      unsigned char *bmp2,
+                      unsigned char *map,
+                      BBox          *bbox,
+                      Params        *params);
+
+
 static void *Malloc(size_t size) {
     void *block;
-    
+
     block = malloc(size);
     if (block == NULL) {
         fprintf(stderr, "Failed to malloc %u bytes\n", (unsigned int)size);
@@ -279,18 +343,22 @@
                       int         *width,
                       int         *height,
                       int         *span,
-                      int         *bpp)
+                      int         *bpp,
+                      int         *cmyk)
 {
     int            offset;
     long           filelen, filepos;
     unsigned char *data;
     unsigned char *bmp;
 
+    /* No CMYK bmp support */
+    *cmyk = 0;
+
     filepos = ftell(im->file);
     fseek(im->file, 0, SEEK_END);
     filelen = ftell(im->file);
     fseek(im->file, 0, SEEK_SET);
-    
+
     /* If we were at the end to start, then we'd read our one and only
      * image. */
     if (filepos == filelen)
@@ -306,18 +374,27 @@
     return data;
 }
 
+static void skip_to_eol(FILE *file)
+{
+    int c;
+
+    do
+    {
+        c = fgetc(file);
+    }
+    while ((c != EOF) && (c != '\n') && (c != '\r'));
+}
+
 static int get_uncommented_char(FILE *file)
 {
     int c;
-    
+
     do
     {
         c = fgetc(file);
         if (c != '#')
             return c;
-        do {
-            c = fgetc(file);
-        } while ((c != EOF) && (c != '\n') && (c != '\r'));
+        skip_to_eol(file);
     }
     while (c != EOF);
 
@@ -328,19 +405,19 @@
 {
     int c;
     int val = 0;
-    
+
     /* Skip over any whitespace */
     do {
         c = get_uncommented_char(file);
     } while (isspace(c));
-    
+
     /* Read the number */
     while (isdigit(c))
     {
         val = val*10 + c - '0';
         c = get_uncommented_char(file);
     }
-    
+
     /* assume the last c is whitespace */
     return val;
 }
@@ -353,9 +430,9 @@
 {
     int w;
     int byte, mask, g;
-    
+
     bmp += width*(height-1)<<2;
-    
+
     for (; height>0; height--) {
         mask = 0;
         for (w=width; w>0; w--) {
@@ -385,9 +462,9 @@
                      unsigned char *bmp)
 {
     int w;
-    
+
     bmp += width*(height-1)<<2;
-    
+
     if (maxval == 255)
     {
         for (; height>0; height--) {
@@ -435,7 +512,7 @@
     int w;
 
     bmp += width*(height-1)<<2;
-    
+
     if (maxval == 255)
     {
         for (; height>0; height--) {
@@ -479,6 +556,63 @@
     }
 }
 
+static void pam_read(FILE          *file,
+                     int            width,
+                     int            height,
+                     int            maxval,
+                     unsigned char *bmp)
+{
+    int c,m,y,k;
+    int w;
+
+    bmp += width*(height-1)<<2;
+
+    if (maxval == 255)
+    {
+        for (; height>0; height--) {
+            for (w=width; w>0; w--) {
+                c = fgetc(file);
+                m = fgetc(file);
+                y = fgetc(file);
+                k = fgetc(file);
+                *bmp++ = c;
+                *bmp++ = m;
+                *bmp++ = y;
+                *bmp++ = k;
+            }
+            bmp -= width<<3;
+        }
+    } else if (maxval < 255) {
+        for (; height>0; height--) {
+            for (w=width; w>0; w--) {
+                c = fgetc(file)*255/maxval;
+                m = fgetc(file)*255/maxval;
+                y = fgetc(file)*255/maxval;
+                k = fgetc(file)*255/maxval;
+                *bmp++ = c;
+                *bmp++ = m;
+                *bmp++ = y;
+                *bmp++ = k;
+            }
+            bmp -= width<<3;
+        }
+    } else {
+        for (; height>0; height--) {
+            for (w=width; w>0; w--) {
+                c = ((fgetc(file)<<8) + (fgetc(file)))*255/maxval;
+                m = ((fgetc(file)<<8) + (fgetc(file)))*255/maxval;
+                y = ((fgetc(file)<<8) + (fgetc(file)))*255/maxval;
+                k = ((fgetc(file)<<8) + (fgetc(file)))*255/maxval;
+                *bmp++ = c;
+                *bmp++ = m;
+                *bmp++ = y;
+                *bmp++ = k;
+            }
+            bmp -= width<<3;
+        }
+    }
+}
+
 static void pbm_read_plain(FILE          *file,
                            int            width,
                            int            height,
@@ -487,9 +621,9 @@
 {
     int w;
     int g;
-    
+
     bmp += width*(height-1)<<2;
-    
+
     for (; height>0; height--) {
         for (w=width; w>0; w--) {
             g = get_pnm_num(file);
@@ -511,9 +645,9 @@
                            unsigned char *bmp)
 {
     int w;
-    
+
     bmp += width*(height-1)<<2;
-    
+
     if (maxval == 255)
     {
         for (; height>0; height--) {
@@ -548,9 +682,9 @@
 {
     int r,g,b;
     int w;
-    
+
     bmp += width*(height-1)<<2;
-    
+
     if (maxval == 255)
     {
         for (; height>0; height--) {
@@ -583,11 +717,72 @@
     }
 }
 
+/* Crap function, but does the job - assumes that if the first char matches
+ * for the rest not to match is an error */
+static int skip_string(FILE *file, const char *string)
+{
+    int c;
+
+    /* Skip over any whitespace */
+    do {
+        c = get_uncommented_char(file);
+    } while (isspace(c));
+
+    /* Read the string */
+    if (c != *string++) {
+        ungetc(c, file);
+        return 0;
+    }
+
+    /* Skip the string */
+    while (*string) {
+        c = fgetc(file);
+        if (c != *string++) {
+            ungetc(c, file);
+            return 0;
+        }
+    }
+    return 1;
+}
+
+static void pam_header_read(FILE *file,
+                            int  *width,
+                            int  *height,
+                            int  *maxval)
+{
+    while (1) {
+        if        (skip_string(file, "WIDTH")) {
+            *width = get_pnm_num(file);
+        } else if (skip_string(file, "HEIGHT")) {
+            *height = get_pnm_num(file);
+        } else if (skip_string(file, "DEPTH")) {
+            if (get_pnm_num(file) != 4) {
+                fprintf(stderr, "Only CMYK PAMs!\n");
+                exit(1);
+            }
+        } else if (skip_string(file, "MAXVAL")) {
+            *maxval = get_pnm_num(file);
+        } else if (skip_string(file, "TUPLTYPE")) {
+            if (!skip_string(file, "CMYK")) {
+                fprintf(stderr, "Only CMYK PAMs!\n");
+                exit(1);
+            }
+        } else if (skip_string(file, "ENDHDR")) {
+          skip_to_eol(file);
+          return;
+        } else {
+            /* Unknown header string. Just skip to the end of the line */
+            skip_to_eol(file);
+        }
+    }
+}
+
 static void *pnm_read(ImageReader *im,
                       int         *width,
                       int         *height,
                       int         *span,
-                      int         *bpp)
+                      int         *bpp,
+                      int         *cmyk)
 {
     unsigned char *bmp;
     int            c, maxval;
@@ -600,6 +795,7 @@
     }
     if (c == EOF)
         return NULL;
+    *cmyk = 0;
     switch (get_pnm_num(im->file))
     {
         case 1:
@@ -620,20 +816,29 @@
         case 6:
             read = ppm_read;
             break;
+        case 7:
+            read = pam_read;
+            *cmyk = 1;
+            break;
         default:
             /* Eh? */
             fprintf(stderr, "Unknown PxM format!\n");
             return NULL;
     }
-    *width  = get_pnm_num(im->file);
+    if (read == pam_read) {
+        pam_header_read(im->file, width, height, &maxval);
+    } else {
+        *width  = get_pnm_num(im->file);
+        *height = get_pnm_num(im->file);
+        if (read != pbm_read)
+            maxval = get_pnm_num(im->file);
+        else
+            maxval = 1;
+    }
+
     *span   = *width * 4;
-    *height = get_pnm_num(im->file);
-    if (read != pbm_read)
-        maxval = get_pnm_num(im->file);
-    else
-        maxval = 1;
     *bpp = 32; /* We always convert to 32bpp */
-    
+
     bmp = Malloc(*width * *height * 4);
 
     read(im->file, *width, *height, maxval, bmp);
@@ -644,16 +849,16 @@
                        char        *filename)
 {
     int type;
-    
+
     im->file = fopen(filename, "rb");
     if (im->file == NULL) {
         fprintf(stderr, "%s failed to open\n", filename);
         exit(EXIT_FAILURE);
     }
-    
+
     /* Identify the filetype */
     type  = fgetc(im->file);
-    
+
     if (type == 0x50) {
         /* Starts with a P! Must be a P?M file. */
         im->read = pnm_read;
@@ -676,104 +881,86 @@
     im->file = NULL;
 }
 
-static void find_changed_bbox(unsigned char *bmp,
-                              unsigned char *bmp2,
-                              int            w,
-                              int            h,
-                              int            span,
-                              int            bpp,
-                              BBox          *bbox)
+static void simple_diff(unsigned char *bmp,
+                        unsigned char *bmp2,
+                        unsigned char *map,
+                        BBox          *bbox2,
+                        Params        *params)
 {
     int    x, y;
     int   *isrc, *isrc2;
-    short *ssrc, *ssrc2;
+    BBox   bbox;
+    int    w    = params->width;
+    int    h    = params->height;
+    int    span = params->span;
 
-    bbox->xmin = w;
-    bbox->ymin = h;
-    bbox->xmax = -1;
-    bbox->ymax = -1;
+    bbox.xmin = w;
+    bbox.ymin = h;
+    bbox.xmax = -1;
+    bbox.ymax = -1;
 
-    if (bpp == 32)
+    isrc  = (int *)bmp;
+    isrc2 = (int *)bmp2;
+    span >>= 2;
+    span -= w;
+    for (y = 0; y < h; y++)
     {
-        isrc  = (int *)bmp;
-        isrc2 = (int *)bmp2;
-        span >>= 2;
-        span -= w;
-        for (y = 0; y < h; y++)
+        for (x = 0; x < w; x++)
         {
-            for (x = 0; x < w; x++)
+            if (*isrc++ != *isrc2++)
             {
-                if (*isrc++ != *isrc2++)
-                {
-                    if (x < bbox->xmin)
-                        bbox->xmin = x;
-                    if (x > bbox->xmax)
-                        bbox->xmax = x;
-                    if (y < bbox->ymin)
-                        bbox->ymin = y;
-                    if (y > bbox->ymax)
-                        bbox->ymax = y;
-                }
+                if (x < bbox.xmin)
+                    bbox.xmin = x;
+                if (x > bbox.xmax)
+                    bbox.xmax = x;
+                if (y < bbox.ymin)
+                    bbox.ymin = y;
+                if (y > bbox.ymax)
+                    bbox.ymax = y;
+                *map++ = 1;
             }
-            isrc  += span;
-            isrc2 += span;
-        }
-    }
-    else
-    {
-        ssrc  = (short *)bmp;
-        ssrc2 = (short *)bmp2;
-        span >>= 1;
-        span -= w;
-        for (y = 0; y < h; y++)
-        {
-            for (x = 0; x < w; x++)
+            else
             {
-                if (*ssrc++ != *ssrc2++)
-                {
-                    if (x < bbox->xmin)
-                        bbox->xmin = x;
-                    if (x > bbox->xmax)
-                        bbox->xmax = x;
-                    if (y < bbox->ymin)
-                        bbox->ymin = y;
-                    if (y > bbox->ymax)
-                        bbox->ymax = y;
-                }
+                *map++ = 0;
             }
-            ssrc  += span;
-            ssrc2 += span;
         }
+        isrc  += span;
+        isrc2 += span;
     }
+    *bbox2 = bbox;
 }
 
-static void rediff(unsigned char *bmp,
-                   unsigned char *bmp2,
-                   int            span,
-                   int            bpp,
-                   BBox          *bbox2)
+static void simple_diff2(unsigned char *bmp,
+                         unsigned char *bmp2,
+                         unsigned char *map,
+                         BBox          *bbox2,
+                         Params        *params)
 {
     int    x, y;
-    int   *isrc, *isrc2;
+    int   *isrc, *isrc2, *isrc3;
     short *ssrc, *ssrc2;
     BBox   bbox;
     int    w;
     int    h;
+    int    span = params->span;
 
     w = bbox2->xmax - bbox2->xmin;
     h = bbox2->ymax - bbox2->ymin;
-    bbox.xmin = w;
-    bbox.ymin = h;
+    bbox.xmin = bbox2->xmax;
+    bbox.ymin = bbox2->ymax;
     bbox.xmax = -1;
     bbox.ymax = -1;
 
-    if (bpp == 32)
+    if (params->bpp == 32)
     {
         isrc  = (int *)bmp;
         isrc2 = (int *)bmp2;
         span >>= 2;
         isrc  += span*(bbox2->ymin)+bbox2->xmin;
         isrc2 += span*(bbox2->ymin)+bbox2->xmin;
+        if (isrc3 != NULL) {
+            isrc3 += span*(bbox2->ymin)+bbox2->xmin;
+        }
         span -= w;
         for (y = 0; y < h; y++)
         {
@@ -789,6 +976,9 @@
                         bbox.ymin = y;
                     if (y > bbox.ymax)
                         bbox.ymax = y;
+                    if (isrc3 != NULL)
+                    {
+                    }
                 }
             }
             isrc  += span;
@@ -823,59 +1013,469 @@
             ssrc2 += span;
         }
     }
-    if ((bbox.xmin > bbox.xmax) || (bbox.ymin > bbox.ymax))
+    *bbox2 = bbox;
+}
+
+typedef struct FuzzyParams FuzzyParams;
+
+struct FuzzyParams {
+    int            window;
+    int            threshold;
+    int            wTabLen;
+    ptrdiff_t     *wTab;
+    int            width;
+    int            height;
+    int            span;
+    int          (*slowFn)(FuzzyParams   *self,
+                           unsigned char *src,
+                           unsigned char *src2,
+                           unsigned char *map,
+                           int            x,
+                           int            y);
+    int          (*fastFn)(FuzzyParams   *self,
+                           unsigned char *src,
+                           unsigned char *src2,
+                           unsigned char *map);
+};
+
+static int fuzzy_slow(FuzzyParams   *fuzzy_params,
+                      unsigned char *isrc,
+                      unsigned char *isrc2,
+                      unsigned char *map,
+                      int            x,
+                      int            y)
+{
+    int xmin, ymin, xmax, ymax;
+    int span, t;
+
+    /* left of window = max(0, x - window) - x */
+    xmin = - fuzzy_params->window;
+    if (xmin < -x)
+        xmin = -x;
+    /* right of window = min(width, x + window) - x */
+    xmax = fuzzy_params->window;
+    if (xmax > fuzzy_params->width-x)
+        xmax = fuzzy_params->width-x;
+    /* top of window = max(0, y - window) - y */
+    ymin = - fuzzy_params->window;
+    if (ymin < -y)
+        ymin = -y;
+    /* bottom of window = min(height, y + window) - y */
+    ymax = fuzzy_params->window;
+    if (ymax > fuzzy_params->height-y)
+        ymax = fuzzy_params->height-y;
+    span = fuzzy_params->span;
+    t    = fuzzy_params->threshold;
+
+    for (y = ymin; y < ymax; y++)
     {
-        /* No changes. Return with invalid bbox */
-        *bbox2 = bbox;
-        return;
+        for (x = xmin; x < xmax; x++)
+        {
+            int o = x+y*span;
+            int v;
+
+            v = isrc[0]-isrc2[o];
+            if (v < 0)
+                v = -v;
+            if (v > t)
+                continue;
+            v = isrc[1]-isrc2[o+1];
+            if (v < 0)
+                v = -v;
+            if (v > t)
+                continue;
+            v = isrc[2]-isrc2[o+2];
+            if (v < 0)
+                v = -v;
+            if (v > t)
+                continue;
+            v = isrc[3]-isrc2[o+3];
+            if (v < 0)
+                v = -v;
+            if (v <= t)
+                return 0;
+        }
     }
-    bbox.xmin += bbox2->xmin;
-    bbox.ymin += bbox2->ymin;
-    bbox.xmax += bbox2->xmin;
-    bbox.ymax += bbox2->ymin;
-    bbox.xmax++;
-    bbox.ymax++;
-    if ((bbox.xmax-bbox.xmin > 0) &&
-        (bbox.xmax-bbox.xmin < MINX))
+    *map |= 15;
+    return 1;
+}
+
+static int fuzzy_slow_exhaustive(FuzzyParams   *fuzzy_params,
+                                 unsigned char *isrc,
+                                 unsigned char *isrc2,
+                                 unsigned char *map,
+                                 int            x,
+                                 int            y)
+{
+    int          xmin, ymin, xmax, ymax;
+    int          span, t;
+    unsigned int flags = 15;
+    int          ret   = 1;
+
+    /* left of window = max(0, x - window) - x */
+    xmin = - fuzzy_params->window;
+    if (xmin < -x)
+        xmin = -x;
+    /* right of window = min(width, x + window) - x */
+    xmax = fuzzy_params->window;
+    if (xmax > fuzzy_params->width-x)
+        xmax = fuzzy_params->width-x;
+    /* top of window = max(0, y - window) - y */
+    ymin = - fuzzy_params->window;
+    if (ymin < -y)
+        ymin = -y;
+    /* bottom of window = min(height, y + window) - y */
+    ymax = fuzzy_params->window;
+    if (ymax > fuzzy_params->height-y)
+        ymax = fuzzy_params->height-y;
+    span = fuzzy_params->span;
+    t    = fuzzy_params->threshold;
+
+    for (y = ymin; y < ymax; y++)
     {
-        int d = MINX;
-        
-        if (d > w)
-            d = w;
-        d -= (bbox.xmax-bbox.xmin);
-        bbox.xmin -= d>>1;
-        bbox.xmax += d-(d>>1);
-        if (bbox.xmin < bbox2->xmin)
+        for (x = xmin; x < xmax; x++)
         {
-            bbox.xmax += bbox2->xmin-bbox.xmin;
-            bbox.xmin  = bbox2->xmin;
+            int o = x+y*span;
+            int v;
+            int exact = 1;
+
+            v = isrc[0]-isrc2[o];
+            if (v < 0)
+                v = -v;
+            if (v != 0)
+                exact = 0;
+            if (v > t)
+                continue;
+            v = isrc[1]-isrc2[o+1];
+            if (v < 0)
+                v = -v;
+            if (v != 0)
+                exact = 0;
+            if (v > t)
+                continue;
+            v = isrc[2]-isrc2[o+2];
+            if (v < 0)
+                v = -v;
+            if (v != 0)
+                exact = 0;
+            if (v > t)
+                continue;
+            v = isrc[3]-isrc2[o+3];
+            if (v < 0)
+                v = -v;
+            if (v != 0)
+                exact = 0;
+            if (v <= t) {
+                /* We match within the tolerance */
+                flags &= ~(1<<3);
+                if ((x | y) == 0)
+                    flags &= ~(1<<2);
+                if (exact) {
+                    *map |= 1;
+                    return 0;
+                }
+                ret = 0;
+            }
         }
-        if (bbox.xmax > bbox2->xmax)
+    }
+    *map |= flags;
+    return ret;
+}
+
+static int fuzzy_fast(FuzzyParams   *fuzzy_params,
+                      unsigned char *isrc,
+                      unsigned char *isrc2,
+                      unsigned char *map)
+{
+    int        i;
+    ptrdiff_t *wTab = fuzzy_params->wTab;
+    int        t    = fuzzy_params->threshold;
+
+    for (i = fuzzy_params->wTabLen; i > 0; i--)
+    {
+        int o = *wTab++;
+        int v;
+
+        v = isrc[0]-isrc2[o];
+        if (v < 0)
+            v = -v;
+        if (v > t)
+            continue;
+        v = isrc[1]-isrc2[o+1];
+        if (v < 0)
+            v = -v;
+        if (v > t)
+            continue;
+        v = isrc[2]-isrc2[o+2];
+        if (v < 0)
+            v = -v;
+        if (v > t)
+            continue;
+        v = isrc[3]-isrc2[o+3];
+        if (v < 0)
+            v = -v;
+        if (v <= t)
+            return 0;
+    }
+    *map |= 15;
+    return 1;
+}
+
+static int fuzzy_fast_exhaustive(FuzzyParams   *fuzzy_params,
+                                 unsigned char *isrc,
+                                 unsigned char *isrc2,
+                                 unsigned char *map)
+{
+    int            i;
+    ptrdiff_t     *wTab  = fuzzy_params->wTab;
+    int            t     = fuzzy_params->threshold;
+    unsigned char  flags = 15;
+    int            ret   = 1;
+
+    for (i = fuzzy_params->wTabLen; i > 0; i--)
+    {
+        int o = *wTab++;
+        int v;
+        int exact = 1;
+
+        v = isrc[0]-isrc2[o];
+        if (v < 0)
+            v = -v;
+        if (v > t)
+            continue;
+        if (v != 0)
+            exact = 0;
+        v = isrc[1]-isrc2[o+1];
+        if (v < 0)
+            v = -v;
+        if (v > t)
+            continue;
+        if (v != 0)
+            exact = 0;
+        v = isrc[2]-isrc2[o+2];
+        if (v < 0)
+            v = -v;
+        if (v > t)
+            continue;
+        if (v != 0)
+            exact = 0;
+        v = isrc[3]-isrc2[o+3];
+        if (v < 0)
+            v = -v;
+        if (v <= t) {
+            /* We match within the tolerance */
+            flags &= ~(1<<3);
+            if (o == 0)
+                flags &= ~(1<<2);
+            if (exact) {
+                *map |= 1;
+                return 0;
+            }
+            ret = 0;
+        }
+    }
+    *map |= flags;
+    return ret;
+}
+
+
+static void fuzzy_diff(unsigned char *bmp,
+                       unsigned char *bmp2,
+                       unsigned char *map,
+                       BBox          *bbox2,
+                       Params        *params)
+{
+    int          x, y;
+    int         *isrc, *isrc2;
+    BBox         bbox;
+    int          w, h, span;
+    int          border;
+    int          lb, rb, tb, bb;
+    FuzzyParams  fuzzy_params;
+
+    w = params->width;
+    h = params->height;
+    bbox.xmin = w;
+    bbox.ymin = h;
+    bbox.xmax = -1;
+    bbox.ymax = -1;
+    fuzzy_params.window    = params->window>>1;
+    fuzzy_params.threshold = params->threshold;
+    fuzzy_params.wTab      = params->wTab;
+    fuzzy_params.wTabLen   = params->wTabLen;
+    fuzzy_params.threshold = params->threshold;
+    fuzzy_params.width     = params->width;
+    fuzzy_params.height    = params->height;
+    fuzzy_params.span      = params->span;
+    if (params->exhaustive)
+    {
+        fuzzy_params.slowFn    = fuzzy_slow_exhaustive;
+        fuzzy_params.fastFn    = fuzzy_fast_exhaustive;
+    } else {
+        fuzzy_params.slowFn    = fuzzy_slow;
+        fuzzy_params.fastFn    = fuzzy_fast;
+    }
+    span                   = params->span;
+
+    /* Figure out borders */
+    border = params->window>>1;
+    lb     = border;
+    if (lb > params->width)
+        lb = params->width;
+    tb     = border;
+    if (tb > params->height)
+        tb = params->height;
+    rb     = border;
+    if (rb > params->width-lb)
+        rb = params->width-lb;
+    bb     = border;
+    if (bb > params->height-tb)
+        bb = params->height;
+
+    isrc  = (int *)bmp;
+    isrc2 = (int *)bmp2;
+    span >>= 2;
+    span -= w;
+    for (y = 0; y < tb; y++)
+    {
+        for (x = 0; x < w; x++)
         {
-            bbox.xmin -= bbox.xmax-bbox2->xmax;
-            bbox.xmax  = bbox2->xmax;
+            if (*isrc++ != *isrc2++)
+            {
+                *map++ |= 1;
+                if (fuzzy_params.slowFn(&fuzzy_params,
+                                        (unsigned char *)(isrc-1),
+                                        (unsigned char *)(isrc2-1),
+                                        map-1,
+                                        x, y))
+                {
+                    if (x < bbox.xmin)
+                        bbox.xmin = x;
+                    if (x > bbox.xmax)
+                        bbox.xmax = x;
+                    if (y < bbox.ymin)
+                        bbox.ymin = y;
+                    if (y > bbox.ymax)
+                        bbox.ymax = y;
+                }
+            }
+            else
+            {
+                *map++ = 0;
+            }
         }
+        isrc  += span;
+        isrc2 += span;
     }
-    if ((bbox.ymax-bbox.ymin > 0) && (bbox.ymax-bbox.ymin < MINY))
+    for (; y < h-bb; y++)
     {
-        int d = MINY;
-        
-        if (d > h)
-            d = h;
-        d -= (bbox.ymax-bbox.ymin);
-        bbox.ymin -= d>>1;
-        bbox.ymax += d-(d>>1);
-        if (bbox.ymin < bbox2->ymin)
+        for (x = 0; x < lb; x++)
         {
-            bbox.ymax += bbox2->ymin-bbox.ymin;
-            bbox.ymin  = bbox2->ymin;
+            if (*isrc++ != *isrc2++)
+            {
+                *map++ |= 1;
+                if (fuzzy_params.slowFn(&fuzzy_params,
+                                        (unsigned char *)(isrc-1),
+                                        (unsigned char *)(isrc2-1),
+                                        map-1,
+                                        x, y))
+                {
+                    if (x < bbox.xmin)
+                        bbox.xmin = x;
+                    if (x > bbox.xmax)
+                        bbox.xmax = x;
+                    if (y < bbox.ymin)
+                        bbox.ymin = y;
+                    if (y > bbox.ymax)
+                        bbox.ymax = y;
+                }
+            }
+            else
+            {
+                *map++ = 0;
+            }
         }
-        if (bbox.ymax > bbox2->ymax)
+        for (; x < w-rb; x++)
         {
-            bbox.ymin -= bbox.ymax-bbox2->ymax;
-            bbox.ymax  = bbox2->ymax;
+            if (*isrc++ != *isrc2++)
+            {
+                *map++ |= 1;
+                if (fuzzy_params.fastFn(&fuzzy_params,
+                                        (unsigned char *)(isrc-1),
+                                        (unsigned char *)(isrc2-1),
+                                        map-1))
+                {
+                    if (x < bbox.xmin)
+                        bbox.xmin = x;
+                    if (x > bbox.xmax)
+                        bbox.xmax = x;
+                    if (y < bbox.ymin)
+                        bbox.ymin = y;
+                    if (y > bbox.ymax)
+                        bbox.ymax = y;
+                }
+            }
+            else
+            {
+                *map++ = 0;
+            }
         }
+        for (; x < w; x++)
+        {
+            if (*isrc++ != *isrc2++)
+            {
+                *map++ |= 1;
+                if (fuzzy_params.slowFn(&fuzzy_params,
+                                        (unsigned char *)(isrc-1),
+                                        (unsigned char *)(isrc2-1),
+                                        map-1,
+                                        x, y))
+                {
+                    if (x < bbox.xmin)
+                        bbox.xmin = x;
+                    if (x > bbox.xmax)
+                        bbox.xmax = x;
+                    if (y < bbox.ymin)
+                        bbox.ymin = y;
+                    if (y > bbox.ymax)
+                        bbox.ymax = y;
+                }
+            }
+            else
+            {
+                *map++ = 0;
+            }
+        }
+        isrc  += span;
+        isrc2 += span;
     }
+    for (; y < bb; y++)
+    {
+        for (x = 0; x < w; x++)
+        {
+            if (*isrc++ != *isrc2++)
+            {
+                *map++ |= 1;
+                if (fuzzy_params.slowFn(&fuzzy_params,
+                                        (unsigned char *)(isrc-1),
+                                        (unsigned char *)(isrc2-1),
+                                        map-1,
+                                        x, y))
+                {
+                    if (x < bbox.xmin)
+                        bbox.xmin = x;
+                    if (x > bbox.xmax)
+                        bbox.xmax = x;
+                    if (y < bbox.ymin)
+                        bbox.ymin = y;
+                    if (y > bbox.ymax)
+                        bbox.ymax = y;
+                }
+            }
+        }
+        isrc  += span;
+        isrc2 += span;
+    }
     *bbox2 = bbox;
 }
 
@@ -884,33 +1484,75 @@
     return ((bbox->xmin < bbox->xmax) && (bbox->ymin < bbox->ymax));
 }
 
+static void uncmyk_bmp(unsigned char *bmp,
+                       BBox          *bbox,
+                       int            span)
+{
+    int w, h;
+    int x, y;
+
+    bmp  += span    *(bbox->ymin)+(bbox->xmin<<2);
+    w     = bbox->xmax - bbox->xmin;
+    h     = bbox->ymax - bbox->ymin;
+    span -= 4*w;
+    for (y = 0; y < h; y++)
+    {
+        for (x = 0; x < w; x++)
+        {
+            int c, m, y, k, r, g, b;
+
+            c = *bmp++;
+            m = *bmp++;
+            y = *bmp++;
+            k = *bmp++;
+
+            r = (255-c-k);
+            if (r < 0)
+                r = 0;
+            g = (255-m-k);
+            if (g < 0)
+                g = 0;
+            b = (255-y-k);
+            if (b < 0)
+                b = 0;
+            bmp[-1] = 0;
+            bmp[-2] = r;
+            bmp[-3] = g;
+            bmp[-4] = b;
+        }
+        bmp += span;
+    }
+}
+
 static void diff_bmp(unsigned char *bmp,
-                     unsigned char *bmp2,
-                     int            w,
-                     int            h,
+                     unsigned char *map,
+                     BBox          *bbox,
                      int            span,
-                     int            bpp)
+                     int            map_span)
 {
-    int    x, y;
-    int   *isrc, *isrc2;
-    int    i, i2;
-    short *ssrc, *ssrc2;
-    short  s, s2;
+    int  w, h;
+    int  x, y;
+    int *isrc;
 
-    if (bpp == 32)
+    isrc      = (int *)bmp;
+    span    >>= 2;
+    isrc     += span    *(bbox->ymin)+bbox->xmin;
+    map      += map_span*(bbox->ymin)+bbox->xmin;
+    w         = bbox->xmax - bbox->xmin;
+    h         = bbox->ymax - bbox->ymin;
+    span     -= w;
+    map_span -= w;
+    for (y = 0; y < h; y++)
     {
-        isrc  = (int *)bmp;
-        isrc2 = (int *)bmp2;
-        span >>= 2;
-        span -= w;
-        for (y = 0; y < h; y++)
+        for (x = 0; x < w; x++)
         {
-            for (x = 0; x < w; x++)
-            {
-                i  = *isrc++;
-                i2 = *isrc2++;
-                if (i == i2)
+            int m = *map++;
+            int i = *isrc;
+
+            switch (m) {
+                case 0:
                 {
+                    /* Matching pixel - greyscale it */
                     int a;
 
                     a  =  i      & 0xFF;
@@ -919,72 +1561,34 @@
                     a += 0xFF*3*2;
                     a /= 6*2;
 
-                    isrc[-1] = a | (a<<8) | (a<<16);
+                    *isrc++ = a | (a<<8) | (a<<16);
+                    break;
                 }
-                else
-                {
-                    int r,g,b,r2,g2,b2;
-
-                    r  = i  & 0x0000FF;
-                    g  = i  & 0x00FF00;
-                    b  = i  & 0xFF0000;
-                    r2 = i2 & 0x0000FF;
-                    g2 = i2 & 0x00FF00;
-                    b2 = i2 & 0xFF0000;
-                    if ((abs(r-r2) <= 3) && (abs(g-g2) <= 0x300) && (abs(b-b2)<= 0x30000))
-                        isrc[-1] = 0x00FF00;
-                    else
-                        isrc[-1] = 0x00FFFF;
-                }
+                case 1:
+                    *isrc++ = 0x00FF00; /* Green */
+                    break;
+                case 3:
+                    *isrc++ = 0x00FFFF; /* Cyan */
+                    break;
+                case 5:
+                    *isrc++ = 0xFFFF00; /* Yellow */
+                    break;
+                case 7:
+                    *isrc++ = 0xFF8000; /* Orange */
+                    break;
+                case 15:
+                    *isrc++ = 0xFF0000; /* Red */
+                    break;
+                default:
+                    fprintf(stderr,
+                            "Internal error: unexpected map type %d\n", m);
+                    isrc++;
+                    break;
             }
-            isrc  += span;
-            isrc2 += span;
         }
+        isrc += span;
+        map  += map_span;
     }
-    else
-    {
-        ssrc  = (short *)bmp;
-        ssrc2 = (short *)bmp2;
-        span >>= 1;
-        span -= w;
-        for (y = 0; y < h; y++)
-        {
-            for (x = 0; x < w; x++)
-            {
-                s  = *ssrc++;
-                s2 = *ssrc2++;
-                if (s == s2)
-                {
-                    int a;
-
-                    a  =  s      & 0x1F;
-                    a += (s>> 6) & 0x1F;
-                    a += (s>>11) & 0x1F;
-                    a += 3*0x1F*2;
-                    a /= 6*2;
-
-                    ssrc[-1] = a | (a<<6) | ((a & 0x10)<<5) | (a<<11);
-                }
-                else
-                {
-                    int r,g,b,r2,g2,b2;
-
-                    r  =  s       & 0x1f;
-                    g  = (s >> 5) & 0x3f;
-                    b  = (s >>11) & 0x1f;
-                    r2 =  s2      & 0x1f;
-                    g2 = (s2>> 5) & 0x3f;
-                    b2 = (s2>>11) & 0x1f;
-                    if ((abs(r-r2) <= 1) && (abs(g-g2) <= 3) && (abs(b-b2)<= 1))
-                        ssrc[-1] = 0x07E0;
-                    else
-                        ssrc[-1] = 0x001F;
-                }
-            }
-            ssrc  += span;
-            ssrc2 += span;
-        }
-    }
 }
 
 static void save_meta(BBox *bbox, char *str, int w, int h, int page)
@@ -1038,10 +1642,10 @@
     putdword(bmp+14, 40);
     putdword(bmp+18, width);
     putdword(bmp+22, height);
-    putword (bmp+26, 1);			/* Bit planes */
+    putword (bmp+26, 1);                        /* Bit planes */
     putword (bmp+28, (bpp == 16 ? 16 : 24));
-    putdword(bmp+30, 0);			/* Compression type */
-    putdword(bmp+34, 0);			/* Compressed size */
+    putdword(bmp+30, 0);                        /* Compression type */
+    putdword(bmp+34, 0);                        /* Compressed size */
     putdword(bmp+38, 354);
     putdword(bmp+42, 354);
     putdword(bmp+46, 0);
@@ -1090,7 +1694,7 @@
     int   bpc;
     int   width, height;
     int   y;
-    
+
     file = fopen(str, "wb");
     if (file == NULL)
         return;
@@ -1104,14 +1708,14 @@
     if (info == NULL)
         /* info being set to NULL above makes this safe */
         goto png_cleanup;
-    
+
     /* libpng using longjmp() for error 'callback' */
     if (setjmp(png_jmpbuf(png)))
         goto png_cleanup;
-    
+
     /* hook the png writer up to our FILE pointer */
     png_init_io(png, file);
-    
+
     /* fill out the image header */
     width  = bbox->xmax - bbox->xmin;
     height = bbox->ymax - bbox->ymin;
@@ -1135,10 +1739,10 @@
     for (y = 0; y < height; y++)
       rows[height - y - 1] = &data[(y + bbox->ymin)*span + bbox->xmin * src_bypp - 1];
     png_set_rows(png, info, rows);
-    
+
     /* write out the image */
     png_write_png(png, info,
-        PNG_TRANSFORM_STRIP_FILLER_BEFORE| 
+        PNG_TRANSFORM_STRIP_FILLER_BEFORE|
         PNG_TRANSFORM_BGR, NULL);
 
     free(rows);
@@ -1150,16 +1754,224 @@
 }
 #endif /* HAVE_LIBPNG */
 
+static void syntax(void)
+{
+    fprintf(stderr, "Syntax: bmpcmp [options] <file1> <file2> <outfile_root> [<basenum>] [<maxdiffs>]\n");
+    fprintf(stderr, "  -w <window> or -w<window>         window size (default=1)\n");
+    fprintf(stderr, "  -t <threshold> or -t<threshold>   threshold   (default=0)\n");
+    fprintf(stderr, "  -e                                exhaustive search\n");
+    fprintf(stderr, "  <file1> and <file2> can be "
+#ifdef HAVE_LIBPNG
+                    "png, "
+#endif /* HAVE_LIBPNG */
+                    "bmp, ppm, pgm, pbm or pam files.\n");
+    fprintf(stderr, "  This will produce a series of <outfile_root>.<number>.bmp files\n");
+    fprintf(stderr, "  and a series of <outfile_root>.<number>.meta files.\n");
+    fprintf(stderr, "  The maxdiffs value determines the maximum number of bitmaps\n");
+    fprintf(stderr, "  produced - 0 (or unsupplied) is taken to mean unlimited.\n");
+}
+
+static void parseArgs(int argc, char *argv[], Params *params)
+{
+    int arg;
+    int i;
+
+    /* Set defaults */
+    memset(params, 0, sizeof(*params));
+    params->window = 1;
+
+    arg = 0;
+    i = 1;
+    while (i < argc)
+    {
+        if (argv[i][0] == '-')
+        {
+            switch (argv[i][1]) {
+                case 'w':
+                    if (argv[i][2]) {
+                        params->window = atoi(&argv[i][2]);
+                    } else if (++i < argc) {
+                        params->window = atoi(argv[i]);
+                    }
+                    break;
+                case 't':
+                    if (argv[i][2]) {
+                        params->threshold = atoi(&argv[i][2]);
+                    } else if (++i < argc) {
+                        params->threshold = atoi(argv[i]);
+                    }
+                    break;
+                case 'e':
+                    params->exhaustive = 1;
+                    break;
+                default:
+                    syntax();
+                    exit(EXIT_FAILURE);
+            }
+        } else {
+            switch (arg) {
+                case 0:
+                    params->filename1 = argv[i];
+                    break;
+                case 1:
+                    params->filename2 = argv[i];
+                    break;
+                case 2:
+                    params->outroot = argv[i];
+                    break;
+                case 3:
+                    params->basenum = atoi(argv[i]);
+                    break;
+                case 4:
+                    params->maxdiffs = atoi(argv[i]);
+                    break;
+                default:
+                    syntax();
+                    exit(EXIT_FAILURE);
+            }
+            arg++;
+        }
+        i++;
+    }
+
+    if (arg < 3)
+    {
+        syntax();
+        exit(EXIT_FAILURE);
+    }
+}
+
+static void makeWindowTable(Params *params, int span, int bpp)
+{
+    int        x, y, i, w;
+    ptrdiff_t *wnd;
+
+    params->window |= 1;
+    w = (params->window+1)>>1;
+    if (params->wTab == NULL) {
+        params->wTabLen = params->window*params->window;
+        params->wTab    = Malloc(params->wTabLen*sizeof(ptrdiff_t));
+    }
+    wnd = params->wTab;
+    *wnd++ = 0;
+
+#define OFFSET(x,y) (x*(bpp>>3)+y*span)
+
+    for(i=1;i<params->window;i++) {
+        x = i;
+        y = 0;
+        while (x != 0)
+        {
+            if ((x < w) && (y < w)) {
+                *wnd++ = OFFSET( x, y);
+                *wnd++ = OFFSET(-x,-y);
+                *wnd++ = OFFSET(-y, x);
+                *wnd++ = OFFSET( y,-x);
+            }
+            x--;
+            y++;
+        }
+    }
+
+#undef OFFSET
+
+}
+
+static void rediff(unsigned char *map,
+                   BBox          *global,
+                   Params        *params)
+{
+    BBox  local;
+    int   x, y;
+    int   w, h;
+    int   span = params->width;
+
+    w = global->xmax - global->xmin;
+    h = global->ymax - global->ymin;
+    local.xmin = global->xmax;
+    local.ymin = global->ymax;
+    local.xmax = -1;
+    local.ymax = -1;
+
+    map += span*(global->ymin)+global->xmin;
+    span -= w;
+    for (y = 0; y < h; y++)
+    {
+        for (x = 0; x < w; x++)
+        {
+            if (*map++ != 0)
+            {
+                if (x < local.xmin)
+                    local.xmin = x;
+                if (x > local.xmax)
+                    local.xmax = x;
+                if (y < local.ymin)
+                    local.ymin = y;
+                if (y > local.ymax)
+                    local.ymax = y;
+            }
+        }
+        map += span;
+    }
+
+    local.xmin += global->xmin;
+    local.ymin += global->ymin;
+    local.xmax += global->xmin;
+    local.ymax += global->ymin;
+    local.xmax++;
+    local.ymax++;
+    if ((local.xmax-local.xmin > 0) &&
+        (local.xmax-local.xmin < MINX))
+    {
+        int d = MINX;
+
+        if (d > w)
+            d = w;
+        d -= (local.xmax-local.xmin);
+        local.xmin -= d>>1;
+        local.xmax += d-(d>>1);
+        if (local.xmin < global->xmin)
+        {
+            local.xmax += global->xmin-local.xmin;
+            local.xmin  = global->xmin;
+        }
+        if (local.xmax > global->xmax)
+        {
+            local.xmin -= local.xmax-global->xmax;
+            local.xmax  = global->xmax;
+        }
+    }
+    if ((local.ymax-local.ymin > 0) && (local.ymax-local.ymin < MINY))
+    {
+        int d = MINY;
+
+        if (d > h)
+            d = h;
+        d -= (local.ymax-local.ymin);
+        local.ymin -= d>>1;
+        local.ymax += d-(d>>1);
+        if (local.ymin < global->ymin)
+        {
+            local.ymax += global->ymin-local.ymin;
+            local.ymin  = global->ymin;
+        }
+        if (local.ymax > global->ymax)
+        {
+            local.ymin -= local.ymax-global->ymax;
+            local.ymax  = global->ymax;
+        }
+    }
+}
+
 int main(int argc, char *argv[])
 {
-    int            w,  h,  s,  bpp;
-    int            w2, h2, s2, bpp2;
+    int            w,  h,  s,  bpp,  cmyk;
+    int            w2, h2, s2, bpp2, cmyk2;
     int            nx, ny, n;
-    int            basenum;
     int            imagecount;
-    int            maxdiffs;
     unsigned char *bmp;
     unsigned char *bmp2;
+    unsigned char *map;
     BBox           bbox, bbox2;
     BBox          *boxlist;
     char           str1[256];
@@ -1167,65 +1979,55 @@
     char           str3[256];
     char           str4[256];
     ImageReader    image1, image2;
+    DiffFn        *diffFn;
+    Params         params;
 
-    if (argc < 4)
-    {
-        fprintf(stderr, "Syntax: bmpcmp <file1> <file2> <outfile_root> [<basenum>] [<maxdiffs>]\n");
-        fprintf(stderr, "  <file1> and <file2> can be bmp, ppm, pgm or pbm files.\n");
-        fprintf(stderr, "  This will produce a series of <outfile_root>.<number>.bmp files\n");
-        fprintf(stderr, "  and a series of <outfile_root>.<number>.meta files.\n");
-        fprintf(stderr, "  The maxdiffs value determines the maximum number of bitmaps\n");
-        fprintf(stderr, "  produced - 0 (or unsupplied) is taken to mean unlimited.\n");
-        exit(EXIT_FAILURE);
+    parseArgs(argc, argv, &params);
+    if (params.window <= 1 && params.threshold == 0) {
+        diffFn = simple_diff;
+    } else {
+        diffFn = fuzzy_diff;
     }
 
-    if (argc > 4)
-    {
-        basenum = atoi(argv[4]);
-    }
-    else
-    {
-        basenum = 0;
-    }
+    image_open(&image1, params.filename1);
+    image_open(&image2, params.filename2);
 
-    if (argc > 5)
-    {
-        maxdiffs = atoi(argv[5]);
-    }
-    else
-    {
-        maxdiffs = 0;
-    }
-    
-    image_open(&image1, argv[1]);
-    image_open(&image2, argv[2]);
-    
     imagecount = 1;
     while (((bmp2 = NULL,
-             bmp  = image1.read(&image1, &w,  &h,  &s,  &bpp )) != NULL) &&
-           ((bmp2 = image2.read(&image2, &w2, &h2, &s2, &bpp2)) != NULL))
+             bmp  = image1.read(&image1,&w, &h, &s, &bpp, &cmyk )) != NULL) &&
+           ((bmp2 = image2.read(&image2,&w2,&h2,&s2,&bpp2,&cmyk2)) != NULL))
     {
         /* Check images are compatible */
-        if ((w != w2) || (h != h2) || (s != s2) || (bpp != bpp2))
+        if ((w != w2) || (h != h2) || (s != s2) || (bpp != bpp2) ||
+            (cmyk != cmyk2))
         {
             fprintf(stderr,
                     "Can't compare images "
-                    "(w=%d,%d) (h=%d,%d) (s=%d,%d) (bpp=%d,%d)!\n",
-                    w, w2, h, h2, s, s2, bpp, bpp2);
+                    "(w=%d,%d) (h=%d,%d) (s=%d,%d) (bpp=%d,%d) (cmyk=%d,%d)!\n",
+                    w, w2, h, h2, s, s2, bpp, bpp2, cmyk, cmyk2);
             exit(EXIT_FAILURE);
         }
 
-        find_changed_bbox(bmp, bmp2, w, h, s, bpp, &bbox);
+        if (params.window != 0)
+        {
+            makeWindowTable(&params, s, bpp);
+        }
+        map = Malloc(s*w*sizeof(unsigned char));
+        params.width  = w;
+        params.height = h;
+        params.span   = s;
+        params.bpp    = bpp;
+        (*diffFn)(bmp, bmp2, map, &bbox, &params);
         if ((bbox.xmin <= bbox.xmax) && (bbox.ymin <= bbox.ymax))
         {
             /* Make the bbox sensibly exclusive */
             bbox.xmax++;
             bbox.ymax++;
-    
+
             /* Make bbox2.xmin/ymin be the centre of the changed area */
             bbox2.xmin = (bbox.xmin + bbox.xmax + 1)/2;
             bbox2.ymin = (bbox.ymin + bbox.ymax + 1)/2;
-    
+
             /* Make bbox2.xmax/ymax be the width of the changed area */
             nx = 1;
             ny = 1;
@@ -1245,7 +2047,7 @@
                 ny = 1+(bbox2.ymax/MAXY);
                 bbox2.ymax = MAXY*ny;
             }
-    
+
             /* Now make the real bbox */
             bbox2.xmin -= bbox2.xmax>>1;
             if (bbox2.xmin < 0)
@@ -1269,12 +2071,12 @@
                     bbox2.ymin = 0;
                 bbox2.ymax = h;
             }
-    
+
             /* bbox */
             boxlist = Malloc(sizeof(*boxlist) * nx * ny);
-    
+
             /* Now save the changed bmps */
-            n = basenum;
+            n = params.basenum;
             boxlist--;
             for (w2=0; w2 < nx; w2++)
             {
@@ -1301,60 +2103,54 @@
                         if (boxlist->ymin < 0)
                             boxlist->ymin = 0;
                     }
-                    rediff(bmp, bmp2, s, bpp, boxlist);
+                    rediff(map, boxlist, &params);
                     if (!BBox_valid(boxlist))
                         continue;
+                    if (cmyk)
+                    {
+                        uncmyk_bmp(bmp,  boxlist, s);
+                        uncmyk_bmp(bmp2, boxlist, s);
+                    }
 #ifdef HAVE_LIBPNG
-                    sprintf(str1, "%s.%05d.png", argv[3], n);
-                    sprintf(str2, "%s.%05d.png", argv[3], n+1);
+                    sprintf(str1, "%s.%05d.png", params.outroot, n);
+                    sprintf(str2, "%s.%05d.png", params.outroot, n+1);
+                    sprintf(str3, "%s.%05d.png", params.outroot, n+2);
                     save_png(bmp,  boxlist, s, bpp, str1);
                     save_png(bmp2, boxlist, s, bpp, str2);
 #else
-                    sprintf(str1, "%s.%05d.bmp", argv[3], n);
-                    sprintf(str2, "%s.%05d.bmp", argv[3], n+1);
+                    sprintf(str1, "%s.%05d.bmp", params.outroot, n);
+                    sprintf(str2, "%s.%05d.bmp", params.outroot, n+1);
+                    sprintf(str3, "%s.%05d.bmp", params.outroot, n+2);
                     save_bmp(bmp,  boxlist, s, bpp, str1);
                     save_bmp(bmp2, boxlist, s, bpp, str2);
 #endif
-                    sprintf(str4, "%s.%05d.meta", argv[3], n);
-                    save_meta(boxlist, str4, w, h, imagecount);
-                    n += 3;
-                }
-            }
-            boxlist -= nx*ny;
-            diff_bmp(bmp, bmp2, w, h, s, bpp);
-            n = basenum;
-            for (w2=0; w2 < nx; w2++)
-            {
-                for (h2=0; h2 < ny; h2++)
-                {
-                    boxlist++;
-                    if (!BBox_valid(boxlist))
-                        continue;
+                    diff_bmp(bmp, map, boxlist, s, w);
 #ifdef HAVE_LIBPNG
-                    sprintf(str3, "%s.%05d.png", argv[3], n+2);
                     save_png(bmp, boxlist, s, bpp, str3);
 #else
-                    sprintf(str3, "%s.%05d.bmp", argv[3], n+2);
                     save_bmp(bmp, boxlist, s, bpp, str3);
 #endif
+                    sprintf(str4, "%s.%05d.meta", params.outroot, n);
+                    save_meta(boxlist, str4, w, h, imagecount);
                     n += 3;
                 }
             }
-            basenum = n;
-    
+            params.basenum = n;
+
             boxlist -= nx*ny;
             boxlist++;
             free(boxlist);
         }
         free(bmp);
         free(bmp2);
-        
+        free(map);
+
         /* If there is a maximum set */
-        if (maxdiffs > 0)
+        if (params.maxdiffs > 0)
         {
             /* Check to see we haven't exceeded it */
-            maxdiffs--;
-            if (maxdiffs == 0)
+            params.maxdiffs--;
+            if (params.maxdiffs == 0)
             {
                 break;
             }
@@ -1365,19 +2161,19 @@
     if ((bmp2 != NULL) && (bmp == NULL))
     {
         fprintf(stderr, "Failed to load image %d from '%s'\n",
-                imagecount, argv[1]);
+                imagecount, params.filename1);
         exit(EXIT_FAILURE);
     }
     if ((bmp != NULL) && (bmp2 == NULL))
     {
         fprintf(stderr, "Failed to load image %d from '%s'\n",
-                imagecount, argv[2]);
+                imagecount, params.filename2);
         exit(EXIT_FAILURE);
     }
 
     image_close(&image1);
     image_close(&image2);
-    
 
+
     return EXIT_SUCCESS;
 }



More information about the gs-commits mailing list