1 #include "StdAfx.h"
2 
3 //#define STRICT
4 #include <windows.h>
5 #include <windowsx.h>
6 #include <commdlg.h>
7 #include <stdlib.h>                     // MAX_ constants
8 #include "diblib.h"
9 
10 /*--------------------------------------------------------------------
11         READ TIFF
12         Load the TIFF data from the file into memory.  Return
13         a pointer to a valid DIB (or NULL for errors).
14         Uses the TIFFRGBA interface to libtiff.lib to convert
15         most file formats to a useable form.  We just keep the 32 bit
16         form of the data to display, rather than optimizing for the
17         display.
18 
19         Main entry points:
20 
21             int ChkTIFF ( LPCTSTR lpszPath )
22             PVOID ReadTIFF ( LPCTSTR lpszPath )
23 
24         RETURN
25             A valid DIB pointer for success; NULL for failure.
26 
27   --------------------------------------------------------------------*/
28 
29 #include "TiffLib/tiff.h"
30 #include "TiffLib/tiffio.h"
31 #include <assert.h>
32 #include <stdio.h>
33 
34 
35 // piggyback some data on top of the RGBA Image
36 struct TIFFDibImage {
37     TIFFRGBAImage tif;
38     int  dibinstalled;
39 } ;
40 
41 
42 HANDLE LoadTIFFinDIB(LPCTSTR lpFileName);
43 HANDLE TIFFRGBA2DIB(TIFFDibImage* dib, uint32* raster)  ;
44 
45 static void
MyWarningHandler(const char * module,const char * fmt,va_list ap)46 MyWarningHandler(const char* module, const char* fmt, va_list ap)
47 {
48     // ignore all warnings (unused tags, etc)
49     return;
50 }
51 
52 static void
MyErrorHandler(const char * module,const char * fmt,va_list ap)53 MyErrorHandler(const char* module, const char* fmt, va_list ap)
54 {
55     return;
56 }
57 
58 //  Turn off the error and warning handlers to check if a valid file.
59 //  Necessary because of the way that the Doc loads images and restart files.
ChkTIFF(LPCTSTR lpszPath)60 int ChkTIFF ( LPCTSTR lpszPath )
61 {
62     int rtn = 0;
63 
64     TIFFErrorHandler  eh;
65     TIFFErrorHandler  wh;
66 
67     eh = TIFFSetErrorHandler(NULL);
68     wh = TIFFSetWarningHandler(NULL);
69 
70     TIFF* tif = TIFFOpen(lpszPath, "r");
71     if (tif) {
72         rtn = 1;
73         TIFFClose(tif);
74     }
75 
76     TIFFSetErrorHandler(eh);
77     TIFFSetWarningHandler(wh);
78 
79     return rtn;
80 }
81 
82 void DibInstallHack(TIFFDibImage* img) ;
83 
ReadTIFF(LPCTSTR lpszPath)84 PVOID ReadTIFF ( LPCTSTR lpszPath )
85 {
86     void*             pDIB = 0;
87     TIFFErrorHandler  wh;
88 
89     wh = TIFFSetWarningHandler(MyWarningHandler);
90 
91     if (ChkTIFF(lpszPath)) {
92         TIFF* tif = TIFFOpen(lpszPath, "r");
93         if (tif) {
94             char emsg[1024];
95 
96             if (TIFFRGBAImageOK(tif, emsg)) {
97                 TIFFDibImage img;
98                 char emsg[1024];
99 
100                 if (TIFFRGBAImageBegin(&img.tif, tif, -1, emsg)) {
101                     size_t npixels;
102                     uint32* raster;
103 
104                     DibInstallHack(&img);
105 
106                     npixels = img.tif.width * img.tif.height;
107                     raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32));
108                     if (raster != NULL) {
109                         if (TIFFRGBAImageGet(&img.tif, raster, img.tif.width, img.tif.height)) {
110                             pDIB = TIFFRGBA2DIB(&img, raster);
111                         }
112                     }
113                     _TIFFfree(raster);
114                 }
115                 TIFFRGBAImageEnd(&img.tif);
116             }
117             else {
118                 TRACE("Unable to open image(%s): %s\n", lpszPath, emsg );
119             }
120             TIFFClose(tif);
121         }
122     }
123 
124     TIFFSetWarningHandler(wh);
125 
126     return pDIB;
127 }
128 
129 
130 
TIFFRGBA2DIB(TIFFDibImage * dib,uint32 * raster)131 HANDLE TIFFRGBA2DIB(TIFFDibImage* dib, uint32* raster)
132 {
133     void*   pDIB = 0;
134     TIFFRGBAImage* img = &dib->tif;
135 
136     uint32 imageLength;
137     uint32 imageWidth;
138     uint16 BitsPerSample;
139     uint16 SamplePerPixel;
140     uint32 RowsPerStrip;
141     uint16 PhotometricInterpretation;
142 
143     BITMAPINFOHEADER   bi;
144     int                dwDIBSize ;
145 
146     TIFFGetField(img->tif, TIFFTAG_IMAGEWIDTH, &imageWidth);
147     TIFFGetField(img->tif, TIFFTAG_IMAGELENGTH, &imageLength);
148     TIFFGetField(img->tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample);
149     TIFFGetField(img->tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip);
150     TIFFGetField(img->tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel);
151     TIFFGetField(img->tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation);
152 
153     if ( BitsPerSample == 1 && SamplePerPixel == 1 && dib->dibinstalled ) {   // bilevel
154         bi.biSize           = sizeof(BITMAPINFOHEADER);
155         bi.biWidth          = imageWidth;
156         bi.biHeight         = imageLength;
157         bi.biPlanes         = 1;  // always
158         bi.biBitCount       = 1;
159         bi.biCompression    = BI_RGB;
160         bi.biSizeImage      = WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight;
161         bi.biXPelsPerMeter  = 0;
162         bi.biYPelsPerMeter  = 0;
163         bi.biClrUsed        = 0;  //  must be zero for RGB compression (none)
164         bi.biClrImportant   = 0;  // always
165 
166         // Get the size of the DIB
167         dwDIBSize = GetDIBSize( &bi );
168 
169         // Allocate for the BITMAPINFO structure and the color table.
170         pDIB = GlobalAllocPtr( GHND, dwDIBSize );
171         if (pDIB == 0) {
172             return( NULL );
173         }
174 
175         // Copy the header info
176         *((BITMAPINFOHEADER*)pDIB) = bi;
177 
178         // Get a pointer to the color table
179         RGBQUAD   *pRgbq = (RGBQUAD   *)((LPSTR)pDIB + sizeof(BITMAPINFOHEADER));
180 
181         pRgbq[0].rgbRed      = 0;
182         pRgbq[0].rgbBlue     = 0;
183         pRgbq[0].rgbGreen    = 0;
184         pRgbq[0].rgbReserved = 0;
185         pRgbq[1].rgbRed      = 255;
186         pRgbq[1].rgbBlue     = 255;
187         pRgbq[1].rgbGreen    = 255;
188         pRgbq[1].rgbReserved = 255;
189 
190         // Pointers to the bits
191         //PVOID pbiBits = (LPSTR)pRgbq + bi.biClrUsed * sizeof(RGBQUAD);
192         //
193         // In the BITMAPINFOHEADER documentation, it appears that
194         // there should be no color table for 32 bit images, but
195         // experience shows that the image is off by 3 words if it
196         // is not included.  So here it is.
197         PVOID pbiBits = GetDIBImagePtr((BITMAPINFOHEADER*)pDIB);  //(LPSTR)pRgbq + 3 * sizeof(RGBQUAD);
198 
199         int       sizeWords = bi.biSizeImage/4;
200         RGBQUAD*  rgbDib = (RGBQUAD*)pbiBits;
201         long*     rgbTif = (long*)raster;
202 
203         _TIFFmemcpy(pbiBits, raster, bi.biSizeImage);
204     }
205 
206         //  For now just always default to the RGB 32 bit form.                                                       // save as 32 bit for simplicity
207     else if ( true /*BitsPerSample == 8 && SamplePerPixel == 3*/ ) {   // 24 bit color
208 
209         bi.biSize           = sizeof(BITMAPINFOHEADER);
210         bi.biWidth          = imageWidth;
211         bi.biHeight         = imageLength;
212         bi.biPlanes         = 1;  // always
213         bi.biBitCount       = 32;
214         bi.biCompression    = BI_RGB;
215         bi.biSizeImage      = WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight;
216         bi.biXPelsPerMeter  = 0;
217         bi.biYPelsPerMeter  = 0;
218         bi.biClrUsed        = 0;  //  must be zero for RGB compression (none)
219         bi.biClrImportant   = 0;  // always
220 
221         // Get the size of the DIB
222         dwDIBSize = GetDIBSize( &bi );
223 
224         // Allocate for the BITMAPINFO structure and the color table.
225         pDIB = GlobalAllocPtr( GHND, dwDIBSize );
226         if (pDIB == 0) {
227             return( NULL );
228         }
229 
230         // Copy the header info
231         *((BITMAPINFOHEADER*)pDIB) = bi;
232 
233         // Get a pointer to the color table
234         RGBQUAD   *pRgbq = (RGBQUAD   *)((LPSTR)pDIB + sizeof(BITMAPINFOHEADER));
235 
236         // Pointers to the bits
237         //PVOID pbiBits = (LPSTR)pRgbq + bi.biClrUsed * sizeof(RGBQUAD);
238         //
239         // In the BITMAPINFOHEADER documentation, it appears that
240         // there should be no color table for 32 bit images, but
241         // experience shows that the image is off by 3 words if it
242         // is not included.  So here it is.
243         PVOID pbiBits = (LPSTR)pRgbq + 3 * sizeof(RGBQUAD);
244 
245         int       sizeWords = bi.biSizeImage/4;
246         RGBQUAD*  rgbDib = (RGBQUAD*)pbiBits;
247         long*     rgbTif = (long*)raster;
248 
249         // Swap the byte order while copying
250         for ( int i = 0 ; i < sizeWords ; ++i )
251         {
252             rgbDib[i].rgbRed   = TIFFGetR(rgbTif[i]);
253             rgbDib[i].rgbBlue  = TIFFGetB(rgbTif[i]);
254             rgbDib[i].rgbGreen = TIFFGetG(rgbTif[i]);
255             rgbDib[i].rgbReserved = 0;
256         }
257     }
258 
259     return pDIB;
260 }
261 
262 
263 
264 
265 ///////////////////////////////////////////////////////////////
266 //
267 //  Hacked from tif_getimage.c in libtiff in v3.5.7
268 //
269 //
270 typedef unsigned char u_char;
271 
272 
273 #define DECLAREContigPutFunc(name) \
274 static void name(\
275     TIFFRGBAImage* img, \
276     uint32* cp, \
277     uint32 x, uint32 y, \
278     uint32 w, uint32 h, \
279     int32 fromskew, int32 toskew, \
280     u_char* pp \
281 )
282 
283 #define DECLARESepPutFunc(name) \
284 static void name(\
285     TIFFRGBAImage* img,\
286     uint32* cp,\
287     uint32 x, uint32 y, \
288     uint32 w, uint32 h,\
289     int32 fromskew, int32 toskew,\
290     u_char* r, u_char* g, u_char* b, u_char* a\
291 )
292 
293 DECLAREContigPutFunc(putContig1bitTile);
294 static int getStripContig1Bit(TIFFRGBAImage* img, uint32* uraster, uint32 w, uint32 h);
295 
296 //typdef struct TIFFDibImage {
297 //    TIFFRGBAImage tif;
298 //    dibinstalled;
299 //} TIFFDibImage ;
300 
DibInstallHack(TIFFDibImage * dib)301 void DibInstallHack(TIFFDibImage* dib) {
302     TIFFRGBAImage* img = &dib->tif;
303     dib->dibinstalled = false;
304     switch (img->photometric) {
305         case PHOTOMETRIC_MINISWHITE:
306         case PHOTOMETRIC_MINISBLACK:
307         switch (img->bitspersample) {
308             case 1:
309                 img->put.contig = putContig1bitTile;
310                 img->get = getStripContig1Bit;
311                 dib->dibinstalled = true;
312                 break;
313         }
314         break;
315     }
316 }
317 
318 /*
319  * 1-bit packed samples => 1-bit
320  *
321  *   Override to just copy the data
322  */
DECLAREContigPutFunc(putContig1bitTile)323 DECLAREContigPutFunc(putContig1bitTile)
324 {
325     int samplesperpixel = img->samplesperpixel;
326 
327     (void) y;
328     fromskew *= samplesperpixel;
329     int wb = WIDTHBYTES(w);
330     u_char*  ucp = (u_char*)cp;
331 
332     /* Conver 'w' to bytes from pixels (rounded up) */
333     w = (w+7)/8;
334 
335     while (h-- > 0) {
336         _TIFFmemcpy(ucp, pp, w);
337         /*
338         for (x = wb; x-- > 0;) {
339             *cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]);
340             pp += samplesperpixel;
341         }
342         */
343         ucp += (wb + toskew);
344         pp += (w + fromskew);
345     }
346 }
347 
348 /*
349  *  Hacked from the tif_getimage.c file.
350  */
351 static uint32
setorientation(TIFFRGBAImage * img,uint32 h)352 setorientation(TIFFRGBAImage* img, uint32 h)
353 {
354     TIFF* tif = img->tif;
355     uint32 y;
356 
357     switch (img->orientation) {
358     case ORIENTATION_BOTRIGHT:
359     case ORIENTATION_RIGHTBOT:  /* XXX */
360     case ORIENTATION_LEFTBOT:   /* XXX */
361     TIFFWarning(TIFFFileName(tif), "using bottom-left orientation");
362     img->orientation = ORIENTATION_BOTLEFT;
363     /* fall thru... */
364     case ORIENTATION_BOTLEFT:
365     y = 0;
366     break;
367     case ORIENTATION_TOPRIGHT:
368     case ORIENTATION_RIGHTTOP:  /* XXX */
369     case ORIENTATION_LEFTTOP:   /* XXX */
370     default:
371     TIFFWarning(TIFFFileName(tif), "using top-left orientation");
372     img->orientation = ORIENTATION_TOPLEFT;
373     /* fall thru... */
374     case ORIENTATION_TOPLEFT:
375     y = h-1;
376     break;
377     }
378     return (y);
379 }
380 
381 /*
382  * Get a strip-organized image that has
383  *  PlanarConfiguration contiguous if SamplesPerPixel > 1
384  * or
385  *  SamplesPerPixel == 1
386  *
387  *  Hacked from the tif_getimage.c file.
388  *
389  *    This is set up to allow us to just copy the data to the raster
390  *    for 1-bit bitmaps
391  */
392 static int
getStripContig1Bit(TIFFRGBAImage * img,uint32 * raster,uint32 w,uint32 h)393 getStripContig1Bit(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h)
394 {
395     TIFF* tif = img->tif;
396     tileContigRoutine put = img->put.contig;
397     uint16 orientation;
398     uint32 row, y, nrow, rowstoread;
399     uint32 pos;
400     u_char* buf;
401     uint32 rowsperstrip;
402     uint32 imagewidth = img->width;
403     tsize_t scanline;
404     int32 fromskew, toskew;
405     tstrip_t strip;
406     tsize_t  stripsize;
407     u_char* braster = (u_char*)raster; // byte wide raster
408     uint32  wb = WIDTHBYTES(w);
409     int ret = 1;
410 
411     buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif));
412     if (buf == 0) {
413         TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer");
414         return (0);
415     }
416     y = setorientation(img, h);
417     orientation = img->orientation;
418     toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? wb+wb : wb-wb);
419     TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip);
420     scanline = TIFFScanlineSize(tif);
421     fromskew = (w < imagewidth ? imagewidth - w : 0)/8;
422     for (row = 0; row < h; row += nrow)
423     {
424         rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip;
425         nrow = (row + rowstoread > h ? h - row : rowstoread);
426         strip = TIFFComputeStrip(tif,row+img->row_offset, 0);
427         stripsize = ((row + img->row_offset)%rowsperstrip + nrow) * scanline;
428         if (TIFFReadEncodedStrip(tif, strip, buf, stripsize ) < 0
429             && img->stoponerr)
430         {
431             ret = 0;
432             break;
433         }
434 
435         pos = ((row + img->row_offset) % rowsperstrip) * scanline;
436         (*put)(img, (uint32*)(braster+y*wb), 0, y, w, nrow, fromskew, toskew, buf + pos);
437         y += (orientation == ORIENTATION_TOPLEFT ?-(int32) nrow : (int32) nrow);
438     }
439     _TIFFfree(buf);
440     return (ret);
441 }
442 
443 /*
444  * Local Variables:
445  * mode: c++
446  * c-basic-offset: 8
447  * fill-column: 78
448  * End:
449  */
450