Merge pull request #25975 from asmorkalov:as/bmp_error_check

Improved error handling in image codecs.
This commit is contained in:
Alexander Smorkalov 2024-08-01 14:15:40 +03:00 committed by GitHub
commit b9b2d551ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 99 additions and 87 deletions

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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();

View File

@ -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

View File

@ -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) ));
}
}

View File

@ -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;

View File

@ -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:

View File

@ -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);