]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/contrib/win_dib/Tiffile.cpp
Initial implementation of wxWebProtocolHandler and wxWebFileProtocolHandler for the...
[wxWidgets.git] / src / tiff / contrib / win_dib / Tiffile.cpp
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
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
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.
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
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
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
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 */
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
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
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