This patch adds multi-page TIFF support to XV 3.10a diff -r -c ../xv-3.10a/xv.c ./xv.c *** ../xv-3.10a/xv.c Thu Jan 19 13:08:43 1995 --- ./xv.c Mon Apr 14 18:21:48 1997 *************** *** 2668,2674 **** #endif #ifdef HAVE_TIFF ! case RFT_TIFF: rv = LoadTIFF (fname, pinfo); break; #endif #ifdef HAVE_PDS --- 2668,2674 ---- #endif #ifdef HAVE_TIFF ! case RFT_TIFF: rv = LoadTIFF (fname, pinfo, quick); break; #endif #ifdef HAVE_PDS *** ../xv-3.10a/xv.h Mon Jan 23 15:22:23 1995 --- ./xv.h Mon Apr 14 18:22:52 1997 *************** *** 1248,1253 **** --- 1248,1254 ---- void xv_getwd PARM((char *, size_t)); char *xv_strstr PARM((char *, char *)); FILE *xv_fopen PARM((char *, char *)); + void xv_mktemp PARM((char *, char *)); void Timer PARM((int)); /*************************** XVCOLOR.C ***************************/ *************** *** 1607,1613 **** void JPEGSaveParams PARM((char *, int)); /**************************** XVTIFF.C ***************************/ ! int LoadTIFF PARM((char *, PICINFO *)); void CreateTIFFW PARM((void)); void TIFFDialog PARM((int)); int TIFFCheckEvent PARM((XEvent *)); --- 1608,1614 ---- void JPEGSaveParams PARM((char *, int)); /**************************** XVTIFF.C ***************************/ ! int LoadTIFF PARM((char *, PICINFO *, int)); void CreateTIFFW PARM((void)); void TIFFDialog PARM((int)); int TIFFCheckEvent PARM((XEvent *)); *** ../xv-3.10a/xvmisc.c Fri Jan 13 18:41:34 1995 --- ./xvmisc.c Mon Apr 14 18:21:48 1997 *************** *** 28,33 **** --- 28,35 ---- * int xvbcmp (s1, s2, length) * void xvbzero(s, length) * char *xv_strstr(s1, s2) + * FILE *xv_fopen(str, str) + * void xv_mktemp(str) * void Timer(milliseconds) */ *************** *** 1066,1071 **** --- 1068,1083 ---- } + /***************************************************/ + void xv_mktemp(buf, fname) + char *buf, *fname; + { + #ifndef VMS + sprintf(buf, "%s/%s", tmpdir, fname); + #else + sprintf(buf, "Sys$Disk:[]%s", fname); + #endif + } /*******/ *** ../xv-3.10a/xvtiff.c Fri Jan 13 14:53:34 1995 --- ./xvtiff.c Mon Apr 14 18:21:48 1997 *************** *** 1,7 **** /* * xvtiff.c - load routine for 'TIFF' format pictures * ! * LoadTIFF(fname, numcols) - load a TIFF file */ #ifndef va_start --- 1,7 ---- /* * xvtiff.c - load routine for 'TIFF' format pictures * ! * LoadTIFF(fname, numcols, quick) - load a TIFF file */ #ifndef va_start *************** *** 15,20 **** --- 15,49 ---- #include "tiffio.h" /* has to be after xv.h, as it needs varargs/stdarg */ + /* Portions fall under the following copyright: + * + * Copyright (c) 1992, 1993, 1994 Sam Leffler + * Copyright (c) 1992, 1993, 1994 Silicon Graphics, Inc. + * + * Permission to use, copy, modify, distribute, and sell this software and + * its documentation for any purpose is hereby granted without fee, provided + * that (i) the above copyright notices and this permission notice appear in + * all copies of the software and related documentation, and (ii) the names of + * Sam Leffler and Silicon Graphics may not be used in any advertising or + * publicity relating to the software without the specific, prior written + * permission of Sam Leffler and Silicon Graphics. + * + * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, + * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + * + * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR + * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, + * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, + * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF + * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE + * OF THIS SOFTWARE. + */ + + + static int copyTiff PARM((TIFF *, char *)); + static int cpStrips PARM((TIFF *, TIFF *)); + static int cpTiles PARM((TIFF *, TIFF *)); static byte *loadPalette PARM((TIFF *, uint32, uint32, int, int, PICINFO *)); static byte *loadColor PARM((TIFF *, uint32, uint32, int, int, PICINFO *)); static int loadImage PARM((TIFF *, uint32, uint32, byte *, int)); *************** *** 28,46 **** static int error_occurred; /*******************************************/ ! int LoadTIFF(fname, pinfo) ! char *fname; PICINFO *pinfo; /*******************************************/ { /* returns '1' on success, '0' on failure */ TIFF *tif; uint32 w, h; short bps, spp, photo, orient; FILE *fp; byte *pic8; char *desc, oldpath[MAXPATHLEN+1], tmppath[MAXPATHLEN+1], *sp; error_occurred = 0; --- 57,79 ---- static int error_occurred; /*******************************************/ ! int LoadTIFF(fname, pinfo, quick) ! char *fname; PICINFO *pinfo; + int quick; /*******************************************/ { /* returns '1' on success, '0' on failure */ TIFF *tif; uint32 w, h; + float xres, yres; short bps, spp, photo, orient; FILE *fp; byte *pic8; char *desc, oldpath[MAXPATHLEN+1], tmppath[MAXPATHLEN+1], *sp; + char tmp[256], tmpname[256]; + int i, nump; error_occurred = 0; *************** *** 60,65 **** --- 93,100 ---- filesize = ftell(fp); fclose(fp); + + rmap = pinfo->r; gmap = pinfo->g; bmap = pinfo->b; /* a kludge: temporarily cd to the directory that the file is in (if *************** *** 81,89 **** } } ! tif=TIFFOpen(filename,"r"); if (!tif) return 0; /* flip orientation so that image comes in X order */ --- 116,172 ---- } } + + nump = 1; + + if (!quick) { + /* see if there's more than 1 image in tiff file, to determine if we + should do multi-page thing... */ + + tif = TIFFOpen(filename,"r"); + if (!tif) return 0; + while (TIFFReadDirectory(tif)) nump++; + TIFFClose(tif); + if (DEBUG) + fprintf(stderr,"LoadTIFF: %d page%s found\n", nump, nump==1 ? "" : "s"); + + + /* if there are multiple images, copy them out to multiple tmp files, + and load the first one... */ + + xv_mktemp(tmpname, "xvpgXXXXXX"); + + if (tmpname[0] == '\0') { /* mktemp() blew up */ + sprintf(str,"LoadTIFF: Unable to create temporary filename???"); + ErrPopUp(str, "\nHow unlikely!"); + return 0; + } + if (nump>1) { + TIFF *in, *out; + + in = TIFFOpen(filename, "r"); + if (!in) return 0; + for (i=1; i<=nump; i++) { + sprintf(tmp, "%s%d", tmpname, i); + if (!copyTiff(in, tmp)) { + SetISTR(ISTR_WARNING, "LoadTIFF: Error writing page files!"); + break; + } + + if (!TIFFReadDirectory(in)) break; + } + if (DEBUG) + fprintf(stderr,"LoadTIFF: %d page%s written\n", + i-1, (i-1)==1 ? "" : "s"); + + sprintf(tmp, "%s%d", tmpname, 1); /* open page #1 */ + filename = tmp; + } + } /* if (!quick) ... */ ! ! tif = TIFFOpen(filename,"r"); if (!tif) return 0; /* flip orientation so that image comes in X order */ *************** *** 107,112 **** --- 190,200 ---- TIFFGetFieldDefaulted(tif, TIFFTAG_BITSPERSAMPLE, &bps); TIFFGetField(tif, TIFFTAG_PHOTOMETRIC, &photo); TIFFGetFieldDefaulted(tif, TIFFTAG_SAMPLESPERPIXEL, &spp); + if ((TIFFGetField(tif, TIFFTAG_XRESOLUTION, &xres) == 1) && + (TIFFGetField(tif, TIFFTAG_YRESOLUTION, &yres) == 1)) { + normaspect = yres / xres; + if (DEBUG) fprintf(stderr,"TIFF aspect = %f\n", normaspect); + } if (spp == 1) { pic8 = loadPalette(tif, w, h, photo, bps, pinfo); *************** *** 139,144 **** --- 227,234 ---- if (pic8) free(pic8); if (pinfo->comment) free(pinfo->comment); pinfo->comment = (char *) NULL; + if (!quick && nump>1) KillPageFiles(tmpname, nump); + SetCursors(-1); return 0; } *************** *** 148,164 **** --- 238,404 ---- pinfo->normw = pinfo->w; pinfo->normh = pinfo->h; pinfo->frmType = F_TIFF; + if (nump>1) strcpy(pinfo->pagebname, tmpname); + pinfo->numpages = nump; if (pinfo->pic) return 1; + /* failed. if we malloc'd a comment, free it */ if (pinfo->comment) free(pinfo->comment); pinfo->comment = (char *) NULL; + if (!quick && nump>1) KillPageFiles(tmpname, nump); + SetCursors(-1); + return 0; } + + + /*******************************************/ + + #define CopyField(tag, v) \ + if (TIFFGetField(in, tag, &v)) TIFFSetField(out, tag, v) + #define CopyField2(tag, v1, v2) \ + if (TIFFGetField(in, tag, &v1, &v2)) TIFFSetField(out, tag, v1, v2) + #define CopyField3(tag, v1, v2, v3) \ + if (TIFFGetField(in, tag, &v1, &v2, &v3)) TIFFSetField(out, tag, v1, v2, v3) + + + /*******************************************/ + static int copyTiff(in, fname) + TIFF *in; + char *fname; + { + /* copies tiff image to given filename. Returns 0 on error */ + + TIFF *out; + short bitspersample, samplesperpixel, shortv, *shortav; + uint32 w, l; + float floatv; + char *stringv; + uint32 longv; + uint16 *red, *green, *blue, shortv2; + int rv; + + out = TIFFOpen(fname, "w"); + if (!out) return 0; + + CopyField (TIFFTAG_SUBFILETYPE, longv); + CopyField (TIFFTAG_TILEWIDTH, w); + CopyField (TIFFTAG_TILELENGTH, l); + CopyField (TIFFTAG_IMAGEWIDTH, w); + CopyField (TIFFTAG_IMAGELENGTH, l); + CopyField (TIFFTAG_BITSPERSAMPLE, bitspersample); + CopyField (TIFFTAG_COMPRESSION, shortv); + CopyField (TIFFTAG_PREDICTOR, shortv); + CopyField (TIFFTAG_PHOTOMETRIC, shortv); + CopyField (TIFFTAG_THRESHHOLDING, shortv); + CopyField (TIFFTAG_FILLORDER, shortv); + CopyField (TIFFTAG_ORIENTATION, shortv); + CopyField (TIFFTAG_SAMPLESPERPIXEL, samplesperpixel); + CopyField (TIFFTAG_MINSAMPLEVALUE, shortv); + CopyField (TIFFTAG_MAXSAMPLEVALUE, shortv); + CopyField (TIFFTAG_XRESOLUTION, floatv); + CopyField (TIFFTAG_YRESOLUTION, floatv); + CopyField (TIFFTAG_GROUP3OPTIONS, longv); + CopyField (TIFFTAG_GROUP4OPTIONS, longv); + CopyField (TIFFTAG_RESOLUTIONUNIT, shortv); + CopyField (TIFFTAG_PLANARCONFIG, shortv); + CopyField (TIFFTAG_ROWSPERSTRIP, longv); + CopyField (TIFFTAG_XPOSITION, floatv); + CopyField (TIFFTAG_YPOSITION, floatv); + CopyField (TIFFTAG_IMAGEDEPTH, longv); + CopyField (TIFFTAG_TILEDEPTH, longv); + CopyField2(TIFFTAG_EXTRASAMPLES, shortv, shortav); + CopyField3(TIFFTAG_COLORMAP, red, green, blue); + CopyField2(TIFFTAG_PAGENUMBER, shortv, shortv2); + CopyField (TIFFTAG_ARTIST, stringv); + CopyField (TIFFTAG_IMAGEDESCRIPTION,stringv); + CopyField (TIFFTAG_MAKE, stringv); + CopyField (TIFFTAG_MODEL, stringv); + CopyField (TIFFTAG_SOFTWARE, stringv); + CopyField (TIFFTAG_DATETIME, stringv); + CopyField (TIFFTAG_HOSTCOMPUTER, stringv); + CopyField (TIFFTAG_PAGENAME, stringv); + CopyField (TIFFTAG_DOCUMENTNAME, stringv); + + if (TIFFIsTiled(in)) rv = cpTiles (in, out); + else rv = cpStrips(in, out); + + TIFFClose(out); + return rv; + } + + + /*******************************************/ + static int cpStrips(in, out) + TIFF *in, *out; + { + tsize_t bufsize; + byte *buf; + + bufsize = TIFFStripSize(in); + buf = (byte *) malloc((size_t) bufsize); + if (buf) { + tstrip_t s, ns = TIFFNumberOfStrips(in); + uint32 *bytecounts; + + TIFFGetField(in, TIFFTAG_STRIPBYTECOUNTS, &bytecounts); + for (s = 0; s < ns; s++) { + if (bytecounts[s] > bufsize) { + buf = (unsigned char *) realloc(buf, (size_t) bytecounts[s]); + if (!buf) return (0); + bufsize = bytecounts[s]; + } + if (TIFFReadRawStrip (in, s, buf, (tsize_t) bytecounts[s]) < 0 || + TIFFWriteRawStrip(out, s, buf, (tsize_t) bytecounts[s]) < 0) { + free(buf); + return 0; + } + } + free(buf); + return 1; + } + return 0; + } + + + /*******************************/ + static int cpTiles(in, out) + TIFF *in, *out; + { + tsize_t bufsize; + byte *buf; + + bufsize = TIFFTileSize(in); + buf = (unsigned char *) malloc((size_t) bufsize); + if (buf) { + ttile_t t, nt = TIFFNumberOfTiles(in); + uint32 *bytecounts; + + TIFFGetField(in, TIFFTAG_TILEBYTECOUNTS, &bytecounts); + for (t = 0; t < nt; t++) { + if (bytecounts[t] > bufsize) { + buf = (unsigned char *)realloc(buf, (size_t) bytecounts[t]); + if (!buf) return (0); + bufsize = bytecounts[t]; + } + if (TIFFReadRawTile (in, t, buf, (tsize_t) bytecounts[t]) < 0 || + TIFFWriteRawTile(out, t, buf, (tsize_t) bytecounts[t]) < 0) { + free(buf); + return 0; + } + } + free(buf); + return 1; + } + return 0; + } + + /*******************************************/ static byte *loadPalette(tif, w, h, photo, bps, pinfo) TIFF *tif; *************** *** 186,192 **** break; } ! sprintf(pinfo->shrtInfo, "%ux%u TIFF.",w,h); pic8 = (byte *) malloc((size_t) w*h); if (!pic8) FatalError("loadPalette() - couldn't malloc 'pic8'"); --- 426,432 ---- break; } ! sprintf(pinfo->shrtInfo, "%ux%u TIFF.",(u_int) w, (u_int) h); pic8 = (byte *) malloc((size_t) w*h); if (!pic8) FatalError("loadPalette() - couldn't malloc 'pic8'"); *************** *** 214,220 **** "???"), filesize); ! sprintf(pinfo->shrtInfo, "%ux%u TIFF.",w,h); /* allocate 24-bit image */ pic24 = (byte *) malloc((size_t) w*h*3); --- 454,460 ---- "???"), filesize); ! sprintf(pinfo->shrtInfo, "%ux%u TIFF.",(u_int) w, (u_int) h); /* allocate 24-bit image */ pic24 = (byte *) malloc((size_t) w*h*3); *************** *** 1014,1020 **** #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } #define UNROLL8(w, op1, op2) { \ ! uint32 x; \ for (x = w; x >= 8; x -= 8) { \ op1; \ REPEAT8(op2); \ --- 1254,1260 ---- #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } #define UNROLL8(w, op1, op2) { \ ! uint32 x; \ for (x = w; x >= 8; x -= 8) { \ op1; \ REPEAT8(op2); \ *************** *** 1026,1032 **** } #define UNROLL4(w, op1, op2) { \ ! register uint32 x; \ for (x = w; x >= 4; x -= 4) { \ op1; \ REPEAT4(op2); \ --- 1266,1272 ---- } #define UNROLL4(w, op1, op2) { \ ! uint32 x; \ for (x = w; x >= 4; x -= 4) { \ op1; \ REPEAT4(op2); \ *************** *** 1038,1044 **** } #define UNROLL2(w, op1, op2) { \ ! register uint32 x; \ for (x = w; x >= 2; x -= 2) { \ op1; \ REPEAT2(op2); \ --- 1278,1284 ---- } #define UNROLL2(w, op1, op2) { \ ! uint32 x; \ for (x = w; x >= 2; x -= 2) { \ op1; \ REPEAT2(op2); \