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_Error_ (CV_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
@@ -119,13 +127,13 @@ ImageDecoder PxMDecoder::newDecoder() const
119
127
return new PxMDecoder;
120
128
}
121
129
122
- void PxMDecoder::close ()
130
+ void PxMDecoder::close ()
123
131
{
124
132
m_strm.close ();
125
133
}
126
134
127
135
128
- bool PxMDecoder::readHeader ()
136
+ bool PxMDecoder::readHeader ()
129
137
{
130
138
bool result = false ;
131
139
@@ -155,10 +163,10 @@ bool PxMDecoder::readHeader()
155
163
m_binary = code >= ' 4' ;
156
164
m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1;
157
165
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);
160
168
161
- m_maxval = m_bpp == 1 ? 1 : ReadNumber ( m_strm, INT_MAX );
169
+ m_maxval = m_bpp == 1 ? 1 : ReadNumber (m_strm);
162
170
if ( m_maxval > 65535 )
163
171
throw RBS_BAD_HEADER;
164
172
@@ -172,8 +180,14 @@ bool PxMDecoder::readHeader()
172
180
result = true ;
173
181
}
174
182
}
175
- catch (... )
183
+ catch ( const cv::Exception& )
176
184
{
185
+ throw ;
186
+ }
187
+ catch (...)
188
+ {
189
+ std::cerr << " PXM::readHeader(): unknown C++ exception" << std::endl << std::flush;
190
+ throw ;
177
191
}
178
192
179
193
if ( !result )
@@ -193,27 +207,23 @@ bool PxMDecoder::readData( Mat& img )
193
207
int step = (int )img.step ;
194
208
PaletteEntry palette[256 ];
195
209
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
+
198
213
int nch = CV_MAT_CN (m_type);
199
214
int width3 = m_width*nch;
200
- int i, x, y;
201
215
202
216
if ( m_offset < 0 || !m_strm.isOpened ())
203
217
return false ;
204
218
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 };
209
220
210
221
// create LUT for converting colors
211
222
if ( bit_depth == 8 )
212
223
{
213
- _gray_palette.allocate (m_maxval + 1 );
214
- gray_palette = _gray_palette;
224
+ CV_Assert (m_maxval < 256 );
215
225
216
- for ( i = 0 ; i <= m_maxval; i++ )
226
+ for ( int i = 0 ; i <= m_maxval; i++)
217
227
gray_palette[i] = (uchar)((i*255 /m_maxval)^(m_bpp == 1 ? 255 : 0 ));
218
228
219
229
FillGrayPalette ( palette, m_bpp==1 ? 1 : 8 , m_bpp == 1 );
@@ -227,12 +237,16 @@ bool PxMDecoder::readData( Mat& img )
227
237
{
228
238
// //////////////////////// 1 BPP /////////////////////////
229
239
case 1 :
240
+ CV_Assert (CV_MAT_DEPTH (m_type) == CV_8U);
230
241
if ( !m_binary )
231
242
{
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)
233
247
{
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 ;
236
250
237
251
if ( color )
238
252
FillColorRow8 ( data, src, m_width, palette );
@@ -242,7 +256,10 @@ bool PxMDecoder::readData( Mat& img )
242
256
}
243
257
else
244
258
{
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)
246
263
{
247
264
m_strm.getBytes ( src, src_pitch );
248
265
@@ -258,11 +275,15 @@ bool PxMDecoder::readData( Mat& img )
258
275
// //////////////////////// 8 BPP /////////////////////////
259
276
case 8 :
260
277
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)
262
283
{
263
284
if ( !m_binary )
264
285
{
265
- for ( x = 0 ; x < width3; x++ )
286
+ for ( int x = 0 ; x < width3; x++)
266
287
{
267
288
int code = ReadNumber ( m_strm, INT_MAX );
268
289
if ( (unsigned )code > (unsigned )m_maxval ) code = m_maxval;
@@ -277,7 +298,7 @@ bool PxMDecoder::readData( Mat& img )
277
298
m_strm.getBytes ( src, src_pitch );
278
299
if ( bit_depth == 16 && !isBigEndian () )
279
300
{
280
- for ( x = 0 ; x < width3; x++ )
301
+ for ( int x = 0 ; x < width3; x++)
281
302
{
282
303
uchar v = src[x * 2 ];
283
304
src[x * 2 ] = src[x * 2 + 1 ];
@@ -288,7 +309,7 @@ bool PxMDecoder::readData( Mat& img )
288
309
289
310
if ( img.depth () == CV_8U && bit_depth == 16 )
290
311
{
291
- for ( x = 0 ; x < width3; x++ )
312
+ for ( int x = 0 ; x < width3; x++)
292
313
{
293
314
int v = ((ushort *)src)[x];
294
315
src[x] = (uchar)(v >> 8 );
@@ -329,12 +350,19 @@ bool PxMDecoder::readData( Mat& img )
329
350
}
330
351
result = true ;
331
352
break ;
353
+ }
332
354
default :
333
- assert ( 0 );
355
+ CV_Error (CV_StsError, " m_bpp is not supported " );
334
356
}
335
357
}
336
- catch (...)
358
+ catch (const cv::Exception&)
359
+ {
360
+ throw ;
361
+ }
362
+ catch (...)
337
363
{
364
+ std::cerr << " PXM::readData(): unknown exception" << std::endl << std::flush;
365
+ throw ;
338
366
}
339
367
340
368
return result;
@@ -410,8 +438,9 @@ bool PxMEncoder::write( const Mat& img, const vector<int>& params )
410
438
char * buffer = _buffer;
411
439
412
440
// 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 " ,
414
442
' 2' + (channels > 1 ? 1 : 0 ) + (isBinary ? 3 : 0 ),
443
+ CV_VERSION,
415
444
width, height, (1 << depth) - 1 );
416
445
417
446
strm.putBytes ( buffer, (int )strlen (buffer) );
0 commit comments