1 /*M///////////////////////////////////////////////////////////////////////////////////////
3 // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
5 // By downloading, copying, installing or using the software you agree to this license.
6 // If you do not agree to this license, do not download, install,
7 // copy or use the software.
11 // For Open Source Computer Vision Library
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
20 // * Redistribution's of source code must retain the above copyright notice,
21 // this list of conditions and the following disclaimer.
23 // * Redistribution's in binary form must reproduce the above copyright notice,
24 // this list of conditions and the following disclaimer in the documentation
25 // and/or other materials provided with the distribution.
27 // * The name of the copyright holders may not be used to endorse or promote products
28 // derived from this software without specific prior written permission.
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
43 /****************************************************************************************\
44 A part of the file implements TIFF reader on base of libtiff library
45 (see otherlibs/_graphics/readme.txt for copyright notice)
46 \****************************************************************************************/
50 #include "precomp.hpp"
51 #include "grfmt_tiff.hpp"
53 #define int64 int64_tiff
54 #define uint64 uint64_tiff
63 static const char fmtSignTiffII[] = "II\x2a\x00";
67 static const char fmtSignTiffMM[] = "MM\x00\x2a";
68 static int grfmt_tiff_err_handler_init = 0;
69 static void GrFmtSilentTIFFErrorHandler( const char*, const char*, va_list ) {}
71 TiffDecoder::TiffDecoder()
74 if( !grfmt_tiff_err_handler_init )
76 grfmt_tiff_err_handler_init = 1;
78 TIFFSetErrorHandler( GrFmtSilentTIFFErrorHandler );
79 TIFFSetWarningHandler( GrFmtSilentTIFFErrorHandler );
84 void TiffDecoder::close()
88 TIFF* tif = (TIFF*)m_tif;
94 TiffDecoder::~TiffDecoder()
99 size_t TiffDecoder::signatureLength() const
104 bool TiffDecoder::checkSignature( const string& signature ) const
106 return signature.size() >= 4 &&
107 (memcmp(signature.c_str(), fmtSignTiffII, 4) == 0 ||
108 memcmp(signature.c_str(), fmtSignTiffMM, 4) == 0);
111 ImageDecoder TiffDecoder::newDecoder() const
113 return new TiffDecoder;
116 bool TiffDecoder::readHeader()
121 // TIFFOpen() mode flags are different to fopen(). A 'b' in mode "rb" has no effect when reading.
122 // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
123 TIFF* tif = TIFFOpen( m_filename.c_str(), "r" );
127 uint32 wdth = 0, hght = 0;
128 uint16 photometric = 0;
131 if( TIFFGetField( tif, TIFFTAG_IMAGEWIDTH, &wdth ) &&
132 TIFFGetField( tif, TIFFTAG_IMAGELENGTH, &hght ) &&
133 TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric ))
135 uint16 bpp=8, ncn = photometric > 1 ? 3 : 1;
136 TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp );
137 TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn );
142 ((photometric != 2 && photometric != 1) ||
143 (ncn != 1 && ncn != 3 && ncn != 4)))
149 m_type = CV_MAKETYPE(CV_8U, photometric > 1 ? 3 : 1);
152 m_type = CV_MAKETYPE(CV_16U, photometric > 1 ? 3 : 1);
156 m_type = CV_MAKETYPE(CV_32F, photometric > 1 ? 3 : 1);
159 m_type = CV_MAKETYPE(CV_64F, photometric > 1 ? 3 : 1);
176 bool TiffDecoder::readData( Mat& img )
179 bool color = img.channels() > 1;
180 uchar* data = img.data;
182 if( img.depth() != CV_8U && img.depth() != CV_16U && img.depth() != CV_32F && img.depth() != CV_64F )
185 if( m_tif && m_width && m_height )
187 TIFF* tif = (TIFF*)m_tif;
188 uint32 tile_width0 = m_width, tile_height0 = 0;
190 int is_tiled = TIFFIsTiled(tif);
192 TIFFGetField( tif, TIFFTAG_PHOTOMETRIC, &photometric );
193 uint16 bpp = 8, ncn = photometric > 1 ? 3 : 1;
194 TIFFGetField( tif, TIFFTAG_BITSPERSAMPLE, &bpp );
195 TIFFGetField( tif, TIFFTAG_SAMPLESPERPIXEL, &ncn );
196 const int bitsPerByte = 8;
197 int dst_bpp = (int)(img.elemSize1() * bitsPerByte);
202 if(!TIFFRGBAImageOK( tif, errmsg ))
211 TIFFGetField( tif, TIFFTAG_TILEWIDTH, &tile_width0 ) &&
212 TIFFGetField( tif, TIFFTAG_TILELENGTH, &tile_height0 )))
215 TIFFGetField( tif, TIFFTAG_ROWSPERSTRIP, &tile_height0 );
217 if( tile_width0 <= 0 )
218 tile_width0 = m_width;
220 if( tile_height0 <= 0 ||
221 (!is_tiled && tile_height0 == std::numeric_limits<uint32>::max()) )
222 tile_height0 = m_height;
225 // we will use TIFFReadRGBA* functions, so allocate temporary buffer for 32bit RGBA
229 const size_t buffer_size = (bpp/bitsPerByte) * ncn * tile_height0 * tile_width0;
230 AutoBuffer<uchar> _buffer( buffer_size );
231 uchar* buffer = _buffer;
232 ushort* buffer16 = (ushort*)buffer;
233 float* buffer32 = (float*)buffer;
234 double* buffer64 = (double*)buffer;
237 for( y = 0; y < m_height; y += tile_height0, data += img.step*tile_height0 )
239 int tile_height = tile_height0;
241 if( y + tile_height > m_height )
242 tile_height = m_height - y;
244 for( x = 0; x < m_width; x += tile_width0, tileidx++ )
246 int tile_width = tile_width0, ok;
248 if( x + tile_width > m_width )
249 tile_width = m_width - x;
255 uchar * bstart = buffer;
257 ok = TIFFReadRGBAStrip( tif, y, (uint32*)buffer );
260 ok = TIFFReadRGBATile( tif, x, y, (uint32*)buffer );
261 //Tiles fill the buffer from the bottom up
262 bstart += (tile_height0 - tile_height) * tile_width0 * 4;
270 for( i = 0; i < tile_height; i++ )
272 icvCvt_BGRA2BGR_8u_C4C3R( bstart + i*tile_width0*4, 0,
273 data + x*3 + img.step*(tile_height - i - 1), 0,
274 cvSize(tile_width,1), 2 );
276 icvCvt_BGRA2Gray_8u_C4C1R( bstart + i*tile_width0*4, 0,
277 data + x + img.step*(tile_height - i - 1), 0,
278 cvSize(tile_width,1), 2 );
285 ok = (int)TIFFReadEncodedStrip( tif, tileidx, (uint32*)buffer, buffer_size ) >= 0;
287 ok = (int)TIFFReadEncodedTile( tif, tileidx, (uint32*)buffer, buffer_size ) >= 0;
295 for( i = 0; i < tile_height; i++ )
301 icvCvt_Gray2BGR_16u_C1C3R(buffer16 + i*tile_width0*ncn, 0,
302 (ushort*)(data + img.step*i) + x*3, 0,
303 cvSize(tile_width,1) );
307 icvCvt_RGB2BGR_16u_C3R(buffer16 + i*tile_width0*ncn, 0,
308 (ushort*)(data + img.step*i) + x*3, 0,
309 cvSize(tile_width,1) );
313 icvCvt_BGRA2BGR_16u_C4C3R(buffer16 + i*tile_width0*ncn, 0,
314 (ushort*)(data + img.step*i) + x*3, 0,
315 cvSize(tile_width,1), 2 );
322 memcpy((ushort*)(data + img.step*i)+x,
323 buffer16 + i*tile_width0*ncn,
324 tile_width*sizeof(buffer16[0]));
328 icvCvt_BGRA2Gray_16u_CnC1R(buffer16 + i*tile_width0*ncn, 0,
329 (ushort*)(data + img.step*i) + x, 0,
330 cvSize(tile_width,1), ncn, 2 );
341 ok = (int)TIFFReadEncodedStrip( tif, tileidx, buffer, buffer_size ) >= 0;
343 ok = (int)TIFFReadEncodedTile( tif, tileidx, buffer, buffer_size ) >= 0;
345 if( !ok || ncn != 1 )
351 for( i = 0; i < tile_height; i++ )
355 memcpy((float*)(data + img.step*i)+x,
356 buffer32 + i*tile_width0*ncn,
357 tile_width*sizeof(buffer32[0]));
361 memcpy((double*)(data + img.step*i)+x,
362 buffer64 + i*tile_width0*ncn,
363 tile_width*sizeof(buffer64[0]));
388 //////////////////////////////////////////////////////////////////////////////////////////
390 TiffEncoder::TiffEncoder()
392 m_description = "TIFF Files (*.tiff;*.tif)";
394 m_buf_supported = false;
396 m_buf_supported = true;
400 TiffEncoder::~TiffEncoder()
404 ImageEncoder TiffEncoder::newEncoder() const
406 return new TiffEncoder;
409 bool TiffEncoder::isFormatSupported( int depth ) const
411 return depth == CV_8U || depth == CV_16U;
414 void TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag,
415 TiffFieldType fieldType,
416 int count, int value )
419 strm.putWord( fieldType );
420 strm.putDWord( count );
421 strm.putDWord( value );
426 static void readParam(const vector<int>& params, int key, int& value)
428 for(size_t i = 0; i + 1 < params.size(); i += 2)
436 bool TiffEncoder::writeLibTiff( const Mat& img, const vector<int>& params)
438 int channels = img.channels();
439 int width = img.cols, height = img.rows;
440 int depth = img.depth();
442 int bitsPerChannel = -1;
461 const int bitsPerByte = 8;
462 size_t fileStep = (width * channels * bitsPerChannel) / bitsPerByte;
464 int rowsPerStrip = (int)((1 << 13)/fileStep);
465 readParam(params, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
467 if( rowsPerStrip < 1 )
470 if( rowsPerStrip > height )
471 rowsPerStrip = height;
474 // do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode.
475 // http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
476 TIFF* pTiffHandle = TIFFOpen(m_filename.c_str(), "w");
482 // defaults for now, maybe base them on params in the future
483 int compression = COMPRESSION_LZW;
484 int predictor = PREDICTOR_HORIZONTAL;
486 readParam(params, TIFFTAG_COMPRESSION, compression);
487 readParam(params, TIFFTAG_PREDICTOR, predictor);
489 int colorspace = channels > 1 ? PHOTOMETRIC_RGB : PHOTOMETRIC_MINISBLACK;
491 if ( !TIFFSetField(pTiffHandle, TIFFTAG_IMAGEWIDTH, width)
492 || !TIFFSetField(pTiffHandle, TIFFTAG_IMAGELENGTH, height)
493 || !TIFFSetField(pTiffHandle, TIFFTAG_BITSPERSAMPLE, bitsPerChannel)
494 || !TIFFSetField(pTiffHandle, TIFFTAG_COMPRESSION, compression)
495 || !TIFFSetField(pTiffHandle, TIFFTAG_PHOTOMETRIC, colorspace)
496 || !TIFFSetField(pTiffHandle, TIFFTAG_SAMPLESPERPIXEL, channels)
497 || !TIFFSetField(pTiffHandle, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
498 || !TIFFSetField(pTiffHandle, TIFFTAG_ROWSPERSTRIP, rowsPerStrip)
501 TIFFClose(pTiffHandle);
505 if (compression != COMPRESSION_NONE && !TIFFSetField(pTiffHandle, TIFFTAG_PREDICTOR, predictor) )
507 TIFFClose(pTiffHandle);
511 // row buffer, because TIFFWriteScanline modifies the original data!
512 size_t scanlineSize = TIFFScanlineSize(pTiffHandle);
513 AutoBuffer<uchar> _buffer(scanlineSize+32);
514 uchar* buffer = _buffer;
517 TIFFClose(pTiffHandle);
521 for (int y = 0; y < height; ++y)
527 memcpy(buffer, img.data + img.step * y, scanlineSize);
534 icvCvt_BGR2RGB_8u_C3R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
536 icvCvt_BGR2RGB_16u_C3R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
543 icvCvt_BGRA2RGBA_8u_C4R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
545 icvCvt_BGRA2RGBA_16u_C4R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
551 TIFFClose(pTiffHandle);
556 int writeResult = TIFFWriteScanline(pTiffHandle, buffer, y, 0);
557 if (writeResult != 1)
559 TIFFClose(pTiffHandle);
564 TIFFClose(pTiffHandle);
571 bool TiffEncoder::write( const Mat& img, const vector<int>& params)
573 bool TiffEncoder::write( const Mat& img, const vector<int>& /*params*/)
576 int channels = img.channels();
577 int width = img.cols, height = img.rows;
578 int depth = img.depth();
580 if (depth != CV_8U && depth != CV_16U)
583 int bytesPerChannel = depth == CV_8U ? 1 : 2;
584 int fileStep = width * channels * bytesPerChannel;
590 if( !strm.open(*m_buf) )
596 return writeLibTiff(img, params);
598 if( !strm.open(m_filename) )
603 int rowsPerStrip = (1 << 13)/fileStep;
605 if( rowsPerStrip < 1 )
608 if( rowsPerStrip > height )
609 rowsPerStrip = height;
611 int i, stripCount = (height + rowsPerStrip - 1) / rowsPerStrip;
614 m_buf->reserve( alignSize(stripCount*8 + fileStep*height + 256, 256) );
616 /*#if defined _DEBUG || !defined WIN32
617 int uncompressedRowSize = rowsPerStrip * fileStep;
619 int directoryOffset = 0;
621 AutoBuffer<int> stripOffsets(stripCount);
622 AutoBuffer<short> stripCounts(stripCount);
623 AutoBuffer<uchar> _buffer(fileStep+32);
624 uchar* buffer = _buffer;
625 int stripOffsetsOffset = 0;
626 int stripCountsOffset = 0;
627 int bitsPerSample = 8 * bytesPerChannel;
630 strm.putBytes( fmtSignTiffII, 4 );
631 strm.putDWord( directoryOffset );
633 // write an image data first (the most reasonable way
634 // for compressed images)
635 for( i = 0; i < stripCount; i++ )
637 int limit = y + rowsPerStrip;
642 stripOffsets[i] = strm.getPos();
644 for( ; y < limit; y++ )
649 icvCvt_BGR2RGB_8u_C3R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
651 icvCvt_BGR2RGB_16u_C3R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
658 icvCvt_BGRA2RGBA_8u_C4R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) );
660 icvCvt_BGRA2RGBA_16u_C4R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) );
664 strm.putBytes( channels > 1 ? buffer : img.data + img.step*y, fileStep );
667 stripCounts[i] = (short)(strm.getPos() - stripOffsets[i]);
668 /*assert( stripCounts[i] == uncompressedRowSize ||
669 stripCounts[i] < uncompressedRowSize &&
670 i == stripCount - 1);*/
675 stripOffsetsOffset = strm.getPos();
676 for( i = 0; i < stripCount; i++ )
677 strm.putDWord( stripOffsets[i] );
679 stripCountsOffset = strm.getPos();
680 for( i = 0; i < stripCount; i++ )
681 strm.putWord( stripCounts[i] );
683 else if(stripCount == 2)
685 stripOffsetsOffset = strm.getPos();
686 for (i = 0; i < stripCount; i++)
688 strm.putDWord (stripOffsets [i]);
690 stripCountsOffset = stripCounts [0] + (stripCounts [1] << 16);
694 stripOffsetsOffset = stripOffsets[0];
695 stripCountsOffset = stripCounts[0];
700 int bitsPerSamplePos = strm.getPos();
701 strm.putWord(bitsPerSample);
702 strm.putWord(bitsPerSample);
703 strm.putWord(bitsPerSample);
705 strm.putWord(bitsPerSample);
706 bitsPerSample = bitsPerSamplePos;
709 directoryOffset = strm.getPos();
714 /* warning: specification 5.0 of Tiff want to have tags in
715 ascending order. This is a non-fatal error, but this cause
716 warning with some tools. So, keep this in ascending order */
718 writeTag( strm, TIFF_TAG_WIDTH, TIFF_TYPE_LONG, 1, width );
719 writeTag( strm, TIFF_TAG_HEIGHT, TIFF_TYPE_LONG, 1, height );
720 writeTag( strm, TIFF_TAG_BITS_PER_SAMPLE,
721 TIFF_TYPE_SHORT, channels, bitsPerSample );
722 writeTag( strm, TIFF_TAG_COMPRESSION, TIFF_TYPE_LONG, 1, TIFF_UNCOMP );
723 writeTag( strm, TIFF_TAG_PHOTOMETRIC, TIFF_TYPE_SHORT, 1, channels > 1 ? 2 : 1 );
725 writeTag( strm, TIFF_TAG_STRIP_OFFSETS, TIFF_TYPE_LONG,
726 stripCount, stripOffsetsOffset );
728 writeTag( strm, TIFF_TAG_SAMPLES_PER_PIXEL, TIFF_TYPE_SHORT, 1, channels );
729 writeTag( strm, TIFF_TAG_ROWS_PER_STRIP, TIFF_TYPE_LONG, 1, rowsPerStrip );
731 writeTag( strm, TIFF_TAG_STRIP_COUNTS,
732 stripCount > 1 ? TIFF_TYPE_SHORT : TIFF_TYPE_LONG,
733 stripCount, stripCountsOffset );
740 (*m_buf)[4] = (uchar)directoryOffset;
741 (*m_buf)[5] = (uchar)(directoryOffset >> 8);
742 (*m_buf)[6] = (uchar)(directoryOffset >> 16);
743 (*m_buf)[7] = (uchar)(directoryOffset >> 24);
747 // write directory offset
748 FILE* f = fopen( m_filename.c_str(), "r+b" );
749 buffer[0] = (uchar)directoryOffset;
750 buffer[1] = (uchar)(directoryOffset >> 8);
751 buffer[2] = (uchar)(directoryOffset >> 16);
752 buffer[3] = (uchar)(directoryOffset >> 24);
754 fseek( f, 4, SEEK_SET );
755 fwrite( buffer, 1, 4, f );