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
36struct TIFFDibImage {
37    TIFFRGBAImage tif;
38    int  dibinstalled;
39} ;
40
41
42HANDLE LoadTIFFinDIB(LPCTSTR lpFileName);
43HANDLE TIFFRGBA2DIB(TIFFDibImage* dib, uint32* raster)  ;
44
45static void
46MyWarningHandler(const char* module, const char* fmt, va_list ap)
47{
48    // ignore all warnings (unused tags, etc)
49    return;
50}
51
52static void
53MyErrorHandler(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.
60int 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
82void DibInstallHack(TIFFDibImage* img) ;
83
84PVOID 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
131HANDLE 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//
270typedef unsigned char u_char;
271
272
273#define DECLAREContigPutFunc(name) \
274static 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) \
284static 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
293DECLAREContigPutFunc(putContig1bitTile);
294static int getStripContig1Bit(TIFFRGBAImage* img, uint32* uraster, uint32 w, uint32 h);
295
296//typdef struct TIFFDibImage {
297//    TIFFRGBAImage tif;
298//    dibinstalled;
299//} TIFFDibImage ;
300
301void 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 */
323DECLAREContigPutFunc(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 */
351static uint32
352setorientation(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 */
392static int
393getStripContig1Bit(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