Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/modules/imgcodecs/src/grfmt_sunras.cpp
16337 views
1
/*M///////////////////////////////////////////////////////////////////////////////////////
2
//
3
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4
//
5
// By downloading, copying, installing or using the software you agree to this license.
6
// If you do not agree to this license, do not download, install,
7
// copy or use the software.
8
//
9
//
10
// License Agreement
11
// For Open Source Computer Vision Library
12
//
13
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15
// Third party copyrights are property of their respective owners.
16
//
17
// Redistribution and use in source and binary forms, with or without modification,
18
// are permitted provided that the following conditions are met:
19
//
20
// * Redistribution's of source code must retain the above copyright notice,
21
// this list of conditions and the following disclaimer.
22
//
23
// * Redistribution's in binary form must reproduce the above copyright notice,
24
// this list of conditions and the following disclaimer in the documentation
25
// and/or other materials provided with the distribution.
26
//
27
// * The name of the copyright holders may not be used to endorse or promote products
28
// derived from this software without specific prior written permission.
29
//
30
// This software is provided by the copyright holders and contributors "as is" and
31
// any express or implied warranties, including, but not limited to, the implied
32
// warranties of merchantability and fitness for a particular purpose are disclaimed.
33
// In no event shall the Intel Corporation or contributors be liable for any direct,
34
// indirect, incidental, special, exemplary, or consequential damages
35
// (including, but not limited to, procurement of substitute goods or services;
36
// loss of use, data, or profits; or business interruption) however caused
37
// and on any theory of liability, whether in contract, strict liability,
38
// or tort (including negligence or otherwise) arising in any way out of
39
// the use of this software, even if advised of the possibility of such damage.
40
//
41
//M*/
42
43
#include "precomp.hpp"
44
#include "grfmt_sunras.hpp"
45
46
#ifdef HAVE_IMGCODEC_SUNRASTER
47
48
namespace cv
49
{
50
51
static const char* fmtSignSunRas = "\x59\xA6\x6A\x95";
52
53
/************************ Sun Raster reader *****************************/
54
55
SunRasterDecoder::SunRasterDecoder()
56
{
57
m_offset = -1;
58
m_signature = fmtSignSunRas;
59
m_bpp = 0;
60
m_encoding = RAS_STANDARD;
61
m_maptype = RMT_NONE;
62
m_maplength = 0;
63
}
64
65
66
SunRasterDecoder::~SunRasterDecoder()
67
{
68
}
69
70
ImageDecoder SunRasterDecoder::newDecoder() const
71
{
72
return makePtr<SunRasterDecoder>();
73
}
74
75
void SunRasterDecoder::close()
76
{
77
m_strm.close();
78
}
79
80
81
bool SunRasterDecoder::readHeader()
82
{
83
bool result = false;
84
85
if( !m_strm.open( m_filename )) return false;
86
87
CV_TRY
88
{
89
m_strm.skip( 4 );
90
m_width = m_strm.getDWord();
91
m_height = m_strm.getDWord();
92
m_bpp = m_strm.getDWord();
93
int palSize = 3*(1 << m_bpp);
94
95
m_strm.skip( 4 );
96
m_encoding = (SunRasType)m_strm.getDWord();
97
m_maptype = (SunRasMapType)m_strm.getDWord();
98
m_maplength = m_strm.getDWord();
99
100
if( m_width > 0 && m_height > 0 &&
101
(m_bpp == 1 || m_bpp == 8 || m_bpp == 24 || m_bpp == 32) &&
102
(m_encoding == RAS_OLD || m_encoding == RAS_STANDARD ||
103
(m_type == RAS_BYTE_ENCODED && m_bpp == 8) || m_type == RAS_FORMAT_RGB) &&
104
((m_maptype == RMT_NONE && m_maplength == 0) ||
105
(m_maptype == RMT_EQUAL_RGB && m_maplength <= palSize && m_maplength > 0 && m_bpp <= 8)))
106
{
107
memset( m_palette, 0, sizeof(m_palette));
108
109
if( m_maplength != 0 )
110
{
111
uchar buffer[256*3];
112
113
if( m_strm.getBytes( buffer, m_maplength ) == m_maplength )
114
{
115
int i;
116
palSize = m_maplength/3;
117
118
for( i = 0; i < palSize; i++ )
119
{
120
m_palette[i].b = buffer[i + 2*palSize];
121
m_palette[i].g = buffer[i + palSize];
122
m_palette[i].r = buffer[i];
123
m_palette[i].a = 0;
124
}
125
126
m_type = IsColorPalette( m_palette, m_bpp ) ? CV_8UC3 : CV_8UC1;
127
m_offset = m_strm.getPos();
128
129
CV_Assert(m_offset == 32 + m_maplength);
130
result = true;
131
}
132
}
133
else
134
{
135
m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1;
136
137
if( CV_MAT_CN(m_type) == 1 )
138
FillGrayPalette( m_palette, m_bpp );
139
140
m_offset = m_strm.getPos();
141
142
CV_Assert(m_offset == 32 + m_maplength);
143
result = true;
144
}
145
}
146
}
147
CV_CATCH_ALL
148
{
149
}
150
151
if( !result )
152
{
153
m_offset = -1;
154
m_width = m_height = -1;
155
m_strm.close();
156
}
157
return result;
158
}
159
160
161
bool SunRasterDecoder::readData( Mat& img )
162
{
163
bool color = img.channels() > 1;
164
uchar* data = img.ptr();
165
size_t step = img.step;
166
uchar gray_palette[256] = {0};
167
bool result = false;
168
int src_pitch = ((m_width*m_bpp + 7)/8 + 1) & -2;
169
int nch = color ? 3 : 1;
170
int width3 = m_width*nch;
171
int y;
172
173
if( m_offset < 0 || !m_strm.isOpened())
174
return false;
175
176
AutoBuffer<uchar> _src(src_pitch + 32);
177
uchar* src = _src.data();
178
179
if( !color && m_maptype == RMT_EQUAL_RGB )
180
CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp );
181
182
CV_TRY
183
{
184
m_strm.setPos( m_offset );
185
186
switch( m_bpp )
187
{
188
/************************* 1 BPP ************************/
189
case 1:
190
if( m_type != RAS_BYTE_ENCODED )
191
{
192
for( y = 0; y < m_height; y++, data += step )
193
{
194
m_strm.getBytes( src, src_pitch );
195
if( color )
196
FillColorRow1( data, src, m_width, m_palette );
197
else
198
FillGrayRow1( data, src, m_width, gray_palette );
199
}
200
result = true;
201
}
202
else
203
{
204
uchar* line_end = src + (m_width*m_bpp + 7)/8;
205
uchar* tsrc = src;
206
y = 0;
207
208
for(;;)
209
{
210
int max_count = (int)(line_end - tsrc);
211
int code = 0, len = 0, len1 = 0;
212
213
do
214
{
215
code = m_strm.getByte();
216
if( code == 0x80 )
217
{
218
len = m_strm.getByte();
219
if( len != 0 ) break;
220
}
221
tsrc[len1] = (uchar)code;
222
}
223
while( ++len1 < max_count );
224
225
tsrc += len1;
226
227
if( len > 0 ) // encoded mode
228
{
229
++len;
230
code = m_strm.getByte();
231
if( len > line_end - tsrc )
232
{
233
CV_Error(Error::StsInternal, "");
234
goto bad_decoding_1bpp;
235
}
236
237
memset( tsrc, code, len );
238
tsrc += len;
239
}
240
241
if( tsrc >= line_end )
242
{
243
tsrc = src;
244
if( color )
245
FillColorRow1( data, src, m_width, m_palette );
246
else
247
FillGrayRow1( data, src, m_width, gray_palette );
248
data += step;
249
if( ++y >= m_height ) break;
250
}
251
}
252
result = true;
253
bad_decoding_1bpp:
254
;
255
}
256
break;
257
/************************* 8 BPP ************************/
258
case 8:
259
if( m_type != RAS_BYTE_ENCODED )
260
{
261
for( y = 0; y < m_height; y++, data += step )
262
{
263
m_strm.getBytes( src, src_pitch );
264
if( color )
265
FillColorRow8( data, src, m_width, m_palette );
266
else
267
FillGrayRow8( data, src, m_width, gray_palette );
268
}
269
result = true;
270
}
271
else // RLE-encoded
272
{
273
uchar* line_end = data + width3;
274
y = 0;
275
276
for(;;)
277
{
278
int max_count = (int)(line_end - data);
279
int code = 0, len = 0, len1;
280
uchar* tsrc = src;
281
282
do
283
{
284
code = m_strm.getByte();
285
if( code == 0x80 )
286
{
287
len = m_strm.getByte();
288
if( len != 0 ) break;
289
}
290
*tsrc++ = (uchar)code;
291
}
292
while( (max_count -= nch) > 0 );
293
294
len1 = (int)(tsrc - src);
295
296
if( len1 > 0 )
297
{
298
if( color )
299
FillColorRow8( data, src, len1, m_palette );
300
else
301
FillGrayRow8( data, src, len1, gray_palette );
302
data += len1*nch;
303
}
304
305
if( len > 0 ) // encoded mode
306
{
307
len = (len + 1)*nch;
308
code = m_strm.getByte();
309
310
if( color )
311
data = FillUniColor( data, line_end, validateToInt(step), width3,
312
y, m_height, len,
313
m_palette[code] );
314
else
315
data = FillUniGray( data, line_end, validateToInt(step), width3,
316
y, m_height, len,
317
gray_palette[code] );
318
if( y >= m_height )
319
break;
320
}
321
322
if( data == line_end )
323
{
324
if( m_strm.getByte() != 0 )
325
goto bad_decoding_end;
326
line_end += step;
327
data = line_end - width3;
328
if( ++y >= m_height ) break;
329
}
330
}
331
332
result = true;
333
bad_decoding_end:
334
;
335
}
336
break;
337
/************************* 24 BPP ************************/
338
case 24:
339
for( y = 0; y < m_height; y++, data += step )
340
{
341
m_strm.getBytes(src, src_pitch );
342
343
if( color )
344
{
345
if( m_type == RAS_FORMAT_RGB )
346
icvCvt_RGB2BGR_8u_C3R(src, 0, data, 0, cvSize(m_width,1) );
347
else
348
memcpy(data, src, std::min(step, (size_t)src_pitch));
349
}
350
else
351
{
352
icvCvt_BGR2Gray_8u_C3C1R(src, 0, data, 0, cvSize(m_width,1),
353
m_type == RAS_FORMAT_RGB ? 2 : 0 );
354
}
355
}
356
result = true;
357
break;
358
/************************* 32 BPP ************************/
359
case 32:
360
for( y = 0; y < m_height; y++, data += step )
361
{
362
/* hack: a0 b0 g0 r0 a1 b1 g1 r1 ... are written to src + 3,
363
so when we look at src + 4, we see b0 g0 r0 x b1 g1 g1 x ... */
364
m_strm.getBytes( src + 3, src_pitch );
365
366
if( color )
367
icvCvt_BGRA2BGR_8u_C4C3R( src + 4, 0, data, 0, cvSize(m_width,1),
368
m_type == RAS_FORMAT_RGB ? 2 : 0 );
369
else
370
icvCvt_BGRA2Gray_8u_C4C1R( src + 4, 0, data, 0, cvSize(m_width,1),
371
m_type == RAS_FORMAT_RGB ? 2 : 0 );
372
}
373
result = true;
374
break;
375
default:
376
CV_Error(Error::StsInternal, "");
377
}
378
}
379
CV_CATCH_ALL
380
{
381
}
382
383
return result;
384
}
385
386
387
//////////////////////////////////////////////////////////////////////////////////////////
388
389
SunRasterEncoder::SunRasterEncoder()
390
{
391
m_description = "Sun raster files (*.sr;*.ras)";
392
}
393
394
395
ImageEncoder SunRasterEncoder::newEncoder() const
396
{
397
return makePtr<SunRasterEncoder>();
398
}
399
400
SunRasterEncoder::~SunRasterEncoder()
401
{
402
}
403
404
bool SunRasterEncoder::write( const Mat& img, const std::vector<int>& )
405
{
406
bool result = false;
407
int y, width = img.cols, height = img.rows, channels = img.channels();
408
int fileStep = (width*channels + 1) & -2;
409
WMByteStream strm;
410
411
if( strm.open(m_filename) )
412
{
413
strm.putBytes( fmtSignSunRas, (int)strlen(fmtSignSunRas) );
414
strm.putDWord( width );
415
strm.putDWord( height );
416
strm.putDWord( channels*8 );
417
strm.putDWord( fileStep*height );
418
strm.putDWord( RAS_STANDARD );
419
strm.putDWord( RMT_NONE );
420
strm.putDWord( 0 );
421
422
for( y = 0; y < height; y++ )
423
strm.putBytes( img.ptr(y), fileStep );
424
425
strm.close();
426
result = true;
427
}
428
return result;
429
}
430
431
}
432
433
#endif // HAVE_IMGCODEC_SUNRASTER
434
435