void TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag, TiffFieldType fieldType, int count, int value ) { strm.putWord( tag ); strm.putWord( fieldType ); strm.putDWord( count ); strm.putDWord( value ); }
bool TiffEncoder::write( const Mat& img, const vector<int>& /*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; int bytesPerChannel = depth == CV_8U ? 1 : 2; int fileStep = width * channels * bytesPerChannel; WLByteStream strm; if( m_buf ) { if( !strm.open(*m_buf) ) return false; } else { #ifdef HAVE_TIFF return writeLibTiff(img, params); #else if( !strm.open(m_filename) ) return false; #endif } int rowsPerStrip = (1 << 13)/fileStep; if( rowsPerStrip < 1 ) rowsPerStrip = 1; if( rowsPerStrip > height ) rowsPerStrip = height; int i, stripCount = (height + rowsPerStrip - 1) / rowsPerStrip; if( m_buf ) m_buf->reserve( alignSize(stripCount*8 + fileStep*height + 256, 256) ); /*#if defined _DEBUG || !defined WIN32 int uncompressedRowSize = rowsPerStrip * fileStep; #endif*/ int directoryOffset = 0; AutoBuffer<int> stripOffsets(stripCount); AutoBuffer<short> stripCounts(stripCount); AutoBuffer<uchar> _buffer(fileStep+32); uchar* buffer = _buffer; int stripOffsetsOffset = 0; int stripCountsOffset = 0; int bitsPerSample = 8 * bytesPerChannel; int y = 0; strm.putBytes( fmtSignTiffII, 4 ); strm.putDWord( directoryOffset ); // write an image data first (the most reasonable way // for compressed images) for( i = 0; i < stripCount; i++ ) { int limit = y + rowsPerStrip; if( limit > height ) limit = height; stripOffsets[i] = strm.getPos(); for( ; y < limit; y++ ) { if( channels == 3 ) { if (depth == CV_8U) icvCvt_BGR2RGB_8u_C3R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) ); else icvCvt_BGR2RGB_16u_C3R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) ); } else { if( channels == 4 ) { if (depth == CV_8U) icvCvt_BGRA2RGBA_8u_C4R( img.data + img.step*y, 0, buffer, 0, cvSize(width,1) ); else icvCvt_BGRA2RGBA_16u_C4R( (const ushort*)(img.data + img.step*y), 0, (ushort*)buffer, 0, cvSize(width,1) ); } } strm.putBytes( channels > 1 ? buffer : img.data + img.step*y, fileStep ); } stripCounts[i] = (short)(strm.getPos() - stripOffsets[i]); /*assert( stripCounts[i] == uncompressedRowSize || stripCounts[i] < uncompressedRowSize && i == stripCount - 1);*/ } if( stripCount > 2 ) { stripOffsetsOffset = strm.getPos(); for( i = 0; i < stripCount; i++ ) strm.putDWord( stripOffsets[i] ); stripCountsOffset = strm.getPos(); for( i = 0; i < stripCount; i++ ) strm.putWord( stripCounts[i] ); } else if(stripCount == 2) { stripOffsetsOffset = strm.getPos(); for (i = 0; i < stripCount; i++) { strm.putDWord (stripOffsets [i]); } stripCountsOffset = stripCounts [0] + (stripCounts [1] << 16); } else { stripOffsetsOffset = stripOffsets[0]; stripCountsOffset = stripCounts[0]; } if( channels > 1 ) { int bitsPerSamplePos = strm.getPos(); strm.putWord(bitsPerSample); strm.putWord(bitsPerSample); strm.putWord(bitsPerSample); if( channels == 4 ) strm.putWord(bitsPerSample); bitsPerSample = bitsPerSamplePos; } directoryOffset = strm.getPos(); // write header strm.putWord( 9 ); /* warning: specification 5.0 of Tiff want to have tags in ascending order. This is a non-fatal error, but this cause warning with some tools. So, keep this in ascending order */ writeTag( strm, TIFF_TAG_WIDTH, TIFF_TYPE_LONG, 1, width ); writeTag( strm, TIFF_TAG_HEIGHT, TIFF_TYPE_LONG, 1, height ); writeTag( strm, TIFF_TAG_BITS_PER_SAMPLE, TIFF_TYPE_SHORT, channels, bitsPerSample ); writeTag( strm, TIFF_TAG_COMPRESSION, TIFF_TYPE_LONG, 1, TIFF_UNCOMP ); writeTag( strm, TIFF_TAG_PHOTOMETRIC, TIFF_TYPE_SHORT, 1, channels > 1 ? 2 : 1 ); writeTag( strm, TIFF_TAG_STRIP_OFFSETS, TIFF_TYPE_LONG, stripCount, stripOffsetsOffset ); writeTag( strm, TIFF_TAG_SAMPLES_PER_PIXEL, TIFF_TYPE_SHORT, 1, channels ); writeTag( strm, TIFF_TAG_ROWS_PER_STRIP, TIFF_TYPE_LONG, 1, rowsPerStrip ); writeTag( strm, TIFF_TAG_STRIP_COUNTS, stripCount > 1 ? TIFF_TYPE_SHORT : TIFF_TYPE_LONG, stripCount, stripCountsOffset ); strm.putDWord(0); strm.close(); if( m_buf ) { (*m_buf)[4] = (uchar)directoryOffset; (*m_buf)[5] = (uchar)(directoryOffset >> 8); (*m_buf)[6] = (uchar)(directoryOffset >> 16); (*m_buf)[7] = (uchar)(directoryOffset >> 24); } else {