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 {
bool PxMEncoder::write( const Mat& img, const std::vector<int>& params ) { bool isBinary = true; int width = img.cols, height = img.rows; int _channels = img.channels(), depth = (int)img.elemSize1()*8; int channels = _channels > 1 ? 3 : 1; int fileStep = width*(int)img.elemSize(); int x, y; for( size_t i = 0; i < params.size(); i += 2 ) if( params[i] == CV_IMWRITE_PXM_BINARY ) isBinary = params[i+1] != 0; WLByteStream strm; if( m_buf ) { if( !strm.open(*m_buf) ) return false; int t = CV_MAKETYPE(img.depth(), channels); m_buf->reserve( alignSize(256 + (isBinary ? fileStep*height : ((t == CV_8UC1 ? 4 : t == CV_8UC3 ? 4*3+2 : t == CV_16UC1 ? 6 : 6*3+2)*width+1)*height), 256)); } else if( !strm.open(m_filename) ) return false; int lineLength; int bufferSize = 128; // buffer that should fit a header if( isBinary ) lineLength = width * (int)img.elemSize(); else lineLength = (6 * channels + (channels > 1 ? 2 : 0)) * width + 32; if( bufferSize < lineLength ) bufferSize = lineLength; AutoBuffer<char> _buffer(bufferSize); char* buffer = _buffer; // write header; sprintf( buffer, "P%c\n%d %d\n%d\n", '2' + (channels > 1 ? 1 : 0) + (isBinary ? 3 : 0), width, height, (1 << depth) - 1 ); strm.putBytes( buffer, (int)strlen(buffer) ); for( y = 0; y < height; y++ ) { uchar* data = img.data + img.step*y; if( isBinary ) { if( _channels == 3 ) { if( depth == 8 ) icvCvt_BGR2RGB_8u_C3R( (uchar*)data, 0, (uchar*)buffer, 0, cvSize(width,1) ); else icvCvt_BGR2RGB_16u_C3R( (ushort*)data, 0, (ushort*)buffer, 0, cvSize(width,1) ); } // swap endianness if necessary if( depth == 16 && !isBigEndian() ) { if( _channels == 1 ) memcpy( buffer, data, fileStep ); for( x = 0; x < width*channels*2; x += 2 ) { uchar v = buffer[x]; buffer[x] = buffer[x + 1]; buffer[x + 1] = v; } } strm.putBytes( (channels > 1 || depth > 8) ? buffer : (char*)data, fileStep ); } else { char* ptr = buffer; if( channels > 1 ) { if( depth == 8 ) { for( x = 0; x < width*channels; x += channels ) { sprintf( ptr, "% 4d", data[x + 2] ); ptr += 4; sprintf( ptr, "% 4d", data[x + 1] ); ptr += 4; sprintf( ptr, "% 4d", data[x] ); ptr += 4; *ptr++ = ' '; *ptr++ = ' '; } } else { for( x = 0; x < width*channels; x += channels ) { sprintf( ptr, "% 6d", ((ushort *)data)[x + 2] ); ptr += 6; sprintf( ptr, "% 6d", ((ushort *)data)[x + 1] ); ptr += 6; sprintf( ptr, "% 6d", ((ushort *)data)[x] ); ptr += 6; *ptr++ = ' '; *ptr++ = ' '; } } } else { if( depth == 8 ) { for( x = 0; x < width; x++ ) { sprintf( ptr, "% 4d", data[x] ); ptr += 4; } } else { for( x = 0; x < width; x++ ) { sprintf( ptr, "% 6d", ((ushort *)data)[x] ); ptr += 6; } } } *ptr++ = '\n'; strm.putBytes( buffer, (int)(ptr - buffer) ); } } strm.close(); return true; }
bool PAMEncoder::write( const Mat& img, const std::vector<int>& params ) { WLByteStream strm; int width = img.cols, height = img.rows; int stride = width*(int)img.elemSize(); const uchar* data = img.ptr(); const struct pam_format *fmt = NULL; int x, y, tmp, bufsize = 256; /* parse save file type */ for( size_t i = 0; i < params.size(); i += 2 ) if( params[i] == CV_IMWRITE_PAM_TUPLETYPE ) { if ( params[i+1] > CV_IMWRITE_PAM_FORMAT_NULL && params[i+1] < (int) PAM_FORMATS_NO) fmt = &formats[params[i+1]]; } if( m_buf ) { if( !strm.open(*m_buf) ) return false; m_buf->reserve( alignSize(256 + stride*height, 256)); } else if( !strm.open(m_filename) ) return false; tmp = width * (int)img.elemSize(); if (bufsize < tmp) bufsize = tmp; AutoBuffer<char> _buffer(bufsize); char* buffer = _buffer.data(); /* write header */ tmp = 0; tmp += sprintf( buffer, "P7\n"); tmp += sprintf( buffer + tmp, "WIDTH %d\n", width); tmp += sprintf( buffer + tmp, "HEIGHT %d\n", height); tmp += sprintf( buffer + tmp, "DEPTH %d\n", img.channels()); tmp += sprintf( buffer + tmp, "MAXVAL %d\n", (1 << img.elemSize1()*8) - 1); if (fmt) tmp += sprintf( buffer + tmp, "TUPLTYPE %s\n", fmt->name ); sprintf( buffer + tmp, "ENDHDR\n" ); strm.putBytes( buffer, (int)strlen(buffer) ); /* write data */ if (img.depth() == CV_8U) strm.putBytes( data, stride*height ); else if (img.depth() == CV_16U) { /* fix endianness */ if (!isBigEndian()) { for( y = 0; y < height; y++ ) { memcpy( buffer, img.ptr(y), stride ); for( x = 0; x < stride; x += 2 ) { uchar v = buffer[x]; buffer[x] = buffer[x + 1]; buffer[x + 1] = v; } strm.putBytes( buffer, stride ); } } else strm.putBytes( data, stride*height ); } else CV_Error(Error::StsInternal, ""); strm.close(); return true; }