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
SunRasterDecoder()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
~SunRasterDecoder()66 SunRasterDecoder::~SunRasterDecoder()
67 {
68 }
69
newDecoder() const70 ImageDecoder SunRasterDecoder::newDecoder() const
71 {
72 return makePtr<SunRasterDecoder>();
73 }
74
close()75 void SunRasterDecoder::close()
76 {
77 m_strm.close();
78 }
79
80
readHeader()81 bool SunRasterDecoder::readHeader()
82 {
83 bool result = false;
84
85 if( !m_strm.open( m_filename )) return false;
86
87 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 = (m_bpp > 0 && m_bpp <= 8) ? (3*(1 << m_bpp)) : 0;
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 catch(...)
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
readData(Mat & img)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 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, Size(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, Size(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, Size(m_width,1),
368 m_type == RAS_FORMAT_RGB ? 2 : 0 );
369 else
370 icvCvt_BGRA2Gray_8u_C4C1R( src + 4, 0, data, 0, Size(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 catch( ... )
380 {
381 }
382
383 return result;
384 }
385
386
387 //////////////////////////////////////////////////////////////////////////////////////////
388
SunRasterEncoder()389 SunRasterEncoder::SunRasterEncoder()
390 {
391 m_description = "Sun raster files (*.sr;*.ras)";
392 }
393
394
newEncoder() const395 ImageEncoder SunRasterEncoder::newEncoder() const
396 {
397 return makePtr<SunRasterEncoder>();
398 }
399
~SunRasterEncoder()400 SunRasterEncoder::~SunRasterEncoder()
401 {
402 }
403
write(const Mat & img,const std::vector<int> &)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