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 45static const char* fmtSignSunRas = "\x59\xA6\x6A\x95"; 46 47// Sun Raster filter factory 48 49GrFmtSunRaster::GrFmtSunRaster() 50{ 51 m_sign_len = 4; 52 m_signature = fmtSignSunRas; 53 m_description = "Sun raster files (*.sr;*.ras)"; 54} 55 56 57GrFmtSunRaster::~GrFmtSunRaster() 58{ 59} 60 61 62GrFmtReader* GrFmtSunRaster::NewReader( const char* filename ) 63{ 64 return new GrFmtSunRasterReader( filename ); 65} 66 67 68GrFmtWriter* GrFmtSunRaster::NewWriter( const char* filename ) 69{ 70 return new GrFmtSunRasterWriter( filename ); 71} 72 73 74/************************ Sun Raster reader *****************************/ 75 76GrFmtSunRasterReader::GrFmtSunRasterReader( const char* filename ) : GrFmtReader( filename ) 77{ 78 m_offset = -1; 79} 80 81 82GrFmtSunRasterReader::~GrFmtSunRasterReader() 83{ 84} 85 86 87void GrFmtSunRasterReader::Close() 88{ 89 m_strm.Close(); 90} 91 92 93bool 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 173bool 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; 270bad_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; 350bad_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 404GrFmtSunRasterWriter::GrFmtSunRasterWriter( const char* filename ) : GrFmtWriter( filename ) 405{ 406} 407 408 409GrFmtSunRasterWriter::~GrFmtSunRasterWriter() 410{ 411} 412 413 414bool 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 443