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