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