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);		\
***************
*** 1381,1387 ****
    }
  }
  
! #define Code2V(c, RB, RW, CR)  ((((c)-(int)RB)*(float)CR)/(float)(RW-RB))
  
  #define	CLAMP(f,min,max) \
      (int)((f)+.5 < (min) ? (min) : (f)+.5 > (max) ? (max) : (f)+.5)
--- 1621,1627 ----
    }
  }
  
! #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)

