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