|
|
@ -75,6 +75,8 @@ TiffDecoder::TiffDecoder() |
|
|
|
TIFFSetWarningHandler( GrFmtSilentTIFFErrorHandler ); |
|
|
|
TIFFSetWarningHandler( GrFmtSilentTIFFErrorHandler ); |
|
|
|
} |
|
|
|
} |
|
|
|
m_hdr = false; |
|
|
|
m_hdr = false; |
|
|
|
|
|
|
|
m_buf_supported = true; |
|
|
|
|
|
|
|
m_buf_pos = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -115,6 +117,76 @@ ImageDecoder TiffDecoder::newDecoder() const |
|
|
|
return makePtr<TiffDecoder>(); |
|
|
|
return makePtr<TiffDecoder>(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TiffDecoderBufHelper |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
static tmsize_t read( thandle_t handle, void* buffer, tmsize_t n ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TiffDecoder *decoder = reinterpret_cast<TiffDecoder*>(handle); |
|
|
|
|
|
|
|
const Mat& buf = decoder->m_buf; |
|
|
|
|
|
|
|
const tmsize_t size = buf.cols*buf.rows*buf.elemSize(); |
|
|
|
|
|
|
|
tmsize_t pos = decoder->m_buf_pos; |
|
|
|
|
|
|
|
if ( n > (size - pos) ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
n = size - pos; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
memcpy(buffer, buf.ptr() + pos, n); |
|
|
|
|
|
|
|
decoder->m_buf_pos += n; |
|
|
|
|
|
|
|
return n; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static tmsize_t write( thandle_t /*handle*/, void* /*buffer*/, tmsize_t /*n*/ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Not used for decoding.
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static toff_t seek( thandle_t handle, toff_t offset, int whence ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TiffDecoder *decoder = reinterpret_cast<TiffDecoder*>(handle); |
|
|
|
|
|
|
|
const Mat& buf = decoder->m_buf; |
|
|
|
|
|
|
|
const toff_t size = buf.cols*buf.rows*buf.elemSize(); |
|
|
|
|
|
|
|
toff_t new_pos = decoder->m_buf_pos; |
|
|
|
|
|
|
|
switch (whence) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case SEEK_SET: |
|
|
|
|
|
|
|
new_pos = offset; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case SEEK_CUR: |
|
|
|
|
|
|
|
new_pos += offset; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case SEEK_END: |
|
|
|
|
|
|
|
new_pos = size + offset; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
new_pos = std::min(new_pos, size); |
|
|
|
|
|
|
|
decoder->m_buf_pos = (size_t)new_pos; |
|
|
|
|
|
|
|
return new_pos; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int map( thandle_t handle, void** base, toff_t* size ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TiffDecoder *decoder = reinterpret_cast<TiffDecoder*>(handle); |
|
|
|
|
|
|
|
Mat& buf = decoder->m_buf; |
|
|
|
|
|
|
|
*base = buf.ptr(); |
|
|
|
|
|
|
|
*size = buf.cols*buf.rows*buf.elemSize(); |
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static toff_t size( thandle_t handle ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TiffDecoder *decoder = reinterpret_cast<TiffDecoder*>(handle); |
|
|
|
|
|
|
|
const Mat& buf = decoder->m_buf; |
|
|
|
|
|
|
|
return buf.cols*buf.rows*buf.elemSize(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int close( thandle_t /*handle*/ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Do nothing.
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
bool TiffDecoder::readHeader() |
|
|
|
bool TiffDecoder::readHeader() |
|
|
|
{ |
|
|
|
{ |
|
|
|
bool result = false; |
|
|
|
bool result = false; |
|
|
@ -124,8 +196,19 @@ bool TiffDecoder::readHeader() |
|
|
|
{ |
|
|
|
{ |
|
|
|
// TIFFOpen() mode flags are different to fopen(). A 'b' in mode "rb" has no effect when reading.
|
|
|
|
// TIFFOpen() mode flags are different to fopen(). A 'b' in mode "rb" has no effect when reading.
|
|
|
|
// http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
|
|
|
|
// http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
|
|
|
|
|
|
|
|
if ( !m_buf.empty() ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
m_buf_pos = 0; |
|
|
|
|
|
|
|
tif = TIFFClientOpen( "", "r", reinterpret_cast<thandle_t>(this), &TiffDecoderBufHelper::read, |
|
|
|
|
|
|
|
&TiffDecoderBufHelper::write, &TiffDecoderBufHelper::seek, |
|
|
|
|
|
|
|
&TiffDecoderBufHelper::close, &TiffDecoderBufHelper::size, |
|
|
|
|
|
|
|
&TiffDecoderBufHelper::map, /*unmap=*/0 ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
tif = TIFFOpen(m_filename.c_str(), "r"); |
|
|
|
tif = TIFFOpen(m_filename.c_str(), "r"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if( tif ) |
|
|
|
if( tif ) |
|
|
|
{ |
|
|
|
{ |
|
|
@ -472,11 +555,7 @@ bool TiffDecoder::readHdrData(Mat& img) |
|
|
|
TiffEncoder::TiffEncoder() |
|
|
|
TiffEncoder::TiffEncoder() |
|
|
|
{ |
|
|
|
{ |
|
|
|
m_description = "TIFF Files (*.tiff;*.tif)"; |
|
|
|
m_description = "TIFF Files (*.tiff;*.tif)"; |
|
|
|
#ifdef HAVE_TIFF |
|
|
|
|
|
|
|
m_buf_supported = false; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
m_buf_supported = true; |
|
|
|
m_buf_supported = true; |
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
TiffEncoder::~TiffEncoder() |
|
|
|
TiffEncoder::~TiffEncoder() |
|
|
@ -509,6 +588,81 @@ void TiffEncoder::writeTag( WLByteStream& strm, TiffTag tag, |
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_TIFF |
|
|
|
#ifdef HAVE_TIFF |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class TiffEncoderBufHelper |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TiffEncoderBufHelper(std::vector<uchar> *buf) |
|
|
|
|
|
|
|
: m_buf(buf), m_buf_pos(0) |
|
|
|
|
|
|
|
{} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TIFF* open () |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
return TIFFClientOpen( "", "w", reinterpret_cast<thandle_t>(this), &TiffEncoderBufHelper::read, |
|
|
|
|
|
|
|
&TiffEncoderBufHelper::write, &TiffEncoderBufHelper::seek, |
|
|
|
|
|
|
|
&TiffEncoderBufHelper::close, &TiffEncoderBufHelper::size, |
|
|
|
|
|
|
|
/*map=*/0, /*unmap=*/0 ); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static tmsize_t read( thandle_t /*handle*/, void* /*buffer*/, tmsize_t /*n*/ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Not used for encoding.
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static tmsize_t write( thandle_t handle, void* buffer, tmsize_t n ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TiffEncoderBufHelper *helper = reinterpret_cast<TiffEncoderBufHelper*>(handle); |
|
|
|
|
|
|
|
size_t begin = (size_t)helper->m_buf_pos; |
|
|
|
|
|
|
|
size_t end = begin + n; |
|
|
|
|
|
|
|
if ( helper->m_buf->size() < end ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
helper->m_buf->resize(end); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
memcpy(&(*helper->m_buf)[begin], buffer, n); |
|
|
|
|
|
|
|
helper->m_buf_pos = end; |
|
|
|
|
|
|
|
return n; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static toff_t seek( thandle_t handle, toff_t offset, int whence ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TiffEncoderBufHelper *helper = reinterpret_cast<TiffEncoderBufHelper*>(handle); |
|
|
|
|
|
|
|
const toff_t size = helper->m_buf->size(); |
|
|
|
|
|
|
|
toff_t new_pos = helper->m_buf_pos; |
|
|
|
|
|
|
|
switch (whence) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
case SEEK_SET: |
|
|
|
|
|
|
|
new_pos = offset; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case SEEK_CUR: |
|
|
|
|
|
|
|
new_pos += offset; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
case SEEK_END: |
|
|
|
|
|
|
|
new_pos = size + offset; |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
helper->m_buf_pos = new_pos; |
|
|
|
|
|
|
|
return new_pos; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static toff_t size( thandle_t handle ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
TiffEncoderBufHelper *helper = reinterpret_cast<TiffEncoderBufHelper*>(handle); |
|
|
|
|
|
|
|
return helper->m_buf->size(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int close( thandle_t /*handle*/ ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// Do nothing.
|
|
|
|
|
|
|
|
return 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
std::vector<uchar>* m_buf; |
|
|
|
|
|
|
|
toff_t m_buf_pos; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
static void readParam(const std::vector<int>& params, int key, int& value) |
|
|
|
static void readParam(const std::vector<int>& params, int key, int& value) |
|
|
|
{ |
|
|
|
{ |
|
|
|
for(size_t i = 0; i + 1 < params.size(); i += 2) |
|
|
|
for(size_t i = 0; i + 1 < params.size(); i += 2) |
|
|
@ -559,7 +713,17 @@ bool TiffEncoder::writeLibTiff( const Mat& img, const std::vector<int>& params) |
|
|
|
|
|
|
|
|
|
|
|
// do NOT put "wb" as the mode, because the b means "big endian" mode, not "binary" mode.
|
|
|
|
// 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
|
|
|
|
// http://www.remotesensing.org/libtiff/man/TIFFOpen.3tiff.html
|
|
|
|
TIFF* pTiffHandle = TIFFOpen(m_filename.c_str(), "w"); |
|
|
|
TIFF* pTiffHandle; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TiffEncoderBufHelper buf_helper(m_buf); |
|
|
|
|
|
|
|
if ( m_buf ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pTiffHandle = buf_helper.open(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
pTiffHandle = TIFFOpen(m_filename.c_str(), "w"); |
|
|
|
|
|
|
|
} |
|
|
|
if (!pTiffHandle) |
|
|
|
if (!pTiffHandle) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return false; |
|
|
|
return false; |
|
|
@ -655,7 +819,19 @@ bool TiffEncoder::writeHdr(const Mat& _img) |
|
|
|
{ |
|
|
|
{ |
|
|
|
Mat img; |
|
|
|
Mat img; |
|
|
|
cvtColor(_img, img, COLOR_BGR2XYZ); |
|
|
|
cvtColor(_img, img, COLOR_BGR2XYZ); |
|
|
|
TIFF* tif = TIFFOpen(m_filename.c_str(), "w"); |
|
|
|
|
|
|
|
|
|
|
|
TIFF* tif; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TiffEncoderBufHelper buf_helper(m_buf); |
|
|
|
|
|
|
|
if ( m_buf ) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
tif = buf_helper.open(); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
tif = TIFFOpen(m_filename.c_str(), "w"); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!tif) |
|
|
|
if (!tif) |
|
|
|
{ |
|
|
|
{ |
|
|
|
return false; |
|
|
|
return false; |
|
|
@ -686,8 +862,6 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& params) |
|
|
|
bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/) |
|
|
|
bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/) |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
{ |
|
|
|
{ |
|
|
|
int channels = img.channels(); |
|
|
|
|
|
|
|
int width = img.cols, height = img.rows; |
|
|
|
|
|
|
|
int depth = img.depth(); |
|
|
|
int depth = img.depth(); |
|
|
|
#ifdef HAVE_TIFF |
|
|
|
#ifdef HAVE_TIFF |
|
|
|
if(img.type() == CV_32FC3) |
|
|
|
if(img.type() == CV_32FC3) |
|
|
@ -699,6 +873,11 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/) |
|
|
|
if (depth != CV_8U && depth != CV_16U) |
|
|
|
if (depth != CV_8U && depth != CV_16U) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_TIFF |
|
|
|
|
|
|
|
return writeLibTiff(img, params); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
int channels = img.channels(); |
|
|
|
|
|
|
|
int width = img.cols, height = img.rows; |
|
|
|
int bytesPerChannel = depth == CV_8U ? 1 : 2; |
|
|
|
int bytesPerChannel = depth == CV_8U ? 1 : 2; |
|
|
|
int fileStep = width * channels * bytesPerChannel; |
|
|
|
int fileStep = width * channels * bytesPerChannel; |
|
|
|
|
|
|
|
|
|
|
@ -711,12 +890,8 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/) |
|
|
|
} |
|
|
|
} |
|
|
|
else |
|
|
|
else |
|
|
|
{ |
|
|
|
{ |
|
|
|
#ifdef HAVE_TIFF |
|
|
|
|
|
|
|
return writeLibTiff(img, params); |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
if( !strm.open(m_filename) ) |
|
|
|
if( !strm.open(m_filename) ) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
#endif |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int rowsPerStrip = (1 << 13)/fileStep; |
|
|
|
int rowsPerStrip = (1 << 13)/fileStep; |
|
|
@ -876,6 +1051,7 @@ bool TiffEncoder::write( const Mat& img, const std::vector<int>& /*params*/) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
|
|
|
|
#endif |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|