Index: grfmt_tiff.cpp =================================================================== --- grfmt_tiff.cpp (revision 5083) +++ grfmt_tiff.cpp (working copy) @@ -321,13 +321,107 @@ strm.putDWord( value ); } +#ifdef HAVE_TIFF -bool TiffEncoder::write( const Mat& img, const vector& ) +#include "tiff.h" +#include "tiffio.h" + +bool TiffEncoder::writeLibTiff( const Mat& img, const vector& /*params*/) { int channels = img.channels(); int width = img.cols, height = img.rows; int depth = img.depth(); + int bitsPerChannel = -1; + switch (depth) + { + case CV_8U: + { + bitsPerChannel = 8; + break; + } + case CV_16U: + { + bitsPerChannel = 16; + break; + } + default: + { + return false; + } + } + + // do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode. + // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html + TIFF* pTiffHandle = TIFFOpen(m_filename.c_str(), "w"); + if (!pTiffHandle) + { + return false; + } + + // defaults for now, maybe base them on params in the future + int compression = COMPRESSION_LZW; + int predictor = PREDICTOR_HORIZONTAL; + + float xresolution = 120.0; + float yresolution = 120.0; + int rowsperstrip = 100; + + if ( !TIFFSetField(pTiffHandle, TIFFTAG_SUBFILETYPE, 0) + || !TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width) + || !TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height) + || !TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel) + || !TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression) + || !TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB) + || !TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels) + || !TIFFSetField(pTiffHandle, TIFFTAG_XRESOLUTION, xresolution) + || !TIFFSetField(pTiffHandle, TIFFTAG_YRESOLUTION, yresolution) + || !TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG) + || !TIFFSetField(pTiffHandle, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH) + || !TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsperstrip) + || !TIFFSetField(pTiffHandle, TIFFTAG_PREDICTOR, predictor) + ) + { + TIFFClose(pTiffHandle); + return false; + } + + // row buffer, because TIFFWriteScanline modifies the original data! + size_t scanlineSize = TIFFScanlineSize(pTiffHandle); + unsigned char* scanline = (unsigned char*) _TIFFmalloc(scanlineSize); + if (!scanline) + { + TIFFClose(pTiffHandle); + return false; + } + + for (int y = 0; y < height; ++y) + { + memcpy(scanline, img.data + img.step * y, scanlineSize); + int writeResult = TIFFWriteScanline(pTiffHandle, scanline, y, 0); + if (writeResult != 1) + { + TIFFClose(pTiffHandle); + return false; + } + } + + TIFFClose(pTiffHandle); + return true; +} + +#endif + +#ifdef HAVE_TIFF +bool TiffEncoder::write( const Mat& img, const vector& params) +#else +bool TiffEncoder::write( const Mat& img, const vector& /*params*/) +#endif +{ + int channels = img.channels(); + int width = img.cols, height = img.rows; + int depth = img.depth(); + if (depth != CV_8U && depth != CV_16U) return false; @@ -341,8 +435,15 @@ if( !strm.open(*m_buf) ) return false; } - else if( !strm.open(m_filename) ) - return false; + else + { +#ifdef HAVE_TIFF + return writeLibTiff(img, params); +#else + if( !strm.open(m_filename) ) + return false; +#endif + } int rowsPerStrip = (1 << 13)/fileStep; Index: grfmt_tiff.hpp =================================================================== --- grfmt_tiff.hpp (revision 5083) +++ grfmt_tiff.hpp (working copy) @@ -127,6 +127,8 @@ void writeTag( WLByteStream& strm, TiffTag tag, TiffFieldType fieldType, int count, int value ); + + bool writeLibTiff( const Mat& img, const vector& params ); }; }