mirror of
https://github.com/opencv/opencv.git
synced 2025-06-08 18:13:13 +08:00
Merge pull request #9252 from jbms:fix/tiff-in-memory
This commit is contained in:
commit
cc5da83474
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -91,6 +91,8 @@ enum TiffFieldType
|
|||||||
|
|
||||||
// libtiff based TIFF codec
|
// libtiff based TIFF codec
|
||||||
|
|
||||||
|
class TiffDecoderBufHelper;
|
||||||
|
|
||||||
class TiffDecoder : public BaseImageDecoder
|
class TiffDecoder : public BaseImageDecoder
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -107,10 +109,14 @@ public:
|
|||||||
ImageDecoder newDecoder() const;
|
ImageDecoder newDecoder() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
friend class TiffDecoderBufHelper;
|
||||||
|
|
||||||
void* m_tif;
|
void* m_tif;
|
||||||
int normalizeChannelsNumber(int channels) const;
|
int normalizeChannelsNumber(int channels) const;
|
||||||
bool readHdrData(Mat& img);
|
bool readHdrData(Mat& img);
|
||||||
bool m_hdr;
|
bool m_hdr;
|
||||||
|
size_t m_buf_pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user