$NetBSD: patch-ax,v 1.1 2002/10/06 16:26:57 he Exp $ This patch is partly based on ftp://ftp.trilon.com/pub/xv/patches/mp-tiff-patch as found on http://www.trilon.com/xv/downloads.html#patches It was edited to fit into the NetBSD Packages Collection! - HE ------------------------------------------------------------ --- xvtiff.c.orig Fri Aug 9 17:22:16 2002 +++ xvtiff.c @@ -1,7 +1,7 @@ /* * xvtiff.c - load routine for 'TIFF' format pictures * - * LoadTIFF(fname, numcols) - load a TIFF file + * LoadTIFF(fname, numcols, quick) - load a TIFF file */ #ifndef va_start @@ -15,6 +15,35 @@ #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,19 +57,23 @@ static int error_occurred; /*******************************************/ -int LoadTIFF(fname, pinfo) - char *fname; +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,6 +93,8 @@ 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,9 +116,57 @@ } } + + 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"); + + tif = TIFFOpen(filename,"r"); if (!tif) return 0; /* flip orientation so that image comes in X order */ @@ -107,6 +190,11 @@ 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,6 +227,8 @@ 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,17 +238,167 @@ 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,7 +426,7 @@ break; } - sprintf(pinfo->shrtInfo, "%ux%u TIFF.",w,h); + 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,7 +454,7 @@ "???"), filesize); - sprintf(pinfo->shrtInfo, "%ux%u TIFF.",w,h); + sprintf(pinfo->shrtInfo, "%ux%u TIFF.",(u_int) w, (u_int) h); /* allocate 24-bit image */ pic24 = (byte *) malloc((size_t) w*h*3); @@ -1018,7 +1258,7 @@ #define CASE4(x,op) switch (x) { case 3: op; case 2: op; case 1: op; } #define UNROLL8(w, op1, op2) { \ - uint32 x; \ + uint32 x; \ for (x = w; x >= 8; x -= 8) { \ op1; \ REPEAT8(op2); \ @@ -1030,7 +1270,7 @@ } #define UNROLL4(w, op1, op2) { \ - register uint32 x; \ + uint32 x; \ for (x = w; x >= 4; x -= 4) { \ op1; \ REPEAT4(op2); \ @@ -1042,7 +1282,7 @@ } #define UNROLL2(w, op1, op2) { \ - register uint32 x; \ + uint32 x; \ for (x = w; x >= 2; x -= 2) { \ op1; \ REPEAT2(op2); \ @@ -1384,7 +1624,7 @@ } } -#define Code2V(c, RB, RW, CR) ((((c)-(int)RB)*(float)CR)/(float)(RW-RB)) +#define Code2V(c, RB, RW, CR) (((((int)c)-(int)RB)*(float)CR)/(float)(RW-RB)) #define CLAMP(f,min,max) \ (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)