43
43
#include " precomp.hpp"
44
44
#include " utils.hpp"
45
45
#include " grfmt_pxm.hpp"
46
+ #include < iostream>
46
47
47
48
namespace cv
48
49
{
49
50
50
51
// /////////////////////// P?M reader //////////////////////////////
51
52
52
- static int ReadNumber ( RLByteStream& strm, int maxdigits )
53
+ static int ReadNumber (RLByteStream& strm, int maxdigits = 0 )
53
54
{
54
55
int code;
55
- int val = 0 ;
56
+ int64 val = 0 ;
56
57
int digits = 0 ;
57
58
58
59
code = strm.getByte ();
59
60
60
- if ( !isdigit (code))
61
+ while ( !isdigit (code))
61
62
{
62
- do
63
+ if (code == ' # ' )
63
64
{
64
- if ( code == ' # ' )
65
+ do
65
66
{
66
- do
67
- {
68
- code = strm.getByte ();
69
- }
70
- while ( code != ' \n ' && code != ' \r ' );
67
+ code = strm.getByte ();
71
68
}
72
-
69
+ while (code != ' \n ' && code != ' \r ' );
73
70
code = strm.getByte ();
74
-
75
- while ( isspace (code))
71
+ }
72
+ else if (isspace (code))
73
+ {
74
+ while (isspace (code))
76
75
code = strm.getByte ();
77
76
}
78
- while ( !isdigit ( code ));
77
+ else
78
+ {
79
+ #if 1
80
+ CV_ErrorNoReturn_ (Error::StsError, (" PXM: Unexpected code in ReadNumber(): 0x%x (%d)" , code, code));
81
+ #else
82
+ code = strm.getByte();
83
+ #endif
84
+ }
79
85
}
80
86
81
87
do
82
88
{
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 ;
85
93
code = strm.getByte ();
86
94
}
87
- while ( isdigit (code));
95
+ while ( isdigit (code));
88
96
89
- return val;
97
+ return ( int ) val;
90
98
}
91
99
92
100
@@ -122,13 +130,13 @@ ImageDecoder PxMDecoder::newDecoder() const
122
130
return makePtr<PxMDecoder>();
123
131
}
124
132
125
- void PxMDecoder::close ()
133
+ void PxMDecoder::close ()
126
134
{
127
135
m_strm.close ();
128
136
}
129
137
130
138
131
- bool PxMDecoder::readHeader ()
139
+ bool PxMDecoder::readHeader ()
132
140
{
133
141
bool result = false ;
134
142
@@ -158,10 +166,10 @@ bool PxMDecoder::readHeader()
158
166
m_binary = code >= ' 4' ;
159
167
m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1;
160
168
161
- m_width = ReadNumber ( m_strm, INT_MAX );
162
- m_height = ReadNumber ( m_strm, INT_MAX );
169
+ m_width = ReadNumber (m_strm);
170
+ m_height = ReadNumber (m_strm);
163
171
164
- m_maxval = m_bpp == 1 ? 1 : ReadNumber ( m_strm, INT_MAX );
172
+ m_maxval = m_bpp == 1 ? 1 : ReadNumber (m_strm);
165
173
if ( m_maxval > 65535 )
166
174
throw RBS_BAD_HEADER;
167
175
@@ -175,8 +183,14 @@ bool PxMDecoder::readHeader()
175
183
result = true ;
176
184
}
177
185
}
178
- catch (...)
186
+ catch (const cv::Exception&)
187
+ {
188
+ throw ;
189
+ }
190
+ catch (...)
179
191
{
192
+ std::cerr << " PXM::readHeader(): unknown C++ exception" << std::endl << std::flush;
193
+ throw ;
180
194
}
181
195
182
196
if ( !result )
@@ -189,33 +203,28 @@ bool PxMDecoder::readHeader()
189
203
}
190
204
191
205
192
- bool PxMDecoder::readData ( Mat& img )
206
+ bool PxMDecoder::readData ( Mat& img )
193
207
{
194
208
int color = img.channels () > 1 ;
195
209
uchar* data = img.ptr ();
196
210
PaletteEntry palette[256 ];
197
211
bool result = false ;
198
- int bit_depth = CV_ELEM_SIZE1 (m_type)*8 ;
199
- int src_pitch = (m_width*m_bpp*bit_depth/8 + 7 )/ 8 ;
212
+ const int bit_depth = CV_ELEM_SIZE1 (m_type)*8 ;
213
+ const int src_pitch = divUp (m_width*m_bpp*( bit_depth/8 ), 8 ) ;
200
214
int nch = CV_MAT_CN (m_type);
201
215
int width3 = m_width*nch;
202
- int i, x, y;
203
216
204
217
if ( m_offset < 0 || !m_strm.isOpened ())
205
218
return false ;
206
219
207
- AutoBuffer<uchar> _src (src_pitch + 32 );
208
- uchar* src = _src;
209
- AutoBuffer<uchar> _gray_palette;
210
- uchar* gray_palette = _gray_palette;
220
+ uchar gray_palette[256 ] = {0 };
211
221
212
222
// create LUT for converting colors
213
223
if ( bit_depth == 8 )
214
224
{
215
- _gray_palette.allocate (m_maxval + 1 );
216
- gray_palette = _gray_palette;
225
+ CV_Assert (m_maxval < 256 );
217
226
218
- for ( i = 0 ; i <= m_maxval; i++ )
227
+ for ( int i = 0 ; i <= m_maxval; i++)
219
228
gray_palette[i] = (uchar)((i*255 /m_maxval)^(m_bpp == 1 ? 255 : 0 ));
220
229
221
230
FillGrayPalette ( palette, m_bpp==1 ? 1 : 8 , m_bpp == 1 );
@@ -229,12 +238,16 @@ bool PxMDecoder::readData( Mat& img )
229
238
{
230
239
// //////////////////////// 1 BPP /////////////////////////
231
240
case 1 :
241
+ CV_Assert (CV_MAT_DEPTH (m_type) == CV_8U);
232
242
if ( !m_binary )
233
243
{
234
- for ( y = 0 ; y < m_height; y++, data += img.step )
244
+ AutoBuffer<uchar> _src (m_width);
245
+ uchar* src = _src;
246
+
247
+ for (int y = 0 ; y < m_height; y++, data += img.step )
235
248
{
236
- for ( x = 0 ; x < m_width; x++ )
237
- src[x] = ReadNumber ( m_strm, 1 ) != 0 ;
249
+ for ( int x = 0 ; x < m_width; x++)
250
+ src[x] = ReadNumber (m_strm, 1 ) != 0 ;
238
251
239
252
if ( color )
240
253
FillColorRow8 ( data, src, m_width, palette );
@@ -244,7 +257,10 @@ bool PxMDecoder::readData( Mat& img )
244
257
}
245
258
else
246
259
{
247
- for ( y = 0 ; y < m_height; y++, data += img.step )
260
+ AutoBuffer<uchar> _src (src_pitch);
261
+ uchar* src = _src;
262
+
263
+ for (int y = 0 ; y < m_height; y++, data += img.step )
248
264
{
249
265
m_strm.getBytes ( src, src_pitch );
250
266
@@ -260,13 +276,17 @@ bool PxMDecoder::readData( Mat& img )
260
276
// //////////////////////// 8 BPP /////////////////////////
261
277
case 8 :
262
278
case 24 :
263
- for ( y = 0 ; y < m_height; y++, data += img.step )
279
+ {
280
+ AutoBuffer<uchar> _src (std::max<size_t >(width3*2 , src_pitch));
281
+ uchar* src = _src;
282
+
283
+ for (int y = 0 ; y < m_height; y++, data += img.step )
264
284
{
265
285
if ( !m_binary )
266
286
{
267
- for ( x = 0 ; x < width3; x++ )
287
+ for ( int x = 0 ; x < width3; x++)
268
288
{
269
- int code = ReadNumber ( m_strm, INT_MAX );
289
+ int code = ReadNumber (m_strm);
270
290
if ( (unsigned )code > (unsigned )m_maxval ) code = m_maxval;
271
291
if ( bit_depth == 8 )
272
292
src[x] = gray_palette[code];
@@ -279,7 +299,7 @@ bool PxMDecoder::readData( Mat& img )
279
299
m_strm.getBytes ( src, src_pitch );
280
300
if ( bit_depth == 16 && !isBigEndian () )
281
301
{
282
- for ( x = 0 ; x < width3; x++ )
302
+ for ( int x = 0 ; x < width3; x++)
283
303
{
284
304
uchar v = src[x * 2 ];
285
305
src[x * 2 ] = src[x * 2 + 1 ];
@@ -290,7 +310,7 @@ bool PxMDecoder::readData( Mat& img )
290
310
291
311
if ( img.depth () == CV_8U && bit_depth == 16 )
292
312
{
293
- for ( x = 0 ; x < width3; x++ )
313
+ for ( int x = 0 ; x < width3; x++)
294
314
{
295
315
int v = ((ushort *)src)[x];
296
316
src[x] = (uchar)(v >> 8 );
@@ -331,12 +351,19 @@ bool PxMDecoder::readData( Mat& img )
331
351
}
332
352
result = true ;
333
353
break ;
354
+ }
334
355
default :
335
- assert ( 0 );
356
+ CV_ErrorNoReturn (Error::StsError, " m_bpp is not supported " );
336
357
}
337
358
}
338
- catch (...)
359
+ catch (const cv::Exception&)
360
+ {
361
+ throw ;
362
+ }
363
+ catch (...)
339
364
{
365
+ std::cerr << " PXM::readData(): unknown exception" << std::endl << std::flush;
366
+ throw ;
340
367
}
341
368
342
369
return result;
@@ -412,8 +439,9 @@ bool PxMEncoder::write( const Mat& img, const std::vector<int>& params )
412
439
char * buffer = _buffer;
413
440
414
441
// write header;
415
- sprintf ( buffer, " P%c\n %d %d\n %d\n " ,
442
+ sprintf ( buffer, " P%c\n # Generated by OpenCV %s \n %d %d\n %d\n " ,
416
443
' 2' + (channels > 1 ? 1 : 0 ) + (isBinary ? 3 : 0 ),
444
+ CV_VERSION,
417
445
width, height, (1 << depth) - 1 );
418
446
419
447
strm.putBytes ( buffer, (int )strlen (buffer) );
0 commit comments