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 namespace cv 47 { 48 49 static const char* fmtSignSunRas = "\x59\xA6\x6A\x95"; 50 51 /************************ Sun Raster reader *****************************/ 52 53 SunRasterDecoder::SunRasterDecoder() 54 { 55 m_offset = -1; 56 m_signature = fmtSignSunRas; 57 } 58 59 60 SunRasterDecoder::~SunRasterDecoder() 61 { 62 } 63 64 ImageDecoder SunRasterDecoder::newDecoder() const 65 { 66 return makePtr<SunRasterDecoder>(); 67 } 68 69 void SunRasterDecoder::close() 70 { 71 m_strm.close(); 72 } 73 74 75 bool SunRasterDecoder::readHeader() 76 { 77 bool result = false; 78 79 if( !m_strm.open( m_filename )) return false; 80 81 try 82 { 83 m_strm.skip( 4 ); 84 m_width = m_strm.getDWord(); 85 m_height = m_strm.getDWord(); 86 m_bpp = m_strm.getDWord(); 87 int palSize = 3*(1 << m_bpp); 88 89 m_strm.skip( 4 ); 90 m_encoding = (SunRasType)m_strm.getDWord(); 91 m_maptype = (SunRasMapType)m_strm.getDWord(); 92 m_maplength = m_strm.getDWord(); 93 94 if( m_width > 0 && m_height > 0 && 95 (m_bpp == 1 || m_bpp == 8 || m_bpp == 24 || m_bpp == 32) && 96 (m_encoding == RAS_OLD || m_encoding == RAS_STANDARD || 97 (m_type == RAS_BYTE_ENCODED && m_bpp == 8) || m_type == RAS_FORMAT_RGB) && 98 ((m_maptype == RMT_NONE && m_maplength == 0) || 99 (m_maptype == RMT_EQUAL_RGB && m_maplength <= palSize && m_bpp <= 8))) 100 { 101 memset( m_palette, 0, sizeof(m_palette)); 102 103 if( m_maplength != 0 ) 104 { 105 uchar buffer[256*3]; 106 107 if( m_strm.getBytes( buffer, m_maplength ) == m_maplength ) 108 { 109 int i; 110 palSize = m_maplength/3; 111 112 for( i = 0; i < palSize; i++ ) 113 { 114 m_palette[i].b = buffer[i + 2*palSize]; 115 m_palette[i].g = buffer[i + palSize]; 116 m_palette[i].r = buffer[i]; 117 m_palette[i].a = 0; 118 } 119 120 m_type = IsColorPalette( m_palette, m_bpp ) ? CV_8UC3 : CV_8UC1; 121 m_offset = m_strm.getPos(); 122 123 assert( m_offset == 32 + m_maplength ); 124 result = true; 125 } 126 } 127 else 128 { 129 m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1; 130 131 if( CV_MAT_CN(m_type) == 1 ) 132 FillGrayPalette( m_palette, m_bpp ); 133 134 m_offset = m_strm.getPos(); 135 136 assert( m_offset == 32 + m_maplength ); 137 result = true; 138 } 139 } 140 } 141 catch(...) 142 { 143 } 144 145 if( !result ) 146 { 147 m_offset = -1; 148 m_width = m_height = -1; 149 m_strm.close(); 150 } 151 return result; 152 } 153 154 155 bool SunRasterDecoder::readData( Mat& img ) 156 { 157 int color = img.channels() > 1; 158 uchar* data = img.ptr(); 159 int step = (int)img.step; 160 uchar gray_palette[256]; 161 bool result = false; 162 int src_pitch = ((m_width*m_bpp + 7)/8 + 1) & -2; 163 int nch = color ? 3 : 1; 164 int width3 = m_width*nch; 165 int y; 166 167 if( m_offset < 0 || !m_strm.isOpened()) 168 return false; 169 170 AutoBuffer<uchar> _src(src_pitch + 32); 171 uchar* src = _src; 172 AutoBuffer<uchar> _bgr(m_width*3 + 32); 173 uchar* bgr = _bgr; 174 175 if( !color && m_maptype == RMT_EQUAL_RGB ) 176 CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp ); 177 178 try 179 { 180 m_strm.setPos( m_offset ); 181 182 switch( m_bpp ) 183 { 184 /************************* 1 BPP ************************/ 185 case 1: 186 if( m_type != RAS_BYTE_ENCODED ) 187 { 188 for( y = 0; y < m_height; y++, data += step ) 189 { 190 m_strm.getBytes( src, src_pitch ); 191 if( color ) 192 FillColorRow1( data, src, m_width, m_palette ); 193 else 194 FillGrayRow1( data, src, m_width, gray_palette ); 195 } 196 result = true; 197 } 198 else 199 { 200 uchar* line_end = src + (m_width*m_bpp + 7)/8; 201 uchar* tsrc = src; 202 y = 0; 203 204 for(;;) 205 { 206 int max_count = (int)(line_end - tsrc); 207 int code = 0, len = 0, len1 = 0; 208 209 do 210 { 211 code = m_strm.getByte(); 212 if( code == 0x80 ) 213 { 214 len = m_strm.getByte(); 215 if( len != 0 ) break; 216 } 217 tsrc[len1] = (uchar)code; 218 } 219 while( ++len1 < max_count ); 220 221 tsrc += len1; 222 223 if( len > 0 ) // encoded mode 224 { 225 ++len; 226 code = m_strm.getByte(); 227 if( len > line_end - tsrc ) 228 { 229 assert(0); 230 goto bad_decoding_1bpp; 231 } 232 233 memset( tsrc, code, len ); 234 tsrc += len; 235 } 236 237 if( tsrc >= line_end ) 238 { 239 tsrc = src; 240 if( color ) 241 FillColorRow1( data, src, m_width, m_palette ); 242 else 243 FillGrayRow1( data, src, m_width, gray_palette ); 244 data += step; 245 if( ++y >= m_height ) break; 246 } 247 } 248 result = true; 249 bad_decoding_1bpp: 250 ; 251 } 252 break; 253 /************************* 8 BPP ************************/ 254 case 8: 255 if( m_type != RAS_BYTE_ENCODED ) 256 { 257 for( y = 0; y < m_height; y++, data += step ) 258 { 259 m_strm.getBytes( src, src_pitch ); 260 if( color ) 261 FillColorRow8( data, src, m_width, m_palette ); 262 else 263 FillGrayRow8( data, src, m_width, gray_palette ); 264 } 265 result = true; 266 } 267 else // RLE-encoded 268 { 269 uchar* line_end = data + width3; 270 y = 0; 271 272 for(;;) 273 { 274 int max_count = (int)(line_end - data); 275 int code = 0, len = 0, len1; 276 uchar* tsrc = src; 277 278 do 279 { 280 code = m_strm.getByte(); 281 if( code == 0x80 ) 282 { 283 len = m_strm.getByte(); 284 if( len != 0 ) break; 285 } 286 *tsrc++ = (uchar)code; 287 } 288 while( (max_count -= nch) > 0 ); 289 290 len1 = (int)(tsrc - src); 291 292 if( len1 > 0 ) 293 { 294 if( color ) 295 FillColorRow8( data, src, len1, m_palette ); 296 else 297 FillGrayRow8( data, src, len1, gray_palette ); 298 data += len1*nch; 299 } 300 301 if( len > 0 ) // encoded mode 302 { 303 len = (len + 1)*nch; 304 code = m_strm.getByte(); 305 306 if( color ) 307 data = FillUniColor( data, line_end, step, width3, 308 y, m_height, len, 309 m_palette[code] ); 310 else 311 data = FillUniGray( data, line_end, step, width3, 312 y, m_height, len, 313 gray_palette[code] ); 314 if( y >= m_height ) 315 break; 316 } 317 318 if( data == line_end ) 319 { 320 if( m_strm.getByte() != 0 ) 321 goto bad_decoding_end; 322 line_end += step; 323 data = line_end - width3; 324 if( ++y >= m_height ) break; 325 } 326 } 327 328 result = true; 329 bad_decoding_end: 330 ; 331 } 332 break; 333 /************************* 24 BPP ************************/ 334 case 24: 335 for( y = 0; y < m_height; y++, data += step ) 336 { 337 m_strm.getBytes( color ? data : bgr, src_pitch ); 338 339 if( color ) 340 { 341 if( m_type == RAS_FORMAT_RGB ) 342 icvCvt_RGB2BGR_8u_C3R( data, 0, data, 0, cvSize(m_width,1) ); 343 } 344 else 345 { 346 icvCvt_BGR2Gray_8u_C3C1R( bgr, 0, data, 0, cvSize(m_width,1), 347 m_type == RAS_FORMAT_RGB ? 2 : 0 ); 348 } 349 } 350 result = true; 351 break; 352 /************************* 32 BPP ************************/ 353 case 32: 354 for( y = 0; y < m_height; y++, data += step ) 355 { 356 /* hack: a0 b0 g0 r0 a1 b1 g1 r1 ... are written to src + 3, 357 so when we look at src + 4, we see b0 g0 r0 x b1 g1 g1 x ... */ 358 m_strm.getBytes( src + 3, src_pitch ); 359 360 if( color ) 361 icvCvt_BGRA2BGR_8u_C4C3R( src + 4, 0, data, 0, cvSize(m_width,1), 362 m_type == RAS_FORMAT_RGB ? 2 : 0 ); 363 else 364 icvCvt_BGRA2Gray_8u_C4C1R( src + 4, 0, data, 0, cvSize(m_width,1), 365 m_type == RAS_FORMAT_RGB ? 2 : 0 ); 366 } 367 result = true; 368 break; 369 default: 370 assert(0); 371 } 372 } 373 catch( ... ) 374 { 375 } 376 377 return result; 378 } 379 380 381 ////////////////////////////////////////////////////////////////////////////////////////// 382 383 SunRasterEncoder::SunRasterEncoder() 384 { 385 m_description = "Sun raster files (*.sr;*.ras)"; 386 } 387 388 389 ImageEncoder SunRasterEncoder::newEncoder() const 390 { 391 return makePtr<SunRasterEncoder>(); 392 } 393 394 SunRasterEncoder::~SunRasterEncoder() 395 { 396 } 397 398 bool SunRasterEncoder::write( const Mat& img, const std::vector<int>& ) 399 { 400 bool result = false; 401 int y, width = img.cols, height = img.rows, channels = img.channels(); 402 int fileStep = (width*channels + 1) & -2; 403 WMByteStream strm; 404 405 if( strm.open(m_filename) ) 406 { 407 strm.putBytes( fmtSignSunRas, (int)strlen(fmtSignSunRas) ); 408 strm.putDWord( width ); 409 strm.putDWord( height ); 410 strm.putDWord( channels*8 ); 411 strm.putDWord( fileStep*height ); 412 strm.putDWord( RAS_STANDARD ); 413 strm.putDWord( RMT_NONE ); 414 strm.putDWord( 0 ); 415 416 for( y = 0; y < height; y++ ) 417 strm.putBytes( img.ptr(y), fileStep ); 418 419 strm.close(); 420 result = true; 421 } 422 return result; 423 } 424 425 } 426