1 /* zgv 5.3 - GIF, JPEG and PBM/PGM/PPM viewer, for VGA PCs running Linux.
2  * Copyright (C) 1993-2001 Russell Marks. See README for license details.
3  *
4  * readtiff.c - read TIFF files. Based on xzgv's readtiff.c.
5  */
6 
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <stdlib.h>
11 #include <setjmp.h>
12 #include <sys/file.h>  /* for open et al */
13 #include <tiffio.h>
14 
15 #include "zgv.h"
16 #include "vgadisp.h"
17 #include "rcfile.h"
18 #include "rc_config.h"
19 #include "readpnm.h"	/* for dithering stuff */
20 
21 #include "readtiff.h"
22 
23 
24 /* redefine CLOSE_AND_RET to use TIFFClose */
25 #undef CLOSE_AND_RET
26 #define CLOSE_AND_RET(x)	do { TIFFClose(in); return(x); } while(0)
27 
28 
29 static unsigned char *work_bmap,*work_pal;
30 static TIFF *work_in;
31 
32 
aborted_file_tiff_cleanup(void)33 void aborted_file_tiff_cleanup(void)
34 {
35 free(work_bmap);
36 free(work_pal);
37 TIFFClose(work_in);
38 }
39 
40 
41 /* output_type returns how many bytes per pixel needed for display */
read_tiff_file(char * filename,hffunc howfarfunc,unsigned char ** bmap,unsigned char ** palette,int * output_type,PICINFO * pp)42 int read_tiff_file(char *filename,hffunc howfarfunc,unsigned char **bmap,
43                   unsigned char **palette,int *output_type,PICINFO *pp)
44 {
45 TIFF *in;
46 FILE *tmp;
47 unsigned char *src,*dst,*ptr,*pal,*image;
48 int width,height;
49 int f,y,numpix,w3,r,g,b;
50 int bytepp=3;
51 
52 *bmap=NULL;
53 
54 if(((*palette)=malloc(768))==NULL)
55   return(_PICERR_NOMEM);
56 pal=work_pal=*palette;
57 
58 make_332_palette(pal);
59 
60 TIFFSetErrorHandler(NULL);	/* no error messages */
61 TIFFSetWarningHandler(NULL);	/* no warning messages either */
62 
63 /* first see if we can open it. This should catch *most* file-not-found
64  * errors, so we can avoid worrying them with the `corrupt' business. :-)
65  */
66 if((tmp=fopen(filename,"rb"))==NULL)
67   return(_PICERR_NOFILE);
68 
69 fclose(tmp);
70 
71 if((in=work_in=TIFFOpen(filename,"r"))==NULL)
72   return(_PICERR_CORRUPT);	/* probably a missing TIFF directory? */
73 
74 TIFFGetField(in,TIFFTAG_IMAGEWIDTH,&width);
75 TIFFGetField(in,TIFFTAG_IMAGELENGTH,&height);
76 
77 if(*output_type==1 || cfg.jpeg24bit==0)		/* dither? */
78   {
79   bytepp=1;
80   if(ditherinit(width)==0)
81     CLOSE_AND_RET(_PICERR_NOMEM);
82   }
83 
84 /* an extra width*3 guarantees there'll be at least one line
85  * spare for the flip afterwards, but we need twice that to be
86  * certain the dithering has room.
87  */
88 numpix=width*height;
89 if(WH_BAD(width,height) ||
90    (image=*bmap=work_bmap=malloc(numpix*sizeof(uint32)+width*3*2))==NULL)
91   CLOSE_AND_RET(_PICERR_NOMEM);
92 
93 /* XXX what about hffunc!? */
94 if(!TIFFReadRGBAImage(in,width,height,(uint32 *)image,0))
95   {
96   /* caller frees pal/image on error, so just this... */
97   CLOSE_AND_RET(_PICERR_CORRUPT);
98   }
99 
100 TIFFClose(in);
101 
102 
103 /* This is a pretty crappy way to work :-), but the alternative
104  * way (supplying routines to write any contiguous/planar RGBA chunks
105  * you get passed) is, stunningly, even worse.
106  */
107 
108 /* RGBA to BGR */
109 src=dst=image;
110 
111 /* first two pixels are a bit awkward */
112 for(f=0;f<2 && f<numpix;f++,dst+=3)
113   {
114   r=*src++; g=*src++; b=*src++; src++;
115   dst[2]=b; dst[1]=g; *dst=r;
116   }
117 
118 /* the rest can be done a bit more sanely */
119 for(f=2;f<numpix;f++,dst+=3)
120   {
121   dst[2]=*src++;
122   dst[1]=*src++;
123   *dst=*src++;
124   src++;
125   }
126 
127 /* flip the image vertically */
128 src=image;
129 w3=width*3;
130 dst=image+(height-1)*w3;
131 ptr=dst+w3;	/* use extra space for temp row */
132 for(f=0;f<height/2;f++)
133   {
134   memcpy(ptr,src,w3);
135   memcpy(src,dst,w3);
136   memcpy(dst,ptr,w3);
137   src+=w3;
138   dst-=w3;
139   }
140 
141 /* XXX would be better to combine this with one of the above steps.
142  * Would also be hairy, which is why I've not done it. :-)
143  */
144 if(bytepp==1)
145   {
146   for(y=0,ptr=image;y<height;y++,ptr+=width*3)
147     {
148     ditherline(ptr,y,width);
149     if(y>0) memcpy(image+y*width,ptr,width);
150     if(howfarfunc!=NULL) howfarfunc(height+y,height*2);
151     }
152 
153   ditherfinish();
154   }
155 
156 *bmap=realloc(*bmap,numpix*bytepp);
157 
158 /* If the realloc() fails (which it can't?), the memory will still be
159  * there as before, so we can still return ok.
160  */
161 
162 *output_type=bytepp;
163 pp->width=width;
164 pp->height=height;
165 pp->numcols=256;
166 
167 return(_PIC_OK);
168 }
169