ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/util/radcompare.c
Revision: 2.11
Committed: Fri Oct 19 20:32:16 2018 UTC (5 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.10: +32 -6 lines
Log Message:
Version with line backtracking for word boundaries

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: radcompare.c,v 2.10 2018/10/17 17:39:23 greg Exp $";
3 #endif
4 /*
5 * Compare Radiance files for significant differences
6 *
7 * G. Ward
8 */
9
10 #include <stdlib.h>
11 #include <math.h>
12 #include <ctype.h>
13 #include "platform.h"
14 #include "rtio.h"
15 #include "resolu.h"
16 #include "color.h"
17 #include "lookup.h"
18 /* Reporting levels */
19 #define REP_QUIET 0 /* no reporting */
20 #define REP_ERROR 1 /* report errors only */
21 #define REP_WARN 2 /* report warnings as well */
22 #define REP_VERBOSE 3 /* verbose reporting */
23
24 int report = REP_WARN; /* reporting level */
25
26 int ign_header = 0; /* ignore header differences? */
27
28 double rel_min = 1e-5; /* positive for relative comparisons */
29
30 double rms_lim = 0.01; /* RMS difference limit */
31
32 double max_lim = 0.25; /* difference limit if non-negative */
33
34 int lin1cnt=0, lin2cnt=0; /* file line position */
35
36 const char nsuffix[10][3] = { /* 1st, 2nd, 3rd, etc. */
37 "th","st","nd","rd","th","th","th","th","th","th"
38 };
39 #define num_sfx(n) nsuffix[(n)%10]
40
41 /* file types */
42 const char *file_type[] = {
43 "Unrecognized",
44 "TEXT_generic",
45 "ascii",
46 COLRFMT,
47 CIEFMT,
48 "float",
49 "double",
50 "BSDF_RBFmesh",
51 "Radiance_octree",
52 "Radiance_tmesh",
53 "BINARY_unknown",
54 NULL /* terminator */
55 };
56 /* keep consistent with above */
57 enum {TYP_UNKNOWN, TYP_TEXT, TYP_ASCII, TYP_RGBE, TYP_XYZE, TYP_FLOAT,
58 TYP_DOUBLE, TYP_RBFMESH, TYP_OCTREE, TYP_TMESH, TYP_BINARY};
59
60 #define has_header(t) (!( 1L<<(t) & (1L<<TYP_TEXT | 1L<<TYP_BINARY) ))
61
62 /* header variables to always ignore */
63 const char *hdr_ignkey[] = {
64 "SOFTWARE",
65 "CAPDATE",
66 "GMT",
67 NULL /* terminator */
68 };
69 /* header variable settings */
70 LUTAB hdr1 = LU_SINIT(free,free);
71 LUTAB hdr2 = LU_SINIT(free,free);
72
73 /* advance appropriate file line count */
74 #define adv_linecnt(htp) (lin1cnt += (htp == &hdr1), \
75 lin2cnt += (htp == &hdr2))
76
77 /* input files */
78 char *progname = NULL;
79 const char stdin_name[] = "<stdin>";
80 const char *f1name=NULL, *f2name=NULL;
81 FILE *f1in=NULL, *f2in=NULL;
82
83 /* running real differences */
84 double diff2sum = 0;
85 long nsum = 0;
86
87 /* Report usage and exit */
88 static void
89 usage()
90 {
91 fputs("Usage: ", stderr);
92 fputs(progname, stderr);
93 fputs(" [-h][-s|-w|-v][-rel min_test][-rms epsilon][-max epsilon] reference test\n",
94 stderr);
95 exit(2);
96 }
97
98 /* Get type ID from name (or 0 if not found) */
99 static int
100 xlate_type(const char *nm)
101 {
102 int i;
103
104 if (!nm || !*nm)
105 return(TYP_UNKNOWN);
106 for (i = 1; file_type[i]; i++)
107 if (!strcmp(nm, file_type[i]))
108 return(i);
109 return(TYP_UNKNOWN);
110 }
111
112 /* Compare real values and keep track of differences */
113 static int
114 real_check(double r1, double r2)
115 {
116 double diff2 = (r1 - r2)*(r1 - r2);
117
118 if (rel_min > 0) { /* doing relative differences? */
119 double av2 = .25*(r1*r1 + 2.*fabs(r1*r2) + r2*r2);
120 if (av2 > rel_min*rel_min)
121 diff2 /= av2;
122 }
123 if (max_lim >= 0 && diff2 > max_lim*max_lim) {
124 if (report != REP_QUIET)
125 printf(
126 "%s: %sdifference between %.8g and %.8g exceeds epsilon of %.8g\n",
127 progname,
128 (rel_min > 0) ? "relative " : "",
129 r1, r2, max_lim);
130 return(0);
131 }
132 diff2sum += diff2;
133 nsum++;
134 return(1);
135 }
136
137 /* Compare two color values for equivalence */
138 static int
139 color_check(COLOR c1, COLOR c2)
140 {
141 int p;
142
143 if (!real_check(colval(c1,RED)+colval(c1,GRN)+colval(c1,BLU)*(1./3.),
144 colval(c2,RED)+colval(c2,GRN)+colval(c2,BLU))*(1./3.))
145 return(0);
146
147 p = (colval(c1,GRN) > colval(c1,RED)) ? GRN : RED;
148 if (colval(c1,BLU) > colval(c1,p)) p = BLU;
149
150 return(real_check(colval(c1,p), colval(c2,p)));
151 }
152
153 /* Compare two strings for equivalence */
154 static int
155 equiv_string(char *s1, char *s2)
156 {
157 #define CLS_STR 0
158 #define CLS_INT 1
159 #define CLS_FLT 2
160 /* skip whitespace at beginning */
161 while (isspace(*s1)) s1++;
162 while (isspace(*s2)) s2++;
163 while (*s1) { /* check each word */
164 int inquote;
165 if (!*s2) /* unexpected EOL in s2? */
166 return(0);
167 inquote = *s1;
168 if ((inquote != '\'') & (inquote != '"'))
169 inquote = 0;
170 if (inquote) { /* quoted text must match exactly */
171 if (*s1++ != *s2++)
172 return(0);
173 while (*s1 != inquote) {
174 if (!*s1)
175 return(0);
176 if (*s1++ != *s2++)
177 return(0);
178 }
179 s1++;
180 if (*s2++ != inquote)
181 return(0);
182 } else { /* else classify word type */
183 char *s1s = s1;
184 char *s2s = s2;
185 int cls = CLS_STR;
186 s1 = sskip(s1);
187 s2 = sskip(s2);
188 if (iskip(s1s) == s1) {
189 if (iskip(s2s) == s2)
190 cls = CLS_INT;
191 else if (fskip(s2s) == s2)
192 cls = CLS_FLT;
193 } else if (fskip(s1s) == s1) {
194 if (fskip(s2s) != s2)
195 return(0);
196 cls = CLS_FLT;
197 }
198 switch (cls) {
199 case CLS_INT: /* strncmp() faster */
200 case CLS_STR:
201 if (s1 - s1s != s2 - s2s)
202 return(0);
203 if (strncmp(s1s, s2s, s1 - s1s))
204 return(0);
205 break;
206 case CLS_FLT:
207 if (!real_check(atof(s1s), atof(s2s)))
208 return(0);
209 break;
210 }
211 }
212 while (isspace(*s1)) s1++;
213 while (isspace(*s2)) s2++;
214 }
215 return(!*s2); /* match if we reached the end of s2, too */
216 #undef CLS_STR
217 #undef CLS_INT
218 #undef CLS_FLT
219 }
220
221 /* Check if string is var=value pair and set if not in ignore list */
222 static int
223 setheadvar(char *val, void *p)
224 {
225 LUTAB *htp = (LUTAB *)p;
226 LUENT *tep;
227 char *key;
228 int kln, vln;
229 int n;
230
231 adv_linecnt(htp); /* side-effect is to count lines */
232 if (!isalpha(*val)) /* key must start line */
233 return(0);
234 key = val++;
235 while (*val && !isspace(*val) & (*val != '='))
236 val++;
237 kln = val - key;
238 while (isspace(*val)) /* check for value */
239 *val++ = '\0';
240 if (*val != '=')
241 return(0);
242 *val++ = '\0';
243 while (isspace(*val))
244 val++;
245 if (!*val) /* nothing set? */
246 return(0);
247 /* check if key to ignore */
248 for (n = 0; hdr_ignkey[n]; n++)
249 if (!strcmp(key, hdr_ignkey[n]))
250 return(0);
251 vln = strlen(val); /* eliminate space and newline at end */
252 while (isspace(val[--vln]))
253 ;
254 val[++vln] = '\0';
255 if (!(tep = lu_find(htp, key)))
256 return(-1); /* memory allocation error */
257 if (!tep->key)
258 tep->key = strcpy(malloc(kln+1), key);
259 if (tep->data)
260 free(tep->data);
261 tep->data = strcpy(malloc(vln+1), val);
262 return(1);
263 }
264
265 /* Lookup correspondent in other header */
266 static int
267 match_val(const LUENT *ep1, void *p2)
268 {
269 const LUENT *ep2 = lu_find((LUTAB *)p2, ep1->key);
270 if (!ep2 || !ep2->data) {
271 if (report != REP_QUIET)
272 printf("%s: variable '%s' missing in '%s'\n",
273 progname, ep1->key, f2name);
274 return(-1);
275 }
276 if (!equiv_string((char *)ep1->data, (char *)ep2->data)) {
277 if (report != REP_QUIET) {
278 printf("%s: header variable '%s' has different values\n",
279 progname, ep1->key);
280 if (report >= REP_VERBOSE) {
281 printf("%s: %s=%s\n", f1name,
282 ep1->key, (char *)ep1->data);
283 printf("%s: %s=%s\n", f2name,
284 ep2->key, (char *)ep2->data);
285 }
286 }
287 return(-1);
288 }
289 return(1); /* good match */
290 }
291
292 /* Compare two sets of header variables */
293 static int
294 headers_match()
295 {
296 int ne = lu_doall(&hdr1, match_val, &hdr2);
297 if (ne < 0)
298 return(0); /* something didn't match! */
299 /* non-fatal if second header has extra */
300 if (report >= REP_WARN && (ne = lu_doall(&hdr2, NULL, NULL) - ne))
301 printf("%s: warning - '%s' has %d extra header setting(s)\n",
302 progname, f2name, ne);
303 return(1); /* good match */
304 }
305
306 /* Check generic input to determine if it is binary, -1 on error */
307 static int
308 input_is_binary(FILE *fin)
309 {
310 int n = 0;
311 int c = 0;
312
313 while ((c = getc(fin)) != EOF) {
314 ++n;
315 if (!c | (c > 127))
316 break; /* non-ascii character */
317 if (n >= 10240)
318 break; /* enough to be confident */
319 }
320 if (!n)
321 return(-1); /* first read failed */
322 if (fseek(fin, 0L, 0) < 0)
323 return(-1); /* rewind failed */
324 return(!c | (c > 127));
325 }
326
327 /* Identify and return data type from header (if one) */
328 static int
329 identify_type(const char *name, FILE *fin, LUTAB *htp)
330 {
331 extern const char HDRSTR[];
332 int c;
333 /* check magic header start */
334 if ((c = getc(fin)) != HDRSTR[0]) {
335 if (c == EOF) goto badeof;
336 ungetc(c, fin);
337 c = 0;
338 } else if ((c = getc(fin)) != HDRSTR[1]) {
339 if (c == EOF) goto badeof;
340 ungetc(c, fin); ungetc(HDRSTR[0], fin);
341 c = 0;
342 }
343 if (c) { /* appears to have a header */
344 char sbuf[32];
345 if (!fgets(sbuf, sizeof(sbuf), fin))
346 goto badeof;
347 adv_linecnt(htp); /* for #?ID string */
348 if (report >= REP_WARN && strncmp(sbuf, "RADIANCE", 8)) {
349 fputs(name, stdout);
350 fputs(": warning - unexpected header ID: ", stdout);
351 fputs(sbuf, stdout);
352 }
353 if (getheader(fin, setheadvar, htp) < 0) {
354 fputs(name, stderr);
355 fputs(": unknown error reading header\n", stderr);
356 return(-1);
357 }
358 adv_linecnt(htp); /* for trailing emtpy line */
359 return(xlate_type((const char *)lu_find(htp,"FORMAT")->data));
360 }
361 c = input_is_binary(fin); /* else peek to see if binary */
362 if (c < 0) {
363 fputs(name, stderr);
364 fputs(": read/seek error\n", stderr);
365 return(-1);
366 }
367 if (c)
368 return(TYP_BINARY);
369 SET_FILE_TEXT(fin); /* originally set to binary */
370 return(TYP_TEXT);
371 badeof:
372 if (report != REP_QUIET) {
373 fputs(name, stdout);
374 fputs(": unexpected end-of-file\n", stdout);
375 }
376 return(-1);
377 }
378
379 /* Check that overall RMS error is below threshold */
380 static int
381 good_RMS()
382 {
383 if (!nsum)
384 return(1);
385 if (diff2sum/(double)nsum > rms_lim*rms_lim) {
386 if (report != REP_QUIET)
387 printf(
388 "%s: %sRMS difference between '%s' and '%s' of %.5g exceeds limit of %.5g\n",
389 progname,
390 (rel_min > 0) ? "relative " : "",
391 f1name, f2name,
392 sqrt(diff2sum/(double)nsum), rms_lim);
393 return(0);
394 }
395 if (report >= REP_VERBOSE)
396 printf("%s: %sRMS difference of reals in '%s' and '%s' is %.5g\n",
397 progname, (rel_min > 0) ? "relative " : "",
398 f1name, f2name, sqrt(diff2sum/(double)nsum));
399 return(1);
400 }
401
402 /* Compare two inputs as generic binary files */
403 static int
404 compare_binary()
405 {
406 int c1=0, c2=0;
407
408 if (report >= REP_VERBOSE) {
409 fputs(progname, stdout);
410 fputs(": comparing inputs as binary\n", stdout);
411 }
412 for ( ; ; ) { /* exact byte matching */
413 c1 = getc(f1in);
414 c2 = getc(f2in);
415 if (c1 == EOF) {
416 if (c2 == EOF)
417 return(1); /* success! */
418 if (report != REP_QUIET) {
419 fputs(f1name, stdout);
420 fputs(": unexpected end-of-file\n", stdout);
421 }
422 return(0);
423 }
424 if (c2 == EOF) {
425 if (report != REP_QUIET) {
426 fputs(f2name, stdout);
427 fputs(": unexpected end-of-file\n", stdout);
428 }
429 return(0);
430 }
431 if (c1 != c2)
432 break; /* quit and report difference */
433 }
434 if (report == REP_QUIET)
435 return(0);
436 printf("%s: binary files '%s' and '%s' differ at byte offset %ld|%ld\n",
437 progname, f1name, f2name, ftell(f1in), ftell(f2in));
438 if (report >= REP_VERBOSE)
439 printf("%s: byte in '%s' is 0x%X, byte in '%s' is 0x%X\n",
440 progname, f1name, c1, f2name, c2);
441 return(0);
442 }
443
444 /* If line is continued (no newline), then back up to word boundary if one */
445 static int
446 leftover(char *buf)
447 {
448 int minlen = strlen(buf);
449 char *bend = buf + minlen;
450 char *cp = bend-1;
451
452 if (*cp == '\r') *cp = '\n'; /* AARG Windoze! */
453 if (*cp == '\n') /* complete line? */
454 return(0);
455
456 minlen >>= 2; /* back over partial word */
457 while (!isspace(*cp))
458 if (--cp <= buf+minlen)
459 return(0);
460 *cp++ = '\0'; /* break line here */
461 return(bend - cp);
462 }
463
464 /* Compare two inputs as generic text files */
465 static int
466 compare_text()
467 {
468 char l1buf[4096], l2buf[4096];
469 int l1over=0, l2over=0;
470
471 if (report >= REP_VERBOSE) {
472 fputs(progname, stdout);
473 fputs(": comparing inputs as ASCII text\n", stdout);
474 }
475 /* compare a line at a time */
476 while (fgets(l1buf+l1over, sizeof(l1buf)-l1over, f1in)) {
477 lin1cnt += !(l1over = leftover(l1buf));
478 if (!*sskip2(l1buf,0)) {
479 memmove(l1buf, l1buf+sizeof(l1buf)-l1over, l1over);
480 continue; /* ignore empty lines */
481 }
482 while (fgets(l2buf+l2over, sizeof(l2buf)-l2over, f2in)) {
483 lin2cnt += !(l2over = leftover(l2buf));
484 if (*sskip2(l2buf,0))
485 break; /* found other non-empty line */
486 memmove(l2buf, l2buf+sizeof(l2buf)-l2over, l2over);
487 }
488 if (feof(f2in)) {
489 if (report != REP_QUIET) {
490 fputs(f2name, stdout);
491 fputs(": unexpected end-of-file\n", stdout);
492 }
493 return(0);
494 }
495 /* compare non-empty lines */
496 if (!equiv_string(l1buf, l2buf)) {
497 if (report != REP_QUIET) {
498 printf("%s: inputs '%s' and '%s' differ at line %d|%d\n",
499 progname, f1name, f2name,
500 lin1cnt, lin2cnt);
501 if (report >= REP_VERBOSE) {
502 fputs("------------- Mismatch -------------\n", stdout);
503 printf("%s@%d:\t%s", f1name,
504 lin1cnt, l1buf);
505 printf("%s@%d:\t%s", f2name,
506 lin2cnt, l2buf);
507 }
508 }
509 return(0);
510 }
511 if (l1over) memmove(l1buf, l1buf+sizeof(l1buf)-l1over, l1over);
512 if (l2over) memmove(l2buf, l2buf+sizeof(l2buf)-l2over, l2over);
513 }
514 /* check for EOF on input 2 */
515 while (fgets(l2buf, sizeof(l2buf), f2in)) {
516 if (!*sskip2(l2buf,0))
517 continue;
518 if (report != REP_QUIET) {
519 fputs(f1name, stdout);
520 fputs(": unexpected end-of-file\n", stdout);
521 }
522 return(0);
523 }
524 return(good_RMS()); /* final check for reals */
525 }
526
527 /* Compare two inputs that are known to be RGBE or XYZE images */
528 static int
529 compare_hdr()
530 {
531 RESOLU rs1, rs2;
532 COLOR *scan1, *scan2;
533 int x, y;
534
535 if (report >= REP_VERBOSE) {
536 fputs(progname, stdout);
537 fputs(": comparing inputs as HDR images\n", stdout);
538 }
539 fgetsresolu(&rs1, f1in);
540 fgetsresolu(&rs2, f2in);
541 if (rs1.rt != rs2.rt) {
542 if (report != REP_QUIET)
543 printf(
544 "%s: Images '%s' and '%s' have different pixel ordering\n",
545 progname, f1name, f2name);
546 return(0);
547 }
548 if ((rs1.xr != rs2.xr) | (rs1.yr != rs2.yr)) {
549 if (report != REP_QUIET)
550 printf(
551 "%s: Images '%s' and '%s' are different sizes\n",
552 progname, f1name, f2name);
553 return(0);
554 }
555 scan1 = (COLOR *)malloc(scanlen(&rs1)*sizeof(COLOR));
556 scan2 = (COLOR *)malloc(scanlen(&rs2)*sizeof(COLOR));
557 if (!scan1 | !scan2) {
558 fprintf(stderr, "%s: out of memory in compare_hdr()\n", progname);
559 exit(2);
560 }
561 for (y = 0; y < numscans(&rs1); y++) {
562 if ((freadscan(scan1, scanlen(&rs1), f1in) < 0) |
563 (freadscan(scan2, scanlen(&rs2), f2in) < 0)) {
564 if (report != REP_QUIET)
565 printf("%s: unexpected end-of-file\n",
566 progname);
567 free(scan1);
568 free(scan2);
569 return(0);
570 }
571 for (x = 0; x < scanlen(&rs1); x++) {
572 if (color_check(scan1[x], scan2[x]))
573 continue;
574 if (report != REP_QUIET) {
575 printf(
576 "%s: pixels at scanline %d offset %d differ\n",
577 progname, y, x);
578 if (report >= REP_VERBOSE) {
579 printf("%s: (R,G,B)=(%g,%g,%g)\n",
580 f1name, colval(scan1[x],RED),
581 colval(scan1[x],GRN),
582 colval(scan1[x],BLU));
583 printf("%s: (R,G,B)=(%g,%g,%g)\n",
584 f2name, colval(scan2[x],RED),
585 colval(scan2[x],GRN),
586 colval(scan2[x],BLU));
587 }
588 }
589 free(scan1);
590 free(scan2);
591 return(0);
592 }
593 }
594 free(scan1);
595 free(scan2);
596 return(good_RMS()); /* final check of RMS */
597 }
598
599 /* Compare two inputs that are known to be 32-bit floating-point data */
600 static int
601 compare_float()
602 {
603 long nread = 0;
604 float f1, f2;
605
606 if (report >= REP_VERBOSE) {
607 fputs(progname, stdout);
608 fputs(": comparing inputs as 32-bit IEEE floats\n", stdout);
609 }
610 while (getbinary(&f1, sizeof(f1), 1, f1in)) {
611 if (!getbinary(&f2, sizeof(f2), 1, f2in))
612 goto badeof;
613 ++nread;
614 if (real_check(f1, f2))
615 continue;
616 if (report != REP_QUIET)
617 printf("%s: %ld%s float values differ\n",
618 progname, nread, num_sfx(nread));
619 return(0);
620 }
621 if (!getbinary(&f2, sizeof(f2), 1, f2in))
622 return(good_RMS()); /* final check of RMS */
623 badeof:
624 if (report != REP_QUIET)
625 printf("%s: unexpected end-of-file\n", progname);
626 return(0);
627 }
628
629 /* Compare two inputs that are known to be 64-bit floating-point data */
630 static int
631 compare_double()
632 {
633 long nread = 0;
634 double f1, f2;
635
636 if (report >= REP_VERBOSE) {
637 fputs(progname, stdout);
638 fputs(": comparing inputs as 64-bit IEEE doubles\n", stdout);
639 }
640 while (getbinary(&f1, sizeof(f1), 1, f1in)) {
641 if (!getbinary(&f2, sizeof(f2), 1, f2in))
642 goto badeof;
643 ++nread;
644 if (real_check(f1, f2))
645 continue;
646 if (report != REP_QUIET)
647 printf("%s: %ld%s double values differ\n",
648 progname, nread, num_sfx(nread));
649 return(0);
650 }
651 if (!getbinary(&f2, sizeof(f2), 1, f2in))
652 return(good_RMS()); /* final check of RMS */
653 badeof:
654 if (report != REP_QUIET)
655 printf("%s: unexpected end-of-file\n", progname);
656 return(0);
657 }
658
659 /* Compare two Radiance files for equivalence */
660 int
661 main(int argc, char *argv[])
662 {
663 int typ1, typ2;
664 int a;
665
666 progname = argv[0];
667 for (a = 1; a < argc && argv[a][0] == '-'; a++) {
668 switch (argv[a][1]) {
669 case 'h': /* ignore header info. */
670 ign_header = !ign_header;
671 continue;
672 case 's': /* silent operation */
673 report = REP_QUIET;
674 continue;
675 case 'w': /* turn off warnings */
676 if (report > REP_ERROR)
677 report = REP_ERROR;
678 continue;
679 case 'v': /* turn on verbose mode */
680 report = REP_VERBOSE;
681 continue;
682 case 'm': /* maximum epsilon */
683 max_lim = atof(argv[++a]);
684 continue;
685 case 'r':
686 if (argv[a][2] == 'e') /* relative difference */
687 rel_min = atof(argv[++a]);
688 else if (argv[a][2] == 'm') /* RMS limit */
689 rms_lim = atof(argv[++a]);
690 else
691 usage();
692 continue;
693 case '\0': /* first file from stdin */
694 f1in = stdin;
695 f1name = stdin_name;
696 break;
697 default:
698 usage();
699 }
700 break;
701 }
702 if (a != argc-2) /* make sure of two inputs */
703 usage();
704 if (!strcmp(argv[a], argv[a+1])) { /* inputs are same? */
705 if (report >= REP_WARN)
706 printf("%s: warning - identical inputs given\n",
707 progname);
708 return(0);
709 }
710 if (!f1name) f1name = argv[a];
711 if (!f2name) f2name = argv[a+1];
712 /* open inputs */
713 SET_FILE_BINARY(stdin); /* in case we're using it */
714 if (!f1in && !(f1in = fopen(f1name, "rb"))) {
715 fprintf(stderr, "%s: cannot open for reading\n", f1name);
716 return(2);
717 }
718 if (!strcmp(f2name, "-")) {
719 f2in = stdin;
720 f2name = stdin_name;
721 } else if (!(f2in = fopen(f2name, "rb"))) {
722 fprintf(stderr, "%s: cannot open for reading\n", f2name);
723 return(2);
724 }
725 /* load headers */
726 if ((typ1 = identify_type(f1name, f1in, &hdr1)) < 0)
727 return(2);
728 if ((typ2 = identify_type(f2name, f2in, &hdr2)) < 0)
729 return(2);
730 if (typ1 != typ2) {
731 if (report != REP_QUIET)
732 printf("%s: '%s' is %s and '%s' is %s\n",
733 progname, f1name, file_type[typ1],
734 f2name, file_type[typ2]);
735 return(1);
736 }
737 ign_header |= !has_header(typ1); /* check headers if indicated */
738 if (!ign_header && !headers_match())
739 return(1);
740 lu_done(&hdr1); lu_done(&hdr2);
741 if (!ign_header & (report >= REP_WARN)) {
742 if (typ1 == TYP_UNKNOWN)
743 printf("%s: warning - unrecognized format, comparing as binary\n",
744 progname);
745 if (lin1cnt != lin2cnt)
746 printf("%s: warning - headers are different lengths\n",
747 progname);
748 }
749 if (report >= REP_VERBOSE)
750 printf("%s: input file type is %s\n",
751 progname, file_type[typ1]);
752
753 switch (typ1) { /* compare based on type */
754 case TYP_BINARY:
755 case TYP_TMESH:
756 case TYP_OCTREE:
757 case TYP_RBFMESH:
758 case TYP_UNKNOWN:
759 return( !compare_binary() );
760 case TYP_TEXT:
761 case TYP_ASCII:
762 return( !compare_text() );
763 case TYP_RGBE:
764 case TYP_XYZE:
765 return( !compare_hdr() );
766 case TYP_FLOAT:
767 return( !compare_float() );
768 case TYP_DOUBLE:
769 return( !compare_double() );
770 }
771 return(1);
772 }