/************************************************************************ TIFF image file format support. $Id: raster-tiff.cxx 427 2004-09-27 04:45:31Z garland $ ************************************************************************/ #include #include #include #ifdef HAVE_LIBTIFF #include namespace gfx { //////////////////////////////////////////////////////////////////////// // // TIFF output // static bool __tiff_write(TIFF *tif, const ByteRaster& img) { TIFFSetField(tif, TIFFTAG_IMAGEWIDTH, img.width()); TIFFSetField(tif, TIFFTAG_IMAGELENGTH, img.height()); TIFFSetField(tif, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT); TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, img.channels()); TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); TIFFSetField(tif, TIFFTAG_PHOTOMETRIC, img.channels()==1 ? PHOTOMETRIC_MINISBLACK : PHOTOMETRIC_RGB); #ifdef HAVE_LIBTIFF_LZW // // LZW compression is problematic because it is patented by Unisys. TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_LZW); // // Predictors: // 1 (default) -- No predictor // 2 -- Horizontal differencing TIFFSetField(tif, TIFFTAG_PREDICTOR, 2); #endif uint32 scanline_size = img.channels() * img.width(); if( TIFFScanlineSize(tif) != scanline_size ) // ??BUG: Can this mismatch of scanline sizes every occur? return false; TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(tif, 0)); char *scanline_buf = new char[scanline_size]; const unsigned char *scanline = img.head(); for(int y=0; yhead(); for(int i=0; ichannels() >= 3 ) { *pix++ = TIFFGetG(raster[i]); *pix++ = TIFFGetB(raster[i]); if( img->channels() == 4 ) *pix++ = TIFFGetA(raster[i]); } } } static ByteRaster *__tiff_read(TIFF *tif) { uint32 w, h; uint16 nchan; TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &w); TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &h); TIFFGetField(tif, TIFFTAG_SAMPLESPERPIXEL, &nchan); int npixels = w*h; uint32 *raster = (uint32 *)_TIFFmalloc(npixels * sizeof(uint32)); if( !raster ) return NULL; TIFFReadRGBAImage(tif, w, h, raster, true); ByteRaster *img = new ByteRaster(w, h, nchan); unpack_tiff_raster(raster, img, npixels); // // libtiff returned the pixels with the origin in the lower left // rather than the upper left corner. We fix that by flipping the // pixels. // img->vflip(); _TIFFfree(raster); return img; } ByteRaster *read_tiff_image(const char *filename) { TIFF *tif = TIFFOpen(filename, "r"); if( !tif ) return NULL; ByteRaster *img = __tiff_read(tif); TIFFClose(tif); return img; } } // namespace gfx #else namespace gfx { bool write_tiff_image(const char *, const ByteRaster&) { return false; } ByteRaster *read_tiff_image(const char *) { return NULL; } } #endif