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