diff options
Diffstat (limited to 'tiff/contrib/win_dib/Tiffile.cpp')
-rw-r--r-- | tiff/contrib/win_dib/Tiffile.cpp | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/tiff/contrib/win_dib/Tiffile.cpp b/tiff/contrib/win_dib/Tiffile.cpp new file mode 100644 index 0000000..9d958b1 --- /dev/null +++ b/tiff/contrib/win_dib/Tiffile.cpp @@ -0,0 +1,449 @@ +#include "StdAfx.h" + +//#define STRICT +#include <windows.h> +#include <windowsx.h> +#include <commdlg.h> +#include <stdlib.h> // MAX_ constants +#include "diblib.h" + +/*-------------------------------------------------------------------- + READ TIFF + Load the TIFF data from the file into memory. Return + a pointer to a valid DIB (or NULL for errors). + Uses the TIFFRGBA interface to libtiff.lib to convert + most file formats to a useable form. We just keep the 32 bit + form of the data to display, rather than optimizing for the + display. + + Main entry points: + + int ChkTIFF ( LPCTSTR lpszPath ) + PVOID ReadTIFF ( LPCTSTR lpszPath ) + + RETURN + A valid DIB pointer for success; NULL for failure. + + --------------------------------------------------------------------*/ + +#include "TiffLib/tiff.h" +#include "TiffLib/tiffio.h" +#include <assert.h> +#include <stdio.h> + + +// piggyback some data on top of the RGBA Image +struct TIFFDibImage { + TIFFRGBAImage tif; + int dibinstalled; +} ; + + +HANDLE LoadTIFFinDIB(LPCTSTR lpFileName); +HANDLE TIFFRGBA2DIB(TIFFDibImage* dib, uint32* raster) ; + +static void +MyWarningHandler(const char* module, const char* fmt, va_list ap) +{ + // ignore all warnings (unused tags, etc) + return; +} + +static void +MyErrorHandler(const char* module, const char* fmt, va_list ap) +{ + return; +} + +// Turn off the error and warning handlers to check if a valid file. +// Necessary because of the way that the Doc loads images and restart files. +int ChkTIFF ( LPCTSTR lpszPath ) +{ + int rtn = 0; + + TIFFErrorHandler eh; + TIFFErrorHandler wh; + + eh = TIFFSetErrorHandler(NULL); + wh = TIFFSetWarningHandler(NULL); + + TIFF* tif = TIFFOpen(lpszPath, "r"); + if (tif) { + rtn = 1; + TIFFClose(tif); + } + + TIFFSetErrorHandler(eh); + TIFFSetWarningHandler(wh); + + return rtn; +} + +void DibInstallHack(TIFFDibImage* img) ; + +PVOID ReadTIFF ( LPCTSTR lpszPath ) +{ + void* pDIB = 0; + TIFFErrorHandler wh; + + wh = TIFFSetWarningHandler(MyWarningHandler); + + if (ChkTIFF(lpszPath)) { + TIFF* tif = TIFFOpen(lpszPath, "r"); + if (tif) { + char emsg[1024]; + + if (TIFFRGBAImageOK(tif, emsg)) { + TIFFDibImage img; + char emsg[1024]; + + if (TIFFRGBAImageBegin(&img.tif, tif, -1, emsg)) { + size_t npixels; + uint32* raster; + + DibInstallHack(&img); + + npixels = img.tif.width * img.tif.height; + raster = (uint32*) _TIFFmalloc(npixels * sizeof (uint32)); + if (raster != NULL) { + if (TIFFRGBAImageGet(&img.tif, raster, img.tif.width, img.tif.height)) { + pDIB = TIFFRGBA2DIB(&img, raster); + } + } + _TIFFfree(raster); + } + TIFFRGBAImageEnd(&img.tif); + } + else { + TRACE("Unable to open image(%s): %s\n", lpszPath, emsg ); + } + TIFFClose(tif); + } + } + + TIFFSetWarningHandler(wh); + + return pDIB; +} + + + +HANDLE TIFFRGBA2DIB(TIFFDibImage* dib, uint32* raster) +{ + void* pDIB = 0; + TIFFRGBAImage* img = &dib->tif; + + uint32 imageLength; + uint32 imageWidth; + uint16 BitsPerSample; + uint16 SamplePerPixel; + uint32 RowsPerStrip; + uint16 PhotometricInterpretation; + + BITMAPINFOHEADER bi; + int dwDIBSize ; + + TIFFGetField(img->tif, TIFFTAG_IMAGEWIDTH, &imageWidth); + TIFFGetField(img->tif, TIFFTAG_IMAGELENGTH, &imageLength); + TIFFGetField(img->tif, TIFFTAG_BITSPERSAMPLE, &BitsPerSample); + TIFFGetField(img->tif, TIFFTAG_ROWSPERSTRIP, &RowsPerStrip); + TIFFGetField(img->tif, TIFFTAG_SAMPLESPERPIXEL, &SamplePerPixel); + TIFFGetField(img->tif, TIFFTAG_PHOTOMETRIC, &PhotometricInterpretation); + + if ( BitsPerSample == 1 && SamplePerPixel == 1 && dib->dibinstalled ) { // bilevel + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = imageWidth; + bi.biHeight = imageLength; + bi.biPlanes = 1; // always + bi.biBitCount = 1; + bi.biCompression = BI_RGB; + bi.biSizeImage = WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight; + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; // must be zero for RGB compression (none) + bi.biClrImportant = 0; // always + + // Get the size of the DIB + dwDIBSize = GetDIBSize( &bi ); + + // Allocate for the BITMAPINFO structure and the color table. + pDIB = GlobalAllocPtr( GHND, dwDIBSize ); + if (pDIB == 0) { + return( NULL ); + } + + // Copy the header info + *((BITMAPINFOHEADER*)pDIB) = bi; + + // Get a pointer to the color table + RGBQUAD *pRgbq = (RGBQUAD *)((LPSTR)pDIB + sizeof(BITMAPINFOHEADER)); + + pRgbq[0].rgbRed = 0; + pRgbq[0].rgbBlue = 0; + pRgbq[0].rgbGreen = 0; + pRgbq[0].rgbReserved = 0; + pRgbq[1].rgbRed = 255; + pRgbq[1].rgbBlue = 255; + pRgbq[1].rgbGreen = 255; + pRgbq[1].rgbReserved = 255; + + // Pointers to the bits + //PVOID pbiBits = (LPSTR)pRgbq + bi.biClrUsed * sizeof(RGBQUAD); + // + // In the BITMAPINFOHEADER documentation, it appears that + // there should be no color table for 32 bit images, but + // experience shows that the image is off by 3 words if it + // is not included. So here it is. + PVOID pbiBits = GetDIBImagePtr((BITMAPINFOHEADER*)pDIB); //(LPSTR)pRgbq + 3 * sizeof(RGBQUAD); + + int sizeWords = bi.biSizeImage/4; + RGBQUAD* rgbDib = (RGBQUAD*)pbiBits; + long* rgbTif = (long*)raster; + + _TIFFmemcpy(pbiBits, raster, bi.biSizeImage); + } + + // For now just always default to the RGB 32 bit form. // save as 32 bit for simplicity + else if ( true /*BitsPerSample == 8 && SamplePerPixel == 3*/ ) { // 24 bit color + + bi.biSize = sizeof(BITMAPINFOHEADER); + bi.biWidth = imageWidth; + bi.biHeight = imageLength; + bi.biPlanes = 1; // always + bi.biBitCount = 32; + bi.biCompression = BI_RGB; + bi.biSizeImage = WIDTHBYTES(bi.biWidth * bi.biBitCount) * bi.biHeight; + bi.biXPelsPerMeter = 0; + bi.biYPelsPerMeter = 0; + bi.biClrUsed = 0; // must be zero for RGB compression (none) + bi.biClrImportant = 0; // always + + // Get the size of the DIB + dwDIBSize = GetDIBSize( &bi ); + + // Allocate for the BITMAPINFO structure and the color table. + pDIB = GlobalAllocPtr( GHND, dwDIBSize ); + if (pDIB == 0) { + return( NULL ); + } + + // Copy the header info + *((BITMAPINFOHEADER*)pDIB) = bi; + + // Get a pointer to the color table + RGBQUAD *pRgbq = (RGBQUAD *)((LPSTR)pDIB + sizeof(BITMAPINFOHEADER)); + + // Pointers to the bits + //PVOID pbiBits = (LPSTR)pRgbq + bi.biClrUsed * sizeof(RGBQUAD); + // + // In the BITMAPINFOHEADER documentation, it appears that + // there should be no color table for 32 bit images, but + // experience shows that the image is off by 3 words if it + // is not included. So here it is. + PVOID pbiBits = (LPSTR)pRgbq + 3 * sizeof(RGBQUAD); + + int sizeWords = bi.biSizeImage/4; + RGBQUAD* rgbDib = (RGBQUAD*)pbiBits; + long* rgbTif = (long*)raster; + + // Swap the byte order while copying + for ( int i = 0 ; i < sizeWords ; ++i ) + { + rgbDib[i].rgbRed = TIFFGetR(rgbTif[i]); + rgbDib[i].rgbBlue = TIFFGetB(rgbTif[i]); + rgbDib[i].rgbGreen = TIFFGetG(rgbTif[i]); + rgbDib[i].rgbReserved = 0; + } + } + + return pDIB; +} + + + + +/////////////////////////////////////////////////////////////// +// +// Hacked from tif_getimage.c in libtiff in v3.5.7 +// +// +typedef unsigned char u_char; + + +#define DECLAREContigPutFunc(name) \ +static void name(\ + TIFFRGBAImage* img, \ + uint32* cp, \ + uint32 x, uint32 y, \ + uint32 w, uint32 h, \ + int32 fromskew, int32 toskew, \ + u_char* pp \ +) + +#define DECLARESepPutFunc(name) \ +static void name(\ + TIFFRGBAImage* img,\ + uint32* cp,\ + uint32 x, uint32 y, \ + uint32 w, uint32 h,\ + int32 fromskew, int32 toskew,\ + u_char* r, u_char* g, u_char* b, u_char* a\ +) + +DECLAREContigPutFunc(putContig1bitTile); +static int getStripContig1Bit(TIFFRGBAImage* img, uint32* uraster, uint32 w, uint32 h); + +//typdef struct TIFFDibImage { +// TIFFRGBAImage tif; +// dibinstalled; +//} TIFFDibImage ; + +void DibInstallHack(TIFFDibImage* dib) { + TIFFRGBAImage* img = &dib->tif; + dib->dibinstalled = false; + switch (img->photometric) { + case PHOTOMETRIC_MINISWHITE: + case PHOTOMETRIC_MINISBLACK: + switch (img->bitspersample) { + case 1: + img->put.contig = putContig1bitTile; + img->get = getStripContig1Bit; + dib->dibinstalled = true; + break; + } + break; + } +} + +/* + * 1-bit packed samples => 1-bit + * + * Override to just copy the data + */ +DECLAREContigPutFunc(putContig1bitTile) +{ + int samplesperpixel = img->samplesperpixel; + + (void) y; + fromskew *= samplesperpixel; + int wb = WIDTHBYTES(w); + u_char* ucp = (u_char*)cp; + + /* Conver 'w' to bytes from pixels (rounded up) */ + w = (w+7)/8; + + while (h-- > 0) { + _TIFFmemcpy(ucp, pp, w); + /* + for (x = wb; x-- > 0;) { + *cp++ = rgbi(Map[pp[0]], Map[pp[1]], Map[pp[2]]); + pp += samplesperpixel; + } + */ + ucp += (wb + toskew); + pp += (w + fromskew); + } +} + +/* + * Hacked from the tif_getimage.c file. + */ +static uint32 +setorientation(TIFFRGBAImage* img, uint32 h) +{ + TIFF* tif = img->tif; + uint32 y; + + switch (img->orientation) { + case ORIENTATION_BOTRIGHT: + case ORIENTATION_RIGHTBOT: /* XXX */ + case ORIENTATION_LEFTBOT: /* XXX */ + TIFFWarning(TIFFFileName(tif), "using bottom-left orientation"); + img->orientation = ORIENTATION_BOTLEFT; + /* fall thru... */ + case ORIENTATION_BOTLEFT: + y = 0; + break; + case ORIENTATION_TOPRIGHT: + case ORIENTATION_RIGHTTOP: /* XXX */ + case ORIENTATION_LEFTTOP: /* XXX */ + default: + TIFFWarning(TIFFFileName(tif), "using top-left orientation"); + img->orientation = ORIENTATION_TOPLEFT; + /* fall thru... */ + case ORIENTATION_TOPLEFT: + y = h-1; + break; + } + return (y); +} + +/* + * Get a strip-organized image that has + * PlanarConfiguration contiguous if SamplesPerPixel > 1 + * or + * SamplesPerPixel == 1 + * + * Hacked from the tif_getimage.c file. + * + * This is set up to allow us to just copy the data to the raster + * for 1-bit bitmaps + */ +static int +getStripContig1Bit(TIFFRGBAImage* img, uint32* raster, uint32 w, uint32 h) +{ + TIFF* tif = img->tif; + tileContigRoutine put = img->put.contig; + uint16 orientation; + uint32 row, y, nrow, rowstoread; + uint32 pos; + u_char* buf; + uint32 rowsperstrip; + uint32 imagewidth = img->width; + tsize_t scanline; + int32 fromskew, toskew; + tstrip_t strip; + tsize_t stripsize; + u_char* braster = (u_char*)raster; // byte wide raster + uint32 wb = WIDTHBYTES(w); + int ret = 1; + + buf = (u_char*) _TIFFmalloc(TIFFStripSize(tif)); + if (buf == 0) { + TIFFErrorExt(tif->tif_clientdata, TIFFFileName(tif), "No space for strip buffer"); + return (0); + } + y = setorientation(img, h); + orientation = img->orientation; + toskew = -(int32) (orientation == ORIENTATION_TOPLEFT ? wb+wb : wb-wb); + TIFFGetFieldDefaulted(tif, TIFFTAG_ROWSPERSTRIP, &rowsperstrip); + scanline = TIFFScanlineSize(tif); + fromskew = (w < imagewidth ? imagewidth - w : 0)/8; + for (row = 0; row < h; row += nrow) + { + rowstoread = rowsperstrip - (row + img->row_offset) % rowsperstrip; + nrow = (row + rowstoread > h ? h - row : rowstoread); + strip = TIFFComputeStrip(tif,row+img->row_offset, 0); + stripsize = ((row + img->row_offset)%rowsperstrip + nrow) * scanline; + if (TIFFReadEncodedStrip(tif, strip, buf, stripsize ) < 0 + && img->stoponerr) + { + ret = 0; + break; + } + + pos = ((row + img->row_offset) % rowsperstrip) * scanline; + (*put)(img, (uint32*)(braster+y*wb), 0, y, w, nrow, fromskew, toskew, buf + pos); + y += (orientation == ORIENTATION_TOPLEFT ?-(int32) nrow : (int32) nrow); + } + _TIFFfree(buf); + return (ret); +} + +/* + * Local Variables: + * mode: c++ + * c-basic-offset: 8 + * fill-column: 78 + * End: + */ |