"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "viewfax-2.6/faxinput.c" of archive viewfax-2.6.tar.gz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /* Fax file input processing
    2    Copyright (C) 1990, 1995, 2004  Frank D. Cringle.
    3 
    4 This file is part of viewfax - g3/g4 fax processing software.
    5 
    6 viewfax is free software; you can redistribute it and/or modify it
    7 under the terms of the GNU General Public License as published by the
    8 Free Software Foundation; either version 2 of the License, or (at your
    9 option) any later version.
   10 
   11 This program is distributed in the hope that it will be useful, but
   12 WITHOUT ANY WARRANTY; without even the implied warranty of
   13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   14 General Public License for more details.
   15 
   16 You should have received a copy of the GNU General Public License
   17 along with this program; if not, write to the Free Software
   18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
   19 
   20 #include <stdlib.h>
   21 #include <stdio.h>
   22 #include <unistd.h>
   23 #include <errno.h>
   24 #include <string.h>
   25 #include <sys/types.h>
   26 #include <sys/stat.h>
   27 #include <sys/time.h>
   28 #include <fcntl.h>
   29 #include "faxexpand.h"
   30 
   31 #define	FAXMAGIC	"\000PC Research, Inc\000\000\000\000\000\000"
   32 
   33 enum { Tbyte=1, Tascii, Tshort, Tlong, Trational };
   34 static char *typeStr[] = {
   35     "undef", "BYTE", "ASCII", "SHORT", "LONG", "RATIONAL" };
   36 
   37 static char *Filename;
   38 static int warned;
   39 
   40 static int
   41 errwarn(int err) {
   42     if (!(err || verbose)) return 0;
   43     if (!warned) {
   44 	fprintf(stderr, "%s: %s: errors (E), warnings (W), info (I)\n",
   45 		ProgName, Filename);
   46 	warned = 1;
   47     }
   48     return 1;
   49 }
   50 
   51 /* Enter an argument in the linked list of pages */
   52 struct pagenode *
   53 notefile(char *name)
   54 {
   55     struct pagenode *new = (struct pagenode *) xmalloc(sizeof *new);
   56 
   57     *new = defaultpage;
   58     if (firstpage == NULL)
   59 	firstpage = new;
   60     new->prev = lastpage;
   61     new->next = NULL;
   62     new->pageno = 1;
   63     if (lastpage != NULL) {
   64 	lastpage->next = new;
   65 	new->pageno = lastpage->pageno + 1;
   66     }
   67     lastpage = new;
   68     new->pathname = name;
   69     if ((new->name = strrchr(new->pathname, '/')) != NULL)
   70 	new->name++;
   71     else
   72 	new->name = new->pathname;
   73     if (new->width == 0)
   74 	new->width = 1728;
   75     if (new->vres > 1)
   76 	new->vres = !(new->name[0] == 'f' && new->name[1] == 'n');
   77     new->extra = NULL;
   78     return new;
   79 }
   80 
   81 static t32bits
   82 get4(unsigned char *p, int endian)
   83 {
   84     return endian ? (p[0]<<24)|(p[1]<<16)|(p[2]<<8)|p[3] :
   85 	p[0]|(p[1]<<8)|(p[2]<<16)|(p[3]<<24);
   86 }
   87 
   88 static int
   89 get2(unsigned char *p, int endian)
   90 {
   91     return endian ? (p[0]<<8)|p[1] : p[0]|(p[1]<<8);
   92 }
   93 
   94 static int
   95 showtag(FILE *tf, int ftype, int count, t32bits pos, char *tagname)
   96 {
   97     int ch;
   98 
   99     if ((ftype != Tascii) && errwarn(1)) {
  100 	fprintf(stderr, "[W] %s: expected ascii tag, found %d\n",
  101 		tagname, ftype);
  102 	return 0;
  103     }
  104     if (fseek(tf, pos, SEEK_SET) == -1)
  105 	return -1;
  106     fprintf(stderr, "[I] %s: ", tagname);
  107     while (count--) {
  108 	if ((ch = fgetc(tf)) == EOF)
  109 	    return -1;
  110 	if (ch == 0)
  111 	    break;
  112 	if ((ch < ' ') || (ch > '~'))
  113 	    ch = '?';
  114 	fputc(ch, stderr);
  115     }
  116     if (count)
  117 	fputs(" <short!>", stderr);
  118     if (ch)
  119 	fputs(" <long!>", stderr);
  120     fputc('\n', stderr);
  121     return 0;
  122 }
  123 
  124 /* generate pagenodes for the images in a tiff file */
  125 int
  126 notetiff(char *name)
  127 {
  128     FILE *tf;
  129     unsigned char header[8];
  130     static const char littleTIFF[4] = "\x49\x49\x2a\x00";
  131     static const char bigTIFF[4] = "\x4d\x4d\x00\x2a";
  132     int endian;
  133     t32bits IFDoff;
  134     struct pagenode *pn = NULL;
  135 
  136     if ((tf = fopen(name, "r")) == NULL) {
  137 	perror(name);
  138 	return 0;
  139     }
  140 
  141     if (fread(header, 8, 1, tf) == 0) {
  142     nottiff:
  143 	fclose(tf);
  144 	(void) notefile(name);
  145 	return 0;
  146     }
  147     if (memcmp(header, &littleTIFF, 4) == 0)
  148 	endian = 0;
  149     else if (memcmp(header, &bigTIFF, 4) == 0)
  150 	endian = 1;
  151     else
  152 	goto nottiff;
  153     IFDoff = get4(header+4, endian);
  154     if (IFDoff & 1)
  155 	goto nottiff;
  156     Filename = name;
  157     warned = 0;
  158     do {			/* for each page */
  159 	unsigned char buf[8];
  160 	unsigned char *dir = NULL;
  161 	unsigned char *dp;
  162 	int ndirent;
  163 	pixnum iwidth = defaultpage.width ? defaultpage.width : 1728;
  164 	pixnum iheight = defaultpage.height ? defaultpage.height : 2339;
  165 	int inverse = defaultpage.inverse;
  166 	int lsbfirst = 0;
  167 	int t4opt = 0, comp = 0;
  168 	int orient = defaultpage.orient;
  169 	double yres = defaultpage.vres ? 196.0 : 98.0;
  170 	double xres;
  171 	struct strip *strips = NULL;
  172 	unsigned long rowsperstrip = 0;
  173 	int nstrips = 1;
  174 
  175 	if (fseek(tf, IFDoff, SEEK_SET) < 0) {
  176 	realbad:
  177 	    errwarn(1);
  178 	    fputs("[E] invalid tiff file\n", stderr);
  179 	bad:
  180 	    if (strips)
  181 		free(strips);
  182 	    if (dir)
  183 		free(dir);
  184 	    fclose(tf);
  185 	    Filename = NULL;
  186 	    warned = 0;
  187 	    return 1;
  188 	}
  189 	if (fread(buf, 2, 1, tf) == 0)
  190 	    goto realbad;
  191 	ndirent = get2(buf, endian);
  192 	dir = (unsigned char *) xmalloc(12*ndirent+4);
  193 	if (fread(dir, 12*ndirent+4, 1, tf) == 0)
  194 	    goto realbad;
  195 	for (dp = dir; ndirent; ndirent--, dp += 12) {
  196 	    /* for each directory entry */
  197 	    int tag, ftype;
  198 	    t32bits count, value = 0;
  199 	    tag = get2(dp, endian);
  200 	    ftype = get2(dp+2, endian);
  201 	    count = get4(dp+4, endian);
  202 	    switch(ftype) {	/* value is offset to list if count*size > 4 */
  203 	    case Tbyte:
  204 	      break;
  205 	    case Tascii:
  206 		if (count <= 4)
  207 		    value = IFDoff + 10 + dp - dir;
  208 		else {	/* calc offset but don't read unless later used */
  209 		    value = get4(dp+8, endian);
  210 		}
  211 		break;
  212 	    case Tshort:
  213 		value = get2(dp+8, endian);
  214 		break;
  215 	    case Tlong:
  216 		value = get4(dp+8, endian);
  217 		break;
  218 	    case Trational:
  219 		value = get4(dp+8, endian);
  220 		break;
  221 	    default:
  222 		errwarn(1);
  223 		fprintf(stderr, "[E] unknown ftype %d\n", ftype);
  224 		break;
  225 	    }
  226 	    switch(tag) {
  227 	    case 254:		/* NewSubFileType */
  228 		if (errwarn(0))
  229 		    fprintf(stderr, "[I] NewSubfile(%d) = %lu\n",
  230 			    tag, (unsigned long) value);
  231 		break;
  232 	    case 256:		/* ImageWidth */
  233 		iwidth = value;
  234 		break;
  235 	    case 257:		/* ImageLength */
  236 		iheight = value;
  237 		break;
  238 	    case 258:		/* BitsPerSample */
  239 		if ((value != 1) && errwarn(1))
  240 		    fprintf(stderr, "[E] ignored Bits/Sample(%d) = %lu\n",
  241 			    tag, (unsigned long) value);
  242 		break;
  243 	    case 259:		/* Compression */
  244 		comp = value;
  245 		break;
  246 	    case 262:		/* PhotometricInterpretation */
  247 		inverse ^= (value == 1);
  248 		break;
  249 	    case 266:		/* FillOrder */
  250 		lsbfirst = (value == 2);
  251 		break;
  252 	    case 269:		/* DocumentName */
  253 		if (verbose) {
  254 		    if (showtag(tf, ftype, count, value, "DocumentName") < 0)
  255 			goto realbad;
  256 		}
  257 		break;
  258 	    case 270:		/* ImageDescription */
  259 		if (verbose) {
  260 		    if (showtag(tf, ftype, count, value,
  261 				"ImageDescription") < 0)
  262 			goto realbad;
  263 		}
  264 		break;
  265 	    case 271:		/* Make */
  266 		if (verbose) {
  267 		    if (showtag(tf, ftype, count, value, "Make") < 0)
  268 			goto realbad;
  269 		}
  270 		break;
  271 	    case 272:		/* Model */
  272 		if (verbose) {
  273 		    if (showtag(tf, ftype, count, value, "Model") < 0)
  274 			goto realbad;
  275 		}
  276 		break;
  277 	    case 273:		/* StripOffsets */
  278 		nstrips = count;
  279 		strips = (struct strip *) xmalloc(count * sizeof *strips);
  280 		if (count == 1 || (count == 2 && ftype == 3)) {
  281 		    strips[0].offset = value;
  282 		    if (count == 2)
  283 			strips[1].offset = get2(dp+10, endian);
  284 		    break;
  285 		}
  286 		if (fseek(tf, value, SEEK_SET) < 0)
  287 		    goto realbad;
  288 		for (count = 0; count < nstrips; count++) {
  289 		    if (fread(buf, (ftype == 3) ? 2 : 4, 1, tf) == 0)
  290 			goto realbad;
  291 		    strips[count].offset = (ftype == 3) ?
  292 			get2(buf, endian) : get4(buf, endian);
  293 		}
  294 		break;
  295 	    case 274:		/* Orientation */
  296 		switch(value) {
  297 		default:	/* row0 at top,    col0 at left   */
  298 		    orient = 0;
  299 		    break;
  300 		case 2:		/* row0 at top,    col0 at right  */
  301 		    orient = TURN_M;
  302 		    break;
  303 		case 3:		/* row0 at bottom, col0 at right  */
  304 		    orient = TURN_U;
  305 		    break;
  306 		case 4:		/* row0 at bottom, col0 at left   */
  307 		    orient = TURN_U|TURN_M;
  308 		    break;
  309 		case 5:		/* row0 at left,   col0 at top    */
  310 		    orient = TURN_M|TURN_L;
  311 		    break;
  312 		case 6:		/* row0 at right,  col0 at top    */
  313 		    orient = TURN_U|TURN_L;
  314 		    break;
  315 		case 7:		/* row0 at right,  col0 at bottom */
  316 		    orient = TURN_U|TURN_M|TURN_L;
  317 		    break;
  318 		case 8:		/* row0 at left,   col0 at bottom */
  319 		    orient = TURN_L;
  320 		    break;
  321 		}
  322 		break;
  323 	    case 277:		/* SamplesPerPixel */
  324 		if ((value != 1) && errwarn(1))
  325 		    fprintf(stderr, "[I] ignored Sample/Pixel(%d) = %lu\n",
  326 			    tag, (unsigned long) value);
  327 		break;
  328 	    case 278:		/* RowsPerStrip */
  329 		rowsperstrip = value;
  330 		break;
  331 	    case 279:		/* StripByteCounts */
  332 		if ((count != nstrips) && errwarn(1)) {
  333 		    fprintf(stderr,
  334 			    "[E] StripsPerImage tag273=%d, tag279=%ld\n",
  335 			    nstrips, count);
  336 		    goto realbad;
  337 		}
  338 		if (count == 1 || (count == 2 && ftype == 3)) {
  339 		    strips[0].size = value;
  340 		    if (count == 2)
  341 			strips[1].size = get2(dp+10, endian);
  342 		    break;
  343 		}
  344 		if (fseek(tf, value, SEEK_SET) < 0)
  345 		    goto realbad;
  346 		for (count = 0; count < nstrips; count++) {
  347 		    if (fread(buf, (ftype == 3) ? 2 : 4, 1, tf) == 0)
  348 			goto realbad;
  349 		    strips[count].size = (ftype == 3) ?
  350 			get2(buf, endian) : get4(buf, endian);
  351 		}
  352 		break;
  353 	    case 282:		/* XResolution */
  354 		if (fseek(tf, value, SEEK_SET) < 0 ||
  355 		    fread(buf, 8, 1, tf) == 0)
  356 		    goto realbad;
  357 		xres = get4(buf, endian) / get4(buf+4, endian);
  358 		if ((xres != 204) && errwarn(0))
  359 		    fprintf(stderr, "[W] ignored Xres(%d) = %7.2f (ns)\n",
  360 			    tag, xres);
  361 		break;
  362 	    case 283:		/* YResolution */
  363 		if (fseek(tf, value, SEEK_SET) < 0 ||
  364 		    fread(buf, 8, 1, tf) == 0)
  365 		    goto realbad;
  366 		yres = get4(buf, endian) / get4(buf+4, endian);
  367 		break;
  368 	    case 284:		/* PlanarConfiguration */
  369 		if ((value != 1) && errwarn(0))
  370 		    fprintf(stderr, "[W] ignored PlanarConfig(%d) = %lu\n",
  371 			    tag, (unsigned long) value);
  372 		break;
  373 	    case 285:		/* PageName */
  374 	    case 286:		/* XPosition */
  375 	    case 287:		/* YPosition */
  376 		if (errwarn(0))
  377 		    fprintf(stderr,
  378 			    "[W] ignored storage & retrieval tag (%d)\n", tag);
  379 		break;
  380 	    case 292:		/* T4Options */
  381 		t4opt = value;
  382 		break;
  383 	    case 293:		/* T6Options */
  384 		if ((value != 0) && errwarn(1))
  385 		    fprintf(stderr, "[W] ignored T6Options(%d) = %lu\n",
  386 			    tag, (unsigned long) value);
  387 		break;
  388 	    case 296:		/* ResolutionUnit */
  389 		if (value == 3)
  390 		    yres *= 2.54;
  391 		break;
  392 	    case 297:		/* PageNumber */
  393 		if (errwarn(0))
  394 		    fprintf(stderr, "[I] PageNumber(%d) = %lu/%d\n",
  395 			    tag, (unsigned long) value, get2(dp+10, endian));
  396 		break;
  397 	    case 305:		/* Software */
  398 		if (errwarn(0)) {
  399 		    if (showtag(tf, ftype, count, value, "Software") < 0)
  400 			goto realbad;
  401 		}
  402 		break;
  403 	    case 306:		/* DateTime */
  404 		if (errwarn(0)) {
  405 		    if (showtag(tf, ftype, count, value, "DateTime") < 0)
  406 			goto realbad;
  407 		}
  408 		break;
  409 	    case 315:		/* Artist */
  410 		if (errwarn(0)) {
  411 		    if (showtag(tf, ftype, count, value, "Artist") < 0)
  412 			goto realbad;
  413 		}
  414 		break;
  415 	    case 316:		/* HostComputer */
  416 		if (errwarn(0)) {
  417 		    if (showtag(tf, ftype, count, value, "HostComputer") < 0)
  418 			goto realbad;
  419 		}
  420 		break;
  421 	    case 320:		/* ColorMap */
  422 		if (errwarn(0))
  423 		    fprintf(stderr, "[W]ignored ColorMap(%d) = %lu\n",
  424 			    tag, (unsigned long) value);
  425 		break;
  426 	    case 326:	/* BadFaxLines */
  427 	    case 327:	/* CleanFaxData */
  428 	    case 328:	/* ConsecutiveBadFaxLines */
  429 		if ((value != 0) && errwarn(0))
  430 		    fprintf(stderr, "[I] quality(%d) = %lu\n", tag,
  431 			    (unsigned long) value);
  432 		break;
  433 	    default:
  434 		if (errwarn(0)) {
  435 		    fprintf(stderr, "[W] unknown tag %d: #%lu %s",
  436 			    tag, (unsigned long) count, typeStr[ftype]);
  437 		    if ((ftype == Tshort) || (ftype == Tlong))
  438 			fprintf(stderr, " = %lu", (unsigned long) value);
  439 		    fprintf(stderr, "\n");
  440 		}
  441 		break;
  442 	    }
  443 	}
  444 	IFDoff = get4(dp, endian);
  445 	free(dir);
  446 	dir = NULL;
  447 	if ((iwidth * iheight == 0) && errwarn(1)) {
  448 	    fprintf(stderr,
  449 		    "[E] fax width x height (%lu x %lu) must be non-zero\n",
  450 		    (unsigned long) iwidth, (unsigned long) iheight);
  451 	    goto bad;
  452 	}
  453 	if ((comp < 2 || comp > 4) && errwarn(1)) {
  454 	    fprintf(stderr, "[E] compression=%d unsupported\n", comp);
  455 	    goto bad;
  456 	}
  457 	pn = notefile(name);
  458 	pn->nstrips = nstrips;
  459 	pn->rowsperstrip = nstrips > 1 ? rowsperstrip : iheight;
  460 	pn->strips = strips;
  461 	pn->width = iwidth;
  462 	pn->height = iheight;
  463 	pn->inverse = inverse;
  464 	pn->lsbfirst = lsbfirst;
  465 	pn->orient = orient;
  466 	pn->vres = (yres > 150); /* arbitrary threshold for fine resolution */
  467 	if (comp == 2)
  468 	    pn->expander = MHexpand;
  469 	else if (comp == 3)
  470 	    pn->expander = (t4opt & 1) ? g32expand : g31expand;
  471 	else
  472 	    pn->expander = g4expand;
  473     } while (IFDoff);
  474     fclose(tf);
  475     Filename = NULL;
  476     warned = 0;
  477     return 1;
  478 }
  479 
  480 /* report error and remove bad file from the list */
  481 static void
  482 badfile(struct pagenode *pn)
  483 {
  484     struct pagenode *p;
  485 
  486     if (errno)
  487 	perror(pn->pathname);
  488     if (pn == firstpage) {
  489 	if (pn->next == NULL)
  490 	    exit(1);
  491 	firstpage = thispage = firstpage->next;
  492 	firstpage->prev = NULL;
  493     }
  494     else
  495 	for (p = firstpage; p; p = p->next)
  496 	    if (p->next == pn) {
  497 		thispage = p;
  498 		p->next = pn->next;
  499 		if (pn->next)
  500 		    pn->next->prev = p;
  501 		break;
  502 	    }
  503     if (pn) free(pn);
  504 }
  505 
  506 /* rearrange input bits into t16bits lsb-first chunks */
  507 static void
  508 normalize(struct pagenode *pn, int revbits, int swapbytes, size_t length)
  509 {
  510     t32bits *p = (t32bits *) pn->data;
  511 
  512     switch ((revbits<<1)|swapbytes) {
  513     case 0:
  514 	break;
  515     case 1:
  516 	for ( ; length; length -= 4) {
  517 	    t32bits t = *p;
  518 	    *p++ = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8);
  519 	}
  520 	break;
  521     case 2:
  522 	for ( ; length; length -= 4) {
  523 	    t32bits t = *p;
  524 	    t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4);
  525 	    t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2);
  526 	    *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1);
  527 	}
  528 	break;
  529     case 3:
  530 	for ( ; length; length -= 4) {
  531 	    t32bits t = *p;
  532 	    t = ((t & 0xff00ff00) >> 8) | ((t & 0x00ff00ff) << 8);
  533 	    t = ((t & 0xf0f0f0f0) >> 4) | ((t & 0x0f0f0f0f) << 4);
  534 	    t = ((t & 0xcccccccc) >> 2) | ((t & 0x33333333) << 2);
  535 	    *p++ = ((t & 0xaaaaaaaa) >> 1) | ((t & 0x55555555) << 1);
  536 	}
  537 	break;
  538     default:
  539 	fprintf(stderr, "%s: unknown rev %d\n",
  540 		ProgName, (revbits<<1)|swapbytes);
  541 	break;
  542     }
  543 }
  544 
  545 
  546 /* get compressed data into memory */
  547 unsigned char *
  548 getstrip(struct pagenode *pn, int strip)
  549 {
  550     int fd, n;
  551     size_t offset, roundup;
  552     struct stat sbuf;
  553     unsigned char *Data;
  554     union { t16bits s; unsigned char b[2]; } so;
  555 #define ShortOrder	so.b[1]
  556 
  557     so.s = 1;
  558     if ((fd = open(pn->pathname, O_RDONLY, 0)) < 0) {
  559 	badfile(pn);
  560 	return NULL;
  561     }
  562 
  563     if (pn->strips == NULL) {
  564 	if (fstat(fd, &sbuf) != 0) {
  565 	    close(fd);
  566 	    badfile(pn);
  567 	    return NULL;
  568 	}
  569 	offset = 0;
  570 	pn->length = sbuf.st_size;
  571     }
  572     else if (strip < pn->nstrips) {
  573 	offset = pn->strips[strip].offset;
  574 	pn->length = pn->strips[strip].size;
  575     }
  576     else {
  577 	fprintf(stderr, "%s:%s: trying to expand too many strips\n",
  578 		ProgName, pn->pathname);
  579 	close(fd);
  580 	badfile(pn);
  581 	return NULL;
  582     }
  583     if (!pn->length) {
  584 	fprintf(stderr, "%s:%s: trying to expand a null strip\n",
  585 		ProgName, pn->pathname);
  586 	close(fd);
  587 	badfile(pn);
  588 	return NULL;
  589     }
  590 
  591     /* round size to full boundary plus t32bits */
  592     roundup = (pn->length + 7) & ~3;
  593 
  594     Data = (unsigned char *) xmalloc(roundup);
  595     /* clear the last 2 t32bits, to force the expander to terminate
  596        even if the file ends in the middle of a fax line  */
  597     *((t32bits *) Data + roundup/4 - 2) = 0;
  598     *((t32bits *) Data + roundup/4 - 1) = 0;
  599 
  600     /* we expect to get it in one gulp... */
  601     if (lseek(fd, offset, SEEK_SET) < 0 ||
  602 	(n = read(fd, Data, pn->length)) != pn->length) {
  603 	fprintf(stderr, "%s: expected %d bytes, got %d\n",
  604 		pn->pathname, pn->length, n);
  605 	badfile(pn);
  606 	free(Data);
  607 	close(fd);
  608 	return NULL;
  609     }
  610     close(fd);
  611 
  612     pn->data = (t16bits *) Data;
  613     if (pn->strips == NULL && memcmp(Data, FAXMAGIC, sizeof(FAXMAGIC)) == 0) {
  614 	/* handle ghostscript / PC Research fax file */
  615 	if (Data[24] != 1 || Data[25] != 0)
  616 	    printf("%s: only first page of multipage file %s will be shown\n",
  617 		   ProgName, pn->pathname);
  618 	pn->length -= 64;
  619 	pn->vres = Data[29] ? 1 : 0;
  620 	pn->data += 32;
  621 	roundup -= 64;
  622     }
  623 
  624     normalize(pn, !pn->lsbfirst, ShortOrder, roundup);
  625     if (pn->height == 0)
  626 	pn->height = G3count(pn, pn->expander == g32expand);
  627     if (pn->height == 0) {
  628 	fprintf(stderr, "%s: no fax found in file %s\n", ProgName,
  629 		pn->pathname);
  630 	errno = 0;
  631 	badfile(pn);
  632 	free(Data);
  633 	return NULL;
  634     }
  635     if (pn->strips == NULL)
  636 	pn->rowsperstrip = pn->height;
  637     if (verbose && strip == 0)
  638 	printf("%s:\n\twidth = %lu\n\theight = %lu\n\tresolution = %s\n",
  639 	       pn->name, (unsigned long) pn->width, (unsigned long) pn->height,
  640 	       pn->vres ? "fine" : "normal");
  641     return Data;
  642 }