mirror of
https://github.com/opencv/opencv.git
synced 2024-11-24 03:00:14 +08:00
Merge pull request #25975 from asmorkalov:as/bmp_error_check
Improved error handling in image codecs.
This commit is contained in:
commit
b9b2d551ac
@ -377,26 +377,30 @@ void WBaseStream::allocate()
|
||||
}
|
||||
|
||||
|
||||
void WBaseStream::writeBlock()
|
||||
bool WBaseStream::writeBlock()
|
||||
{
|
||||
int size = (int)(m_current - m_start);
|
||||
|
||||
CV_Assert(isOpened());
|
||||
if( size == 0 )
|
||||
return;
|
||||
return true;
|
||||
|
||||
if( m_buf )
|
||||
{
|
||||
size_t sz = m_buf->size();
|
||||
m_buf->resize( sz + size );
|
||||
memcpy( &(*m_buf)[sz], m_start, size );
|
||||
m_current = m_start;
|
||||
m_block_pos += size;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
fwrite( m_start, 1, size, m_file );
|
||||
size_t written = fwrite( m_start, 1, size, m_file );
|
||||
m_current = m_start;
|
||||
m_block_pos += size;
|
||||
return written == (size_t)size;
|
||||
}
|
||||
m_current = m_start;
|
||||
m_block_pos += size;
|
||||
}
|
||||
|
||||
|
||||
@ -463,15 +467,17 @@ WLByteStream::~WLByteStream()
|
||||
{
|
||||
}
|
||||
|
||||
void WLByteStream::putByte( int val )
|
||||
bool WLByteStream::putByte( int val )
|
||||
{
|
||||
*m_current++ = (uchar)val;
|
||||
if( m_current >= m_end )
|
||||
writeBlock();
|
||||
return writeBlock();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void WLByteStream::putBytes( const void* buffer, int count )
|
||||
bool WLByteStream::putBytes( const void* buffer, int count )
|
||||
{
|
||||
uchar* data = (uchar*)buffer;
|
||||
|
||||
@ -492,12 +498,18 @@ void WLByteStream::putBytes( const void* buffer, int count )
|
||||
count -= l;
|
||||
}
|
||||
if( m_current == m_end )
|
||||
writeBlock();
|
||||
{
|
||||
bool written = writeBlock();
|
||||
if (!written)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void WLByteStream::putWord( int val )
|
||||
bool WLByteStream::putWord( int val )
|
||||
{
|
||||
uchar *current = m_current;
|
||||
|
||||
@ -507,17 +519,19 @@ void WLByteStream::putWord( int val )
|
||||
current[1] = (uchar)(val >> 8);
|
||||
m_current = current + 2;
|
||||
if( m_current == m_end )
|
||||
writeBlock();
|
||||
return writeBlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
putByte(val);
|
||||
putByte(val >> 8);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void WLByteStream::putDWord( int val )
|
||||
bool WLByteStream::putDWord( int val )
|
||||
{
|
||||
uchar *current = m_current;
|
||||
|
||||
@ -529,7 +543,7 @@ void WLByteStream::putDWord( int val )
|
||||
current[3] = (uchar)(val >> 24);
|
||||
m_current = current + 4;
|
||||
if( m_current == m_end )
|
||||
writeBlock();
|
||||
return writeBlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -538,6 +552,8 @@ void WLByteStream::putDWord( int val )
|
||||
putByte(val >> 16);
|
||||
putByte(val >> 24);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -548,7 +564,7 @@ WMByteStream::~WMByteStream()
|
||||
}
|
||||
|
||||
|
||||
void WMByteStream::putWord( int val )
|
||||
bool WMByteStream::putWord( int val )
|
||||
{
|
||||
uchar *current = m_current;
|
||||
|
||||
@ -558,17 +574,19 @@ void WMByteStream::putWord( int val )
|
||||
current[1] = (uchar)val;
|
||||
m_current = current + 2;
|
||||
if( m_current == m_end )
|
||||
writeBlock();
|
||||
return writeBlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
putByte(val >> 8);
|
||||
putByte(val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void WMByteStream::putDWord( int val )
|
||||
bool WMByteStream::putDWord( int val )
|
||||
{
|
||||
uchar *current = m_current;
|
||||
|
||||
@ -580,7 +598,7 @@ void WMByteStream::putDWord( int val )
|
||||
current[3] = (uchar)val;
|
||||
m_current = current + 4;
|
||||
if( m_current == m_end )
|
||||
writeBlock();
|
||||
return writeBlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -589,6 +607,8 @@ void WMByteStream::putDWord( int val )
|
||||
putByte(val >> 8);
|
||||
putByte(val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -63,6 +63,12 @@ DECLARE_RBS_EXCEPTION(THROW_FORB)
|
||||
DECLARE_RBS_EXCEPTION(BAD_HEADER)
|
||||
#define RBS_BAD_HEADER RBS_BAD_HEADER_Exception(cv::Error::StsError, "Invalid header", CV_Func, __FILE__, __LINE__)
|
||||
|
||||
#define CHECK_WRITE(action) \
|
||||
if (!action) \
|
||||
{ \
|
||||
return false; \
|
||||
}
|
||||
|
||||
typedef unsigned long ulong;
|
||||
|
||||
// class RBaseStream - base class for other reading streams.
|
||||
@ -147,7 +153,7 @@ protected:
|
||||
bool m_is_opened;
|
||||
std::vector<uchar>* m_buf;
|
||||
|
||||
virtual void writeBlock();
|
||||
virtual bool writeBlock();
|
||||
virtual void release();
|
||||
virtual void allocate();
|
||||
};
|
||||
@ -160,10 +166,10 @@ class WLByteStream : public WBaseStream
|
||||
public:
|
||||
virtual ~WLByteStream();
|
||||
|
||||
void putByte( int val );
|
||||
void putBytes( const void* buffer, int count );
|
||||
void putWord( int val );
|
||||
void putDWord( int val );
|
||||
bool putByte( int val );
|
||||
bool putBytes( const void* buffer, int count );
|
||||
bool putWord( int val );
|
||||
bool putDWord( int val );
|
||||
};
|
||||
|
||||
|
||||
@ -173,8 +179,8 @@ class WMByteStream : public WLByteStream
|
||||
{
|
||||
public:
|
||||
virtual ~WMByteStream();
|
||||
void putWord( int val );
|
||||
void putDWord( int val );
|
||||
bool putWord( int val );
|
||||
bool putDWord( int val );
|
||||
};
|
||||
|
||||
inline unsigned BSWAP(unsigned v)
|
||||
|
@ -635,38 +635,40 @@ bool BmpEncoder::write( const Mat& img, const std::vector<int>& )
|
||||
m_buf->reserve( alignSize(fileSize + 16, 256) );
|
||||
|
||||
// write signature 'BM'
|
||||
strm.putBytes( fmtSignBmp, (int)strlen(fmtSignBmp) );
|
||||
CHECK_WRITE(strm.putBytes( fmtSignBmp, (int)strlen(fmtSignBmp) ));
|
||||
|
||||
// write file header
|
||||
strm.putDWord( validateToInt(fileSize) ); // file size
|
||||
strm.putDWord( 0 );
|
||||
strm.putDWord( headerSize );
|
||||
CHECK_WRITE(strm.putDWord( validateToInt(fileSize) )); // file size
|
||||
CHECK_WRITE(strm.putDWord( 0 ));
|
||||
CHECK_WRITE(strm.putDWord( headerSize ));
|
||||
|
||||
// write bitmap header
|
||||
strm.putDWord( bitmapHeaderSize );
|
||||
strm.putDWord( width );
|
||||
strm.putDWord( height );
|
||||
strm.putWord( 1 );
|
||||
strm.putWord( channels << 3 );
|
||||
strm.putDWord( BMP_RGB );
|
||||
strm.putDWord( 0 );
|
||||
strm.putDWord( 0 );
|
||||
strm.putDWord( 0 );
|
||||
strm.putDWord( 0 );
|
||||
strm.putDWord( 0 );
|
||||
CHECK_WRITE(strm.putDWord( bitmapHeaderSize ));
|
||||
CHECK_WRITE(strm.putDWord( width ));
|
||||
CHECK_WRITE(strm.putDWord( height ));
|
||||
CHECK_WRITE(strm.putWord( 1 ));
|
||||
CHECK_WRITE(strm.putWord( channels << 3 ));
|
||||
CHECK_WRITE(strm.putDWord( BMP_RGB ));
|
||||
CHECK_WRITE(strm.putDWord( 0 ));
|
||||
CHECK_WRITE(strm.putDWord( 0 ));
|
||||
CHECK_WRITE(strm.putDWord( 0 ));
|
||||
CHECK_WRITE(strm.putDWord( 0 ));
|
||||
CHECK_WRITE(strm.putDWord( 0 ));
|
||||
|
||||
if( channels == 1 )
|
||||
{
|
||||
FillGrayPalette( palette, 8 );
|
||||
strm.putBytes( palette, sizeof(palette));
|
||||
CHECK_WRITE(strm.putBytes( palette, sizeof(palette)));
|
||||
}
|
||||
|
||||
width *= channels;
|
||||
for( int y = height - 1; y >= 0; y-- )
|
||||
{
|
||||
strm.putBytes( img.ptr(y), width );
|
||||
CHECK_WRITE(strm.putBytes( img.ptr(y), width ));
|
||||
if( fileStep > width )
|
||||
strm.putBytes( zeropad, fileStep - width );
|
||||
{
|
||||
CHECK_WRITE(strm.putBytes( zeropad, fileStep - width ));
|
||||
}
|
||||
}
|
||||
|
||||
strm.close();
|
||||
|
@ -64,11 +64,11 @@ T read_number(cv::RLByteStream& strm)
|
||||
return atoT<T>(str);
|
||||
}
|
||||
|
||||
template<typename T> void write_anything(cv::WLByteStream& strm, const T& t)
|
||||
template<typename T> bool write_anything(cv::WLByteStream& strm, const T& t)
|
||||
{
|
||||
std::ostringstream ss;
|
||||
ss << t;
|
||||
strm.putBytes(ss.str().c_str(), static_cast<int>(ss.str().size()));
|
||||
return strm.putBytes(ss.str().c_str(), static_cast<int>(ss.str().size()));
|
||||
}
|
||||
|
||||
}
|
||||
@ -206,33 +206,33 @@ bool PFMEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
}
|
||||
|
||||
Mat float_img;
|
||||
strm.putByte('P');
|
||||
CHECK_WRITE(strm.putByte('P'));
|
||||
switch (img.channels()) {
|
||||
case 1:
|
||||
strm.putByte('f');
|
||||
CHECK_WRITE(strm.putByte('f'));
|
||||
img.convertTo(float_img, CV_32FC1);
|
||||
break;
|
||||
case 3:
|
||||
strm.putByte('F');
|
||||
CHECK_WRITE(strm.putByte('F'));
|
||||
img.convertTo(float_img, CV_32FC3);
|
||||
break;
|
||||
default:
|
||||
CV_Error(Error::StsBadArg, "Expected 1 or 3 channel image.");
|
||||
}
|
||||
strm.putByte('\n');
|
||||
CHECK_WRITE(strm.putByte('\n'));
|
||||
|
||||
|
||||
write_anything(strm, float_img.cols);
|
||||
strm.putByte(' ');
|
||||
write_anything(strm, float_img.rows);
|
||||
strm.putByte('\n');
|
||||
CHECK_WRITE(write_anything(strm, float_img.cols));
|
||||
CHECK_WRITE(strm.putByte(' '));
|
||||
CHECK_WRITE(write_anything(strm, float_img.rows));
|
||||
CHECK_WRITE(strm.putByte('\n'));
|
||||
#ifdef WORDS_BIGENDIAN
|
||||
write_anything(strm, 1.0);
|
||||
CHECK_WRITE(write_anything(strm, 1.0));
|
||||
#else
|
||||
write_anything(strm, -1.0);
|
||||
CHECK_WRITE(write_anything(strm, -1.0));
|
||||
#endif
|
||||
|
||||
strm.putByte('\n');
|
||||
CHECK_WRITE(strm.putByte('\n'));
|
||||
|
||||
// Comments are not officially supported in this file format.
|
||||
// write_anything(strm, "# Generated by OpenCV " CV_VERSION "\n");
|
||||
@ -248,17 +248,15 @@ bool PFMEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
rgb_row[x*3+1] = bgr_row[x*3+1];
|
||||
rgb_row[x*3+2] = bgr_row[x*3+0];
|
||||
}
|
||||
strm.putBytes( reinterpret_cast<const uchar*>(rgb_row.data()),
|
||||
static_cast<int>(sizeof(float) * row_size) );
|
||||
CHECK_WRITE(strm.putBytes( reinterpret_cast<const uchar*>(rgb_row.data()),
|
||||
static_cast<int>(sizeof(float) * row_size) ));
|
||||
} else if (float_img.channels() == 1) {
|
||||
strm.putBytes(float_img.ptr(y), sizeof(float) * float_img.cols);
|
||||
CHECK_WRITE(strm.putBytes(float_img.ptr(y), sizeof(float) * float_img.cols));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_IMGCODEC_PFM
|
||||
|
@ -479,7 +479,7 @@ bool PxMEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
header_sz += sz;
|
||||
}
|
||||
|
||||
strm.putBytes(buffer, header_sz);
|
||||
CHECK_WRITE(strm.putBytes(buffer, header_sz));
|
||||
|
||||
for( y = 0; y < height; y++ )
|
||||
{
|
||||
@ -512,7 +512,7 @@ bool PxMEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
{
|
||||
*ptr++ = byte;
|
||||
}
|
||||
strm.putBytes(buffer, (int)(ptr - buffer));
|
||||
CHECK_WRITE(strm.putBytes(buffer, (int)(ptr - buffer)));
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -539,7 +539,7 @@ bool PxMEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
}
|
||||
}
|
||||
|
||||
strm.putBytes( (channels > 1 || depth > 8) ? buffer : (const char*)data, fileStep);
|
||||
CHECK_WRITE(strm.putBytes( (channels > 1 || depth > 8) ? buffer : (const char*)data, fileStep));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -610,7 +610,7 @@ bool PxMEncoder::write(const Mat& img, const std::vector<int>& params)
|
||||
|
||||
*ptr++ = '\n';
|
||||
|
||||
strm.putBytes( buffer, (int)(ptr - buffer) );
|
||||
CHECK_WRITE(strm.putBytes( buffer, (int)(ptr - buffer) ));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -410,17 +410,17 @@ bool SunRasterEncoder::write( const Mat& img, const std::vector<int>& )
|
||||
|
||||
if( strm.open(m_filename) )
|
||||
{
|
||||
strm.putBytes( fmtSignSunRas, (int)strlen(fmtSignSunRas) );
|
||||
strm.putDWord( width );
|
||||
strm.putDWord( height );
|
||||
strm.putDWord( channels*8 );
|
||||
strm.putDWord( fileStep*height );
|
||||
strm.putDWord( RAS_STANDARD );
|
||||
strm.putDWord( RMT_NONE );
|
||||
strm.putDWord( 0 );
|
||||
CHECK_WRITE(strm.putBytes( fmtSignSunRas, (int)strlen(fmtSignSunRas) ));
|
||||
CHECK_WRITE(strm.putDWord( width ));
|
||||
CHECK_WRITE(strm.putDWord( height ));
|
||||
CHECK_WRITE(strm.putDWord( channels*8 ));
|
||||
CHECK_WRITE(strm.putDWord( fileStep*height ));
|
||||
CHECK_WRITE(strm.putDWord( RAS_STANDARD ));
|
||||
CHECK_WRITE(strm.putDWord( RMT_NONE ));
|
||||
CHECK_WRITE(strm.putDWord( 0 ));
|
||||
|
||||
for( y = 0; y < height; y++ )
|
||||
strm.putBytes( img.ptr(y), fileStep );
|
||||
CHECK_WRITE(strm.putBytes( img.ptr(y), fileStep ));
|
||||
|
||||
strm.close();
|
||||
result = true;
|
||||
|
@ -1100,16 +1100,6 @@ bool TiffEncoder::isFormatSupported( int depth ) const
|
||||
return depth == CV_8U || depth == CV_8S || depth == CV_16U || depth == CV_16S || depth == CV_32S || depth == CV_32F || depth == CV_64F;
|
||||
}
|
||||
|
||||
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 );
|
||||
}
|
||||
|
||||
class TiffEncoderBufHelper
|
||||
{
|
||||
public:
|
||||
|
@ -132,10 +132,6 @@ public:
|
||||
ImageEncoder newEncoder() const CV_OVERRIDE;
|
||||
|
||||
protected:
|
||||
void writeTag( WLByteStream& strm, TiffTag tag,
|
||||
TiffFieldType fieldType,
|
||||
int count, int value );
|
||||
|
||||
bool writeLibTiff( const std::vector<Mat>& img_vec, const std::vector<int>& params );
|
||||
bool write_32FC3_SGILOG(const Mat& img, void* tif);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user