f8062f581b6c356f8cbf7714d20e722a7777a38a
[opencv] / otherlibs / VlGrFmts / grfmt_pxm.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 "grfmt_pxm.h"
43 #include <assert.h>
44 #include <string.h>
45 #include <ctype.h>
46 #include <limits.h>
47
48 /************************ P*M reader *****************************/
49
50 static int ReadNumber( RLByteStream& strm, int maxdigits )
51 {
52     int code;
53     int val = 0;
54     int digits = 0;
55
56     code = strm.GetByte();
57
58     if( !isdigit(code))
59     {
60         do
61         {
62             while( isspace(code))
63                 code = strm.GetByte();
64
65             if( code == '#' )
66             {
67                 do
68                 {
69                     code = strm.GetByte();
70                 }
71                 while( code != '\n' && code != '\r' );
72             }
73
74             code = strm.GetByte();
75         }
76         while( !isdigit( code ));
77     }
78
79     do
80     {
81         val = val*10 + code - '0';
82         if( ++digits >= maxdigits ) break;
83         code = strm.GetByte();
84     }
85     while( isdigit(code));
86
87     return val;
88 }
89
90
91 GrFmtPXMReader::GrFmtPXMReader()
92 {
93     m_sign_len = 3;
94     m_signature ="";
95     m_description = "Portable image format (*.pbm;*.pgm;*.ppm)";
96     m_offset = -1;
97 }
98
99
100 bool  GrFmtPXMReader::CheckFormat( const char* signature )
101 {
102     return strlen(signature) >= 3 && signature[0] == 'P' &&
103            '1' <= signature[1] && signature[1] <= '6' &&
104            isspace(signature[2]);
105 }
106
107
108 int  GrFmtPXMReader::GetColor()
109 {
110     return m_bpp > 8 ? 1 : 0;
111 }
112
113
114 void  GrFmtPXMReader::Close()
115 {
116     m_strm.Close();
117 }
118
119
120 bool  GrFmtPXMReader::ReadHeader()
121 {
122     bool result = false;
123     
124     assert( strlen(m_filename) != 0 );
125     if( !m_strm.Open( m_filename )) return false;
126
127     try
128     {
129         int code = m_strm.GetByte();
130         if( code != 'P' )
131             BAD_HEADER_ERR();
132
133         code = m_strm.GetByte();
134         switch( code )
135         {
136         case '1': case '4': m_bpp = 1; break;
137         case '2': case '5': m_bpp = 8; break;
138         case '3': case '6': m_bpp = 24; break;
139         default: BAD_HEADER_ERR();
140         }
141         
142         m_binary = code >= '4';
143
144         m_width = ReadNumber( m_strm, INT_MAX );
145         m_height = ReadNumber( m_strm, INT_MAX );
146         
147         m_maxval = m_bpp == 1 ? 1 : ReadNumber( m_strm, INT_MAX );
148
149         if( m_maxval > 255 ) m_binary = false;
150
151         if( m_width > 0 && m_height > 0 && m_maxval > 0 && m_maxval < (1 << 16)) 
152         {
153             m_offset = m_strm.GetPos();
154             result = true;
155         }
156     }
157     catch( int )
158     {
159     }
160
161     if( !result )
162     {
163         m_offset = -1;
164         m_width = m_height = -1;
165         m_strm.Close();
166     }
167     return result;
168 }
169
170
171 bool  GrFmtPXMReader::ReadData( uchar* data, int step, int color )
172 {
173     const  int buffer_size = 1 << 12;
174     uchar  buffer[buffer_size];
175     uchar  pal_buffer[buffer_size];
176     uchar  bgr_buffer[buffer_size];
177     PaletteEntry palette[256];
178     bool   result = false;
179     uchar* src = buffer;
180     uchar* gray_palette = pal_buffer;
181     uchar* bgr = bgr_buffer;
182     int  src_pitch = (m_width*m_bpp + 7)/8;
183     int  nch = color ? 3 : 1;
184     int  width3 = m_width*nch;
185     int  i, x, 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[width3 + 32];
192
193     if( m_maxval + 1 > buffer_size )
194         gray_palette = new uchar[m_maxval + 1];
195
196     if( m_width*3 + 32 > buffer_size )
197         bgr = new uchar[m_width*3 + 32];
198
199     // create LUT for converting colors
200     for( i = 0; i <= m_maxval; i++ )
201     {
202         gray_palette[i] = (uchar)(i*255/m_maxval);
203     }
204
205     FillGrayPalette( palette, 8 );
206     
207     try
208     {
209         m_strm.SetPos( m_offset );
210         
211         switch( m_bpp )
212         {
213         /************************* 1 BPP ************************/
214         case 1:
215             if( !m_binary )
216             {
217                 for( y = 0; y < m_height; y++, data += step )
218                 {
219                     for( x = 0; x < m_width; x++ )
220                     {
221                         src[x] = gray_palette[ReadNumber( m_strm, 1 ) != 0];
222                     }
223
224                     if( color )
225                         FillColorRow8( data, src, m_width, palette );
226                     else
227                         memcpy( data, src, m_width );
228                 }
229             }
230             else
231             {
232                 for( y = 0; y < m_height; y++, data += step )
233                 {
234                     m_strm.GetBytes( src, src_pitch );
235                     
236                     if( color )
237                         FillColorRow1( data, src, m_width, palette );
238                     else
239                         FillGrayRow1( data, src, m_width, gray_palette );
240                 }
241             }
242             result = true;
243             break;
244
245         /************************* 8 BPP ************************/
246         case 8:
247         case 24:
248             for( y = 0; y < m_height; y++, data += step )
249             {
250                 if( !m_binary )
251                 {
252                     for( x = 0; x < width3; x++ )
253                     {
254                         int code = ReadNumber( m_strm, INT_MAX );
255                         if( (unsigned)code > (unsigned)m_maxval ) code = m_maxval;
256                         src[x] = gray_palette[code];
257                     }
258                 }
259                 else
260                 {
261                     m_strm.GetBytes( src, width3 );
262                 }
263
264                 if( m_bpp == 8 )
265                 {
266                     if( color )
267                         FillColorRow8( src, data, m_width, palette );
268                     else
269                         memcpy( data, src, m_width );
270                 }
271                 else
272                 {
273                     if( color )
274                         CvtRGBToGray( src, data, m_width );
275                     else
276                         CvtRGBToBGR( src, data, m_width );
277                 }
278             }
279             result = true;
280             break;
281         default:
282             assert(0);
283         }
284     }
285     catch( int )
286     {
287     }
288
289     if( src != buffer )
290         delete src; 
291
292     if( bgr != bgr_buffer )
293         delete bgr;
294
295     if( gray_palette != pal_buffer )
296         delete gray_palette;
297
298     return true;
299 }
300