Skip to content

Commit 30f7576

Browse files
authored
Merge pull request opencv#9383 from alalek:imgcodecs_refactoring_2.4
2 parents f548d66 + 72d2925 commit 30f7576

File tree

7 files changed

+207
-72
lines changed

7 files changed

+207
-72
lines changed

modules/core/include/opencv2/core/core.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,6 +3248,9 @@ template<typename _Tp, size_t fixed_size=4096/sizeof(_Tp)+8> class AutoBuffer
32483248
//! returns read-only pointer to the real buffer, stack-allocated or head-allocated
32493249
operator const _Tp* () const;
32503250

3251+
//! returns number of allocated elements
3252+
size_t getSize() const;
3253+
32513254
protected:
32523255
//! pointer to the real buffer, can point to buf if the buffer is small enough
32533256
_Tp* ptr;

modules/core/include/opencv2/core/operations.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2581,6 +2581,9 @@ template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::op
25812581
template<typename _Tp, size_t fixed_size> inline AutoBuffer<_Tp, fixed_size>::operator const _Tp* () const
25822582
{ return ptr; }
25832583

2584+
template<typename _Tp, size_t fixed_size> inline size_t AutoBuffer<_Tp, fixed_size>::getSize() const
2585+
{ return size; }
2586+
25842587

25852588
/////////////////////////////////// Ptr ////////////////////////////////////////
25862589

modules/highgui/src/bitstrm.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,8 @@ int RLByteStream::getByte()
208208
current = m_current;
209209
}
210210

211+
CV_Assert(current < m_end);
212+
211213
val = *((uchar*)current);
212214
m_current = current + 1;
213215
return val;

modules/highgui/src/bitstrm.hpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,20 @@
4848
namespace cv
4949
{
5050

51-
enum
52-
{
53-
RBS_THROW_EOS=-123, // <end of stream> exception code
54-
RBS_THROW_FORB=-124, // <forrbidden huffman code> exception code
55-
RBS_HUFF_FORB=2047, // forrbidden huffman code "value"
56-
RBS_BAD_HEADER=-125 // invalid header
51+
#define DECLARE_RBS_EXCEPTION(name) \
52+
class RBS_ ## name ## _Exception : public cv::Exception \
53+
{ \
54+
public: \
55+
RBS_ ## name ## _Exception(int code_, const String& err_, const String& func_, const String& file_, int line_) : \
56+
cv::Exception(code_, err_, func_, file_, line_) \
57+
{} \
5758
};
59+
DECLARE_RBS_EXCEPTION(THROW_EOS)
60+
#define RBS_THROW_EOS RBS_THROW_EOS_Exception(CV_StsError, "Unexpected end of input stream", CV_Func, __FILE__, __LINE__)
61+
DECLARE_RBS_EXCEPTION(THROW_FORB)
62+
#define RBS_THROW_FORB RBS_THROW_FORB_Exception(CV_StsError, "Forrbidden huffman code", CV_Func, __FILE__, __LINE__)
63+
DECLARE_RBS_EXCEPTION(BAD_HEADER)
64+
#define RBS_BAD_HEADER RBS_BAD_HEADER_Exception(CV_StsError, "Invalid header", CV_Func, __FILE__, __LINE__)
5865

5966
typedef unsigned long ulong;
6067

modules/highgui/src/grfmt_bmp.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,9 @@ bool BmpDecoder::readHeader()
115115

116116
if( m_bpp <= 8 )
117117
{
118-
memset( m_palette, 0, sizeof(m_palette));
119-
m_strm.getBytes( m_palette, (clrused == 0? 1<<m_bpp : clrused)*4 );
118+
CV_Assert(clrused < 256);
119+
memset(m_palette, 0, sizeof(m_palette));
120+
m_strm.getBytes(m_palette, (clrused == 0? 1<<m_bpp : clrused)*4 );
120121
iscolor = IsColorPalette( m_palette, m_bpp );
121122
}
122123
else if( m_bpp == 16 && m_rle_code == BMP_BITFIELDS )
@@ -282,7 +283,9 @@ bool BmpDecoder::readData( Mat& img )
282283
else if( code > 2 ) // absolute mode
283284
{
284285
if( data + code*nch > line_end ) goto decode_rle4_bad;
285-
m_strm.getBytes( src, (((code + 1)>>1) + 1) & -2 );
286+
int sz = (((code + 1)>>1) + 1) & (~1);
287+
CV_Assert((size_t)sz < _src.getSize());
288+
m_strm.getBytes(src, sz);
286289
if( color )
287290
data = FillColorRow4( data, src, code, m_palette );
288291
else
@@ -371,7 +374,9 @@ decode_rle4_bad: ;
371374

372375
if( data + code3 > line_end )
373376
goto decode_rle8_bad;
374-
m_strm.getBytes( src, (code + 1) & -2 );
377+
int sz = (code + 1) & (~1);
378+
CV_Assert((size_t)sz < _src.getSize());
379+
m_strm.getBytes(src, sz);
375380
if( color )
376381
data = FillColorRow8( data, src, code, m_palette );
377382
else

modules/highgui/src/grfmt_pxm.cpp

Lines changed: 74 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -43,50 +43,58 @@
4343
#include "precomp.hpp"
4444
#include "utils.hpp"
4545
#include "grfmt_pxm.hpp"
46+
#include <iostream>
4647

4748
namespace cv
4849
{
4950

5051
///////////////////////// P?M reader //////////////////////////////
5152

52-
static int ReadNumber( RLByteStream& strm, int maxdigits )
53+
static int ReadNumber(RLByteStream& strm, int maxdigits = 0)
5354
{
5455
int code;
55-
int val = 0;
56+
int64 val = 0;
5657
int digits = 0;
5758

5859
code = strm.getByte();
5960

60-
if( !isdigit(code))
61+
while (!isdigit(code))
6162
{
62-
do
63+
if (code == '#' )
6364
{
64-
if( code == '#' )
65+
do
6566
{
66-
do
67-
{
68-
code = strm.getByte();
69-
}
70-
while( code != '\n' && code != '\r' );
67+
code = strm.getByte();
7168
}
72-
69+
while (code != '\n' && code != '\r');
7370
code = strm.getByte();
74-
75-
while( isspace(code))
71+
}
72+
else if (isspace(code))
73+
{
74+
while (isspace(code))
7675
code = strm.getByte();
7776
}
78-
while( !isdigit( code ));
77+
else
78+
{
79+
#if 1
80+
CV_Error_(CV_StsError, ("PXM: Unexpected code in ReadNumber(): 0x%x (%d)", code, code));
81+
#else
82+
code = strm.getByte();
83+
#endif
84+
}
7985
}
8086

8187
do
8288
{
83-
val = val*10 + code - '0';
84-
if( ++digits >= maxdigits ) break;
89+
val = val*10 + (code - '0');
90+
CV_Assert(val <= INT_MAX && "PXM: ReadNumber(): result is too large");
91+
digits++;
92+
if (maxdigits != 0 && digits >= maxdigits) break;
8593
code = strm.getByte();
8694
}
87-
while( isdigit(code));
95+
while (isdigit(code));
8896

89-
return val;
97+
return (int)val;
9098
}
9199

92100

@@ -119,13 +127,13 @@ ImageDecoder PxMDecoder::newDecoder() const
119127
return new PxMDecoder;
120128
}
121129

122-
void PxMDecoder::close()
130+
void PxMDecoder::close()
123131
{
124132
m_strm.close();
125133
}
126134

127135

128-
bool PxMDecoder::readHeader()
136+
bool PxMDecoder::readHeader()
129137
{
130138
bool result = false;
131139

@@ -155,10 +163,10 @@ bool PxMDecoder::readHeader()
155163
m_binary = code >= '4';
156164
m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1;
157165

158-
m_width = ReadNumber( m_strm, INT_MAX );
159-
m_height = ReadNumber( m_strm, INT_MAX );
166+
m_width = ReadNumber(m_strm);
167+
m_height = ReadNumber(m_strm);
160168

161-
m_maxval = m_bpp == 1 ? 1 : ReadNumber( m_strm, INT_MAX );
169+
m_maxval = m_bpp == 1 ? 1 : ReadNumber(m_strm);
162170
if( m_maxval > 65535 )
163171
throw RBS_BAD_HEADER;
164172

@@ -172,8 +180,14 @@ bool PxMDecoder::readHeader()
172180
result = true;
173181
}
174182
}
175-
catch(...)
183+
catch (const cv::Exception&)
176184
{
185+
throw;
186+
}
187+
catch (...)
188+
{
189+
std::cerr << "PXM::readHeader(): unknown C++ exception" << std::endl << std::flush;
190+
throw;
177191
}
178192

179193
if( !result )
@@ -193,27 +207,23 @@ bool PxMDecoder::readData( Mat& img )
193207
int step = (int)img.step;
194208
PaletteEntry palette[256];
195209
bool result = false;
196-
int bit_depth = CV_ELEM_SIZE1(m_type)*8;
197-
int src_pitch = (m_width*m_bpp*bit_depth/8 + 7)/8;
210+
const int bit_depth = CV_ELEM_SIZE1(m_type)*8;
211+
const int src_pitch = (m_width*m_bpp*(bit_depth/8) + 7) / 8;
212+
198213
int nch = CV_MAT_CN(m_type);
199214
int width3 = m_width*nch;
200-
int i, x, y;
201215

202216
if( m_offset < 0 || !m_strm.isOpened())
203217
return false;
204218

205-
AutoBuffer<uchar,1024> _src(src_pitch + 32);
206-
uchar* src = _src;
207-
AutoBuffer<uchar,1024> _gray_palette;
208-
uchar* gray_palette = _gray_palette;
219+
uchar gray_palette[256] = {0};
209220

210221
// create LUT for converting colors
211222
if( bit_depth == 8 )
212223
{
213-
_gray_palette.allocate(m_maxval + 1);
214-
gray_palette = _gray_palette;
224+
CV_Assert(m_maxval < 256);
215225

216-
for( i = 0; i <= m_maxval; i++ )
226+
for (int i = 0; i <= m_maxval; i++)
217227
gray_palette[i] = (uchar)((i*255/m_maxval)^(m_bpp == 1 ? 255 : 0));
218228

219229
FillGrayPalette( palette, m_bpp==1 ? 1 : 8 , m_bpp == 1 );
@@ -227,12 +237,16 @@ bool PxMDecoder::readData( Mat& img )
227237
{
228238
////////////////////////// 1 BPP /////////////////////////
229239
case 1:
240+
CV_Assert(CV_MAT_DEPTH(m_type) == CV_8U);
230241
if( !m_binary )
231242
{
232-
for( y = 0; y < m_height; y++, data += step )
243+
AutoBuffer<uchar> _src(m_width);
244+
uchar* src = _src;
245+
246+
for (int y = 0; y < m_height; y++, data += step)
233247
{
234-
for( x = 0; x < m_width; x++ )
235-
src[x] = ReadNumber( m_strm, 1 ) != 0;
248+
for (int x = 0; x < m_width; x++)
249+
src[x] = ReadNumber(m_strm, 1) != 0;
236250

237251
if( color )
238252
FillColorRow8( data, src, m_width, palette );
@@ -242,7 +256,10 @@ bool PxMDecoder::readData( Mat& img )
242256
}
243257
else
244258
{
245-
for( y = 0; y < m_height; y++, data += step )
259+
AutoBuffer<uchar> _src(src_pitch);
260+
uchar* src = _src;
261+
262+
for (int y = 0; y < m_height; y++, data += step)
246263
{
247264
m_strm.getBytes( src, src_pitch );
248265

@@ -258,11 +275,15 @@ bool PxMDecoder::readData( Mat& img )
258275
////////////////////////// 8 BPP /////////////////////////
259276
case 8:
260277
case 24:
261-
for( y = 0; y < m_height; y++, data += step )
278+
{
279+
AutoBuffer<uchar> _src(std::max<size_t>(width3*2, src_pitch));
280+
uchar* src = _src;
281+
282+
for (int y = 0; y < m_height; y++, data += step)
262283
{
263284
if( !m_binary )
264285
{
265-
for( x = 0; x < width3; x++ )
286+
for (int x = 0; x < width3; x++)
266287
{
267288
int code = ReadNumber( m_strm, INT_MAX );
268289
if( (unsigned)code > (unsigned)m_maxval ) code = m_maxval;
@@ -277,7 +298,7 @@ bool PxMDecoder::readData( Mat& img )
277298
m_strm.getBytes( src, src_pitch );
278299
if( bit_depth == 16 && !isBigEndian() )
279300
{
280-
for( x = 0; x < width3; x++ )
301+
for (int x = 0; x < width3; x++)
281302
{
282303
uchar v = src[x * 2];
283304
src[x * 2] = src[x * 2 + 1];
@@ -288,7 +309,7 @@ bool PxMDecoder::readData( Mat& img )
288309

289310
if( img.depth() == CV_8U && bit_depth == 16 )
290311
{
291-
for( x = 0; x < width3; x++ )
312+
for (int x = 0; x < width3; x++)
292313
{
293314
int v = ((ushort *)src)[x];
294315
src[x] = (uchar)(v >> 8);
@@ -329,12 +350,19 @@ bool PxMDecoder::readData( Mat& img )
329350
}
330351
result = true;
331352
break;
353+
}
332354
default:
333-
assert(0);
355+
CV_Error(CV_StsError, "m_bpp is not supported");
334356
}
335357
}
336-
catch(...)
358+
catch (const cv::Exception&)
359+
{
360+
throw;
361+
}
362+
catch (...)
337363
{
364+
std::cerr << "PXM::readData(): unknown exception" << std::endl << std::flush;
365+
throw;
338366
}
339367

340368
return result;
@@ -410,8 +438,9 @@ bool PxMEncoder::write( const Mat& img, const vector<int>& params )
410438
char* buffer = _buffer;
411439

412440
// write header;
413-
sprintf( buffer, "P%c\n%d %d\n%d\n",
441+
sprintf( buffer, "P%c\n# Generated by OpenCV %s\n%d %d\n%d\n",
414442
'2' + (channels > 1 ? 1 : 0) + (isBinary ? 3 : 0),
443+
CV_VERSION,
415444
width, height, (1 << depth) - 1 );
416445

417446
strm.putBytes( buffer, (int)strlen(buffer) );

0 commit comments

Comments
 (0)