1 /* $Id: tiffcmp.c,v 1.16 2010-03-10 18:56:50 bfriesen Exp $ */ 2 3 /* 4 * Copyright (c) 1988-1997 Sam Leffler 5 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 6 * 7 * Permission to use, copy, modify, distribute, and sell this software and 8 * its documentation for any purpose is hereby granted without fee, provided 9 * that (i) the above copyright notices and this permission notice appear in 10 * all copies of the software and related documentation, and (ii) the names of 11 * Sam Leffler and Silicon Graphics may not be used in any advertising or 12 * publicity relating to the software without the specific, prior written 13 * permission of Sam Leffler and Silicon Graphics. 14 * 15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 18 * 19 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 24 * OF THIS SOFTWARE. 25 */ 26 27 #include "tif_config.h" 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <math.h> 33 34 #ifdef HAVE_UNISTD_H 35 # include <unistd.h> 36 #endif 37 38 #ifdef NEED_LIBPORT 39 # include "libport.h" 40 #endif 41 42 #include "tiffio.h" 43 44 #ifndef HAVE_GETOPT 45 extern int getopt(int, char**, char*); 46 #endif 47 48 static int stopondiff = 1; 49 static int stoponfirsttag = 1; 50 static uint16 bitspersample = 1; 51 static uint16 samplesperpixel = 1; 52 static uint16 sampleformat = SAMPLEFORMAT_UINT; 53 static uint32 imagewidth; 54 static uint32 imagelength; 55 56 static void usage(void); 57 static int tiffcmp(TIFF*, TIFF*); 58 static int cmptags(TIFF*, TIFF*); 59 static int ContigCompare(int, uint32, unsigned char*, unsigned char*, tsize_t); 60 static int SeparateCompare(int, int, uint32, unsigned char*, unsigned char*); 61 static void PrintIntDiff(uint32, int, uint32, uint32, uint32); 62 static void PrintFloatDiff(uint32, int, uint32, double, double); 63 64 static void leof(const char*, uint32, int); 65 66 int 67 main(int argc, char* argv[]) 68 { 69 TIFF *tif1, *tif2; 70 int c, dirnum; 71 extern int optind; 72 extern char* optarg; 73 74 while ((c = getopt(argc, argv, "ltz:")) != -1) 75 switch (c) { 76 case 'l': 77 stopondiff = 0; 78 break; 79 case 'z': 80 stopondiff = atoi(optarg); 81 break; 82 case 't': 83 stoponfirsttag = 0; 84 break; 85 case '?': 86 usage(); 87 /*NOTREACHED*/ 88 } 89 if (argc - optind < 2) 90 usage(); 91 tif1 = TIFFOpen(argv[optind], "r"); 92 if (tif1 == NULL) 93 return (-1); 94 tif2 = TIFFOpen(argv[optind+1], "r"); 95 if (tif2 == NULL) 96 return (-2); 97 dirnum = 0; 98 while (tiffcmp(tif1, tif2)) { 99 if (!TIFFReadDirectory(tif1)) { 100 if (!TIFFReadDirectory(tif2)) 101 break; 102 printf("No more directories for %s\n", 103 TIFFFileName(tif1)); 104 return (1); 105 } else if (!TIFFReadDirectory(tif2)) { 106 printf("No more directories for %s\n", 107 TIFFFileName(tif2)); 108 return (1); 109 } 110 printf("Directory %d:\n", ++dirnum); 111 } 112 113 TIFFClose(tif1); 114 TIFFClose(tif2); 115 return (0); 116 } 117 118 char* stuff[] = { 119 "usage: tiffcmp [options] file1 file2", 120 "where options are:", 121 " -l list each byte of image data that differs between the files", 122 " -z # list specified number of bytes that differs between the files", 123 " -t ignore any differences in directory tags", 124 NULL 125 }; 126 127 static void 128 usage(void) 129 { 130 char buf[BUFSIZ]; 131 int i; 132 133 setbuf(stderr, buf); 134 fprintf(stderr, "%s\n\n", TIFFGetVersion()); 135 for (i = 0; stuff[i] != NULL; i++) 136 fprintf(stderr, "%s\n", stuff[i]); 137 exit(-1); 138 } 139 140 #define checkEOF(tif, row, sample) { \ 141 leof(TIFFFileName(tif), row, sample); \ 142 goto bad; \ 143 } 144 145 static int CheckShortTag(TIFF*, TIFF*, int, char*); 146 static int CheckShort2Tag(TIFF*, TIFF*, int, char*); 147 static int CheckShortArrayTag(TIFF*, TIFF*, int, char*); 148 static int CheckLongTag(TIFF*, TIFF*, int, char*); 149 static int CheckFloatTag(TIFF*, TIFF*, int, char*); 150 static int CheckStringTag(TIFF*, TIFF*, int, char*); 151 152 static int 153 tiffcmp(TIFF* tif1, TIFF* tif2) 154 { 155 uint16 config1, config2; 156 tsize_t size1; 157 uint32 row; 158 tsample_t s; 159 unsigned char *buf1, *buf2; 160 161 if (!CheckShortTag(tif1, tif2, TIFFTAG_BITSPERSAMPLE, "BitsPerSample")) 162 return (0); 163 if (!CheckShortTag(tif1, tif2, TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel")) 164 return (0); 165 if (!CheckLongTag(tif1, tif2, TIFFTAG_IMAGEWIDTH, "ImageWidth")) 166 return (0); 167 if (!cmptags(tif1, tif2)) 168 return (1); 169 (void) TIFFGetField(tif1, TIFFTAG_BITSPERSAMPLE, &bitspersample); 170 (void) TIFFGetField(tif1, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel); 171 (void) TIFFGetField(tif1, TIFFTAG_SAMPLEFORMAT, &sampleformat); 172 (void) TIFFGetField(tif1, TIFFTAG_IMAGEWIDTH, &imagewidth); 173 (void) TIFFGetField(tif1, TIFFTAG_IMAGELENGTH, &imagelength); 174 (void) TIFFGetField(tif1, TIFFTAG_PLANARCONFIG, &config1); 175 (void) TIFFGetField(tif2, TIFFTAG_PLANARCONFIG, &config2); 176 buf1 = (unsigned char *)_TIFFmalloc(size1 = TIFFScanlineSize(tif1)); 177 buf2 = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(tif2)); 178 if (buf1 == NULL || buf2 == NULL) { 179 fprintf(stderr, "No space for scanline buffers\n"); 180 exit(-1); 181 } 182 if (config1 != config2 && bitspersample != 8 && samplesperpixel > 1) { 183 fprintf(stderr, 184 "Can't handle different planar configuration w/ different bits/sample\n"); 185 goto bad; 186 } 187 #define pack(a,b) ((a)<<8)|(b) 188 switch (pack(config1, config2)) { 189 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG): 190 for (row = 0; row < imagelength; row++) { 191 if (TIFFReadScanline(tif2, buf2, row, 0) < 0) 192 checkEOF(tif2, row, -1) 193 for (s = 0; s < samplesperpixel; s++) { 194 if (TIFFReadScanline(tif1, buf1, row, s) < 0) 195 checkEOF(tif1, row, s) 196 if (SeparateCompare(1, s, row, buf2, buf1) < 0) 197 goto bad1; 198 } 199 } 200 break; 201 case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE): 202 for (row = 0; row < imagelength; row++) { 203 if (TIFFReadScanline(tif1, buf1, row, 0) < 0) 204 checkEOF(tif1, row, -1) 205 for (s = 0; s < samplesperpixel; s++) { 206 if (TIFFReadScanline(tif2, buf2, row, s) < 0) 207 checkEOF(tif2, row, s) 208 if (SeparateCompare(0, s, row, buf1, buf2) < 0) 209 goto bad1; 210 } 211 } 212 break; 213 case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE): 214 for (s = 0; s < samplesperpixel; s++) 215 for (row = 0; row < imagelength; row++) { 216 if (TIFFReadScanline(tif1, buf1, row, s) < 0) 217 checkEOF(tif1, row, s) 218 if (TIFFReadScanline(tif2, buf2, row, s) < 0) 219 checkEOF(tif2, row, s) 220 if (ContigCompare(s, row, buf1, buf2, size1) < 0) 221 goto bad1; 222 } 223 break; 224 case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG): 225 for (row = 0; row < imagelength; row++) { 226 if (TIFFReadScanline(tif1, buf1, row, 0) < 0) 227 checkEOF(tif1, row, -1) 228 if (TIFFReadScanline(tif2, buf2, row, 0) < 0) 229 checkEOF(tif2, row, -1) 230 if (ContigCompare(-1, row, buf1, buf2, size1) < 0) 231 goto bad1; 232 } 233 break; 234 } 235 if (buf1) _TIFFfree(buf1); 236 if (buf2) _TIFFfree(buf2); 237 return (1); 238 bad: 239 if (stopondiff) 240 exit(1); 241 bad1: 242 if (buf1) _TIFFfree(buf1); 243 if (buf2) _TIFFfree(buf2); 244 return (0); 245 } 246 247 #define CmpShortField(tag, name) \ 248 if (!CheckShortTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 249 #define CmpShortField2(tag, name) \ 250 if (!CheckShort2Tag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 251 #define CmpLongField(tag, name) \ 252 if (!CheckLongTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 253 #define CmpFloatField(tag, name) \ 254 if (!CheckFloatTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 255 #define CmpStringField(tag, name) \ 256 if (!CheckStringTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 257 #define CmpShortArrayField(tag, name) \ 258 if (!CheckShortArrayTag(tif1, tif2, tag, name) && stoponfirsttag) return (0) 259 260 static int 261 cmptags(TIFF* tif1, TIFF* tif2) 262 { 263 CmpLongField(TIFFTAG_SUBFILETYPE, "SubFileType"); 264 CmpLongField(TIFFTAG_IMAGEWIDTH, "ImageWidth"); 265 CmpLongField(TIFFTAG_IMAGELENGTH, "ImageLength"); 266 CmpShortField(TIFFTAG_BITSPERSAMPLE, "BitsPerSample"); 267 CmpShortField(TIFFTAG_COMPRESSION, "Compression"); 268 CmpShortField(TIFFTAG_PREDICTOR, "Predictor"); 269 CmpShortField(TIFFTAG_PHOTOMETRIC, "PhotometricInterpretation"); 270 CmpShortField(TIFFTAG_THRESHHOLDING, "Thresholding"); 271 CmpShortField(TIFFTAG_FILLORDER, "FillOrder"); 272 CmpShortField(TIFFTAG_ORIENTATION, "Orientation"); 273 CmpShortField(TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel"); 274 CmpShortField(TIFFTAG_MINSAMPLEVALUE, "MinSampleValue"); 275 CmpShortField(TIFFTAG_MAXSAMPLEVALUE, "MaxSampleValue"); 276 CmpShortField(TIFFTAG_SAMPLEFORMAT, "SampleFormat"); 277 CmpFloatField(TIFFTAG_XRESOLUTION, "XResolution"); 278 CmpFloatField(TIFFTAG_YRESOLUTION, "YResolution"); 279 CmpLongField(TIFFTAG_GROUP3OPTIONS, "Group3Options"); 280 CmpLongField(TIFFTAG_GROUP4OPTIONS, "Group4Options"); 281 CmpShortField(TIFFTAG_RESOLUTIONUNIT, "ResolutionUnit"); 282 CmpShortField(TIFFTAG_PLANARCONFIG, "PlanarConfiguration"); 283 CmpLongField(TIFFTAG_ROWSPERSTRIP, "RowsPerStrip"); 284 CmpFloatField(TIFFTAG_XPOSITION, "XPosition"); 285 CmpFloatField(TIFFTAG_YPOSITION, "YPosition"); 286 CmpShortField(TIFFTAG_GRAYRESPONSEUNIT, "GrayResponseUnit"); 287 CmpShortField(TIFFTAG_COLORRESPONSEUNIT, "ColorResponseUnit"); 288 #ifdef notdef 289 { uint16 *graycurve; 290 CmpField(TIFFTAG_GRAYRESPONSECURVE, graycurve); 291 } 292 { uint16 *red, *green, *blue; 293 CmpField3(TIFFTAG_COLORRESPONSECURVE, red, green, blue); 294 } 295 { uint16 *red, *green, *blue; 296 CmpField3(TIFFTAG_COLORMAP, red, green, blue); 297 } 298 #endif 299 CmpShortField2(TIFFTAG_PAGENUMBER, "PageNumber"); 300 CmpStringField(TIFFTAG_ARTIST, "Artist"); 301 CmpStringField(TIFFTAG_IMAGEDESCRIPTION,"ImageDescription"); 302 CmpStringField(TIFFTAG_MAKE, "Make"); 303 CmpStringField(TIFFTAG_MODEL, "Model"); 304 CmpStringField(TIFFTAG_SOFTWARE, "Software"); 305 CmpStringField(TIFFTAG_DATETIME, "DateTime"); 306 CmpStringField(TIFFTAG_HOSTCOMPUTER, "HostComputer"); 307 CmpStringField(TIFFTAG_PAGENAME, "PageName"); 308 CmpStringField(TIFFTAG_DOCUMENTNAME, "DocumentName"); 309 CmpShortField(TIFFTAG_MATTEING, "Matteing"); 310 CmpShortArrayField(TIFFTAG_EXTRASAMPLES,"ExtraSamples"); 311 return (1); 312 } 313 314 static int 315 ContigCompare(int sample, uint32 row, 316 unsigned char* p1, unsigned char* p2, tsize_t size) 317 { 318 uint32 pix; 319 int ppb = 8 / bitspersample; 320 int samples_to_test; 321 322 if (memcmp(p1, p2, size) == 0) 323 return 0; 324 325 samples_to_test = (sample == -1) ? samplesperpixel : 1; 326 327 switch (bitspersample) { 328 case 1: case 2: case 4: case 8: 329 { 330 unsigned char *pix1 = p1, *pix2 = p2; 331 332 for (pix = 0; pix < imagewidth; pix += ppb) { 333 int s; 334 335 for(s = 0; s < samples_to_test; s++) { 336 if (*pix1 != *pix2) { 337 if( sample == -1 ) 338 PrintIntDiff(row, s, pix, *pix1, *pix2); 339 else 340 PrintIntDiff(row, sample, pix, *pix1, *pix2); 341 } 342 343 pix1++; 344 pix2++; 345 } 346 } 347 break; 348 } 349 case 16: 350 { 351 uint16 *pix1 = (uint16 *)p1, *pix2 = (uint16 *)p2; 352 353 for (pix = 0; pix < imagewidth; pix++) { 354 int s; 355 356 for(s = 0; s < samples_to_test; s++) { 357 if (*pix1 != *pix2) 358 PrintIntDiff(row, sample, pix, *pix1, *pix2); 359 360 pix1++; 361 pix2++; 362 } 363 } 364 break; 365 } 366 case 32: 367 if (sampleformat == SAMPLEFORMAT_UINT 368 || sampleformat == SAMPLEFORMAT_INT) { 369 uint32 *pix1 = (uint32 *)p1, *pix2 = (uint32 *)p2; 370 371 for (pix = 0; pix < imagewidth; pix++) { 372 int s; 373 374 for(s = 0; s < samples_to_test; s++) { 375 if (*pix1 != *pix2) { 376 PrintIntDiff(row, sample, pix, 377 *pix1, *pix2); 378 } 379 380 pix1++; 381 pix2++; 382 } 383 } 384 } else if (sampleformat == SAMPLEFORMAT_IEEEFP) { 385 float *pix1 = (float *)p1, *pix2 = (float *)p2; 386 387 for (pix = 0; pix < imagewidth; pix++) { 388 int s; 389 390 for(s = 0; s < samples_to_test; s++) { 391 if (fabs(*pix1 - *pix2) < 0.000000000001) { 392 PrintFloatDiff(row, sample, pix, 393 *pix1, *pix2); 394 } 395 396 pix1++; 397 pix2++; 398 } 399 } 400 } else { 401 fprintf(stderr, "Sample format %d is not supported.\n", 402 sampleformat); 403 return -1; 404 } 405 break; 406 default: 407 fprintf(stderr, "Bit depth %d is not supported.\n", bitspersample); 408 return -1; 409 } 410 411 return 0; 412 } 413 414 static void 415 PrintIntDiff(uint32 row, int sample, uint32 pix, uint32 w1, uint32 w2) 416 { 417 if (sample < 0) 418 sample = 0; 419 switch (bitspersample) { 420 case 1: 421 case 2: 422 case 4: 423 { 424 int32 mask1, mask2, s; 425 426 mask1 = ~((-1) << bitspersample); 427 s = (8 - bitspersample); 428 mask2 = mask1 << s; 429 for (; mask2 && pix < imagewidth; 430 mask2 >>= bitspersample, s -= bitspersample, pix++) { 431 if ((w1 & mask2) ^ (w2 & mask2)) { 432 printf( 433 "Scanline %lu, pixel %lu, sample %d: %01x %01x\n", 434 (unsigned long) row, 435 (unsigned long) pix, 436 sample, 437 (unsigned int)((w1 >> s) & mask1), 438 (unsigned int)((w2 >> s) & mask1)); 439 if (--stopondiff == 0) 440 exit(1); 441 } 442 } 443 break; 444 } 445 case 8: 446 printf("Scanline %lu, pixel %lu, sample %d: %02x %02x\n", 447 (unsigned long) row, (unsigned long) pix, sample, 448 (unsigned int) w1, (unsigned int) w2); 449 if (--stopondiff == 0) 450 exit(1); 451 break; 452 case 16: 453 printf("Scanline %lu, pixel %lu, sample %d: %04x %04x\n", 454 (unsigned long) row, (unsigned long) pix, sample, 455 (unsigned int) w1, (unsigned int) w2); 456 if (--stopondiff == 0) 457 exit(1); 458 break; 459 case 32: 460 printf("Scanline %lu, pixel %lu, sample %d: %08x %08x\n", 461 (unsigned long) row, (unsigned long) pix, sample, 462 (unsigned int) w1, (unsigned int) w2); 463 if (--stopondiff == 0) 464 exit(1); 465 break; 466 default: 467 break; 468 } 469 } 470 471 static void 472 PrintFloatDiff(uint32 row, int sample, uint32 pix, double w1, double w2) 473 { 474 if (sample < 0) 475 sample = 0; 476 switch (bitspersample) { 477 case 32: 478 printf("Scanline %lu, pixel %lu, sample %d: %g %g\n", 479 (long) row, (long) pix, sample, w1, w2); 480 if (--stopondiff == 0) 481 exit(1); 482 break; 483 default: 484 break; 485 } 486 } 487 488 static int 489 SeparateCompare(int reversed, int sample, uint32 row, 490 unsigned char* cp1, unsigned char* p2) 491 { 492 uint32 npixels = imagewidth; 493 int pixel; 494 495 cp1 += sample; 496 for (pixel = 0; npixels-- > 0; pixel++, cp1 += samplesperpixel, p2++) { 497 if (*cp1 != *p2) { 498 printf("Scanline %lu, pixel %lu, sample %ld: ", 499 (long) row, (long) pixel, (long) sample); 500 if (reversed) 501 printf("%02x %02x\n", *p2, *cp1); 502 else 503 printf("%02x %02x\n", *cp1, *p2); 504 if (--stopondiff == 0) 505 exit(1); 506 } 507 } 508 509 return 0; 510 } 511 512 static int 513 checkTag(TIFF* tif1, TIFF* tif2, int tag, char* name, void* p1, void* p2) 514 { 515 516 if (TIFFGetField(tif1, tag, p1)) { 517 if (!TIFFGetField(tif2, tag, p2)) { 518 printf("%s tag appears only in %s\n", 519 name, TIFFFileName(tif1)); 520 return (0); 521 } 522 return (1); 523 } else if (TIFFGetField(tif2, tag, p2)) { 524 printf("%s tag appears only in %s\n", name, TIFFFileName(tif2)); 525 return (0); 526 } 527 return (-1); 528 } 529 530 #define CHECK(cmp, fmt) { \ 531 switch (checkTag(tif1,tif2,tag,name,&v1,&v2)) { \ 532 case 1: if (cmp) \ 533 case -1: return (1); \ 534 printf(fmt, name, v1, v2); \ 535 } \ 536 return (0); \ 537 } 538 539 static int 540 CheckShortTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 541 { 542 uint16 v1, v2; 543 CHECK(v1 == v2, "%s: %u %u\n"); 544 } 545 546 static int 547 CheckShort2Tag(TIFF* tif1, TIFF* tif2, int tag, char* name) 548 { 549 uint16 v11, v12, v21, v22; 550 551 if (TIFFGetField(tif1, tag, &v11, &v12)) { 552 if (!TIFFGetField(tif2, tag, &v21, &v22)) { 553 printf("%s tag appears only in %s\n", 554 name, TIFFFileName(tif1)); 555 return (0); 556 } 557 if (v11 == v21 && v12 == v22) 558 return (1); 559 printf("%s: <%u,%u> <%u,%u>\n", name, v11, v12, v21, v22); 560 } else if (TIFFGetField(tif2, tag, &v21, &v22)) 561 printf("%s tag appears only in %s\n", name, TIFFFileName(tif2)); 562 else 563 return (1); 564 return (0); 565 } 566 567 static int 568 CheckShortArrayTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 569 { 570 uint16 n1, *a1; 571 uint16 n2, *a2; 572 573 if (TIFFGetField(tif1, tag, &n1, &a1)) { 574 if (!TIFFGetField(tif2, tag, &n2, &a2)) { 575 printf("%s tag appears only in %s\n", 576 name, TIFFFileName(tif1)); 577 return (0); 578 } 579 if (n1 == n2) { 580 char* sep; 581 uint16 i; 582 583 if (memcmp(a1, a2, n1 * sizeof(uint16)) == 0) 584 return (1); 585 printf("%s: value mismatch, <%u:", name, n1); 586 sep = ""; 587 for (i = 0; i < n1; i++) 588 printf("%s%u", sep, a1[i]), sep = ","; 589 printf("> and <%u: ", n2); 590 sep = ""; 591 for (i = 0; i < n2; i++) 592 printf("%s%u", sep, a2[i]), sep = ","; 593 printf(">\n"); 594 } else 595 printf("%s: %u items in %s, %u items in %s", name, 596 n1, TIFFFileName(tif1), 597 n2, TIFFFileName(tif2) 598 ); 599 } else if (TIFFGetField(tif2, tag, &n2, &a2)) 600 printf("%s tag appears only in %s\n", name, TIFFFileName(tif2)); 601 else 602 return (1); 603 return (0); 604 } 605 606 static int 607 CheckLongTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 608 { 609 uint32 v1, v2; 610 CHECK(v1 == v2, "%s: %u %u\n"); 611 } 612 613 static int 614 CheckFloatTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 615 { 616 float v1, v2; 617 CHECK(v1 == v2, "%s: %g %g\n"); 618 } 619 620 static int 621 CheckStringTag(TIFF* tif1, TIFF* tif2, int tag, char* name) 622 { 623 char *v1, *v2; 624 CHECK(strcmp(v1, v2) == 0, "%s: \"%s\" \"%s\"\n"); 625 } 626 627 static void 628 leof(const char* name, uint32 row, int s) 629 { 630 631 printf("%s: EOF at scanline %lu", name, (unsigned long)row); 632 if (s >= 0) 633 printf(", sample %d", s); 634 printf("\n"); 635 } 636 637 /* vim: set ts=8 sts=8 sw=8 noet: */ 638 /* 639 * Local Variables: 640 * mode: c 641 * c-basic-offset: 8 642 * fill-column: 78 643 * End: 644 */ 645