[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, ¶ms);
+ 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(¶ms, 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, ¶ms);
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, ¶ms);
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