123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449 |
- #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:
- */
|