| /*M/////////////////////////////////////////////////////////////////////////////////////// |
| // |
| // IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. |
| // |
| // By downloading, copying, installing or using the software you agree to this license. |
| // If you do not agree to this license, do not download, install, |
| // copy or use the software. |
| // |
| // |
| // Intel License Agreement |
| // For Open Source Computer Vision Library |
| // |
| // Copyright (C) 2000, Intel Corporation, all rights reserved. |
| // Third party copyrights are property of their respective owners. |
| // |
| // Redistribution and use in source and binary forms, with or without modification, |
| // are permitted provided that the following conditions are met: |
| // |
| // * Redistribution's of source code must retain the above copyright notice, |
| // this list of conditions and the following disclaimer. |
| // |
| // * Redistribution's in binary form must reproduce the above copyright notice, |
| // this list of conditions and the following disclaimer in the documentation |
| // and/or other materials provided with the distribution. |
| // |
| // * The name of Intel Corporation may not be used to endorse or promote products |
| // derived from this software without specific prior written permission. |
| // |
| // This software is provided by the copyright holders and contributors "as is" and |
| // any express or implied warranties, including, but not limited to, the implied |
| // warranties of merchantability and fitness for a particular purpose are disclaimed. |
| // In no event shall the Intel Corporation or contributors be liable for any direct, |
| // indirect, incidental, special, exemplary, or consequential damages |
| // (including, but not limited to, procurement of substitute goods or services; |
| // loss of use, data, or profits; or business interruption) however caused |
| // and on any theory of liability, whether in contract, strict liability, |
| // or tort (including negligence or otherwise) arising in any way out of |
| // the use of this software, even if advised of the possibility of such damage. |
| // |
| //M*/ |
| |
| #include "_highgui.h" |
| #include "grfmt_sunras.h" |
| |
| static const char* fmtSignSunRas = "\x59\xA6\x6A\x95"; |
| |
| // Sun Raster filter factory |
| |
| GrFmtSunRaster::GrFmtSunRaster() |
| { |
| m_sign_len = 4; |
| m_signature = fmtSignSunRas; |
| m_description = "Sun raster files (*.sr;*.ras)"; |
| } |
| |
| |
| GrFmtSunRaster::~GrFmtSunRaster() |
| { |
| } |
| |
| |
| GrFmtReader* GrFmtSunRaster::NewReader( const char* filename ) |
| { |
| return new GrFmtSunRasterReader( filename ); |
| } |
| |
| |
| GrFmtWriter* GrFmtSunRaster::NewWriter( const char* filename ) |
| { |
| return new GrFmtSunRasterWriter( filename ); |
| } |
| |
| |
| /************************ Sun Raster reader *****************************/ |
| |
| GrFmtSunRasterReader::GrFmtSunRasterReader( const char* filename ) : GrFmtReader( filename ) |
| { |
| m_offset = -1; |
| } |
| |
| |
| GrFmtSunRasterReader::~GrFmtSunRasterReader() |
| { |
| } |
| |
| |
| void GrFmtSunRasterReader::Close() |
| { |
| m_strm.Close(); |
| } |
| |
| |
| bool GrFmtSunRasterReader::ReadHeader() |
| { |
| bool result = false; |
| |
| assert( strlen(m_filename) != 0 ); |
| if( !m_strm.Open( m_filename )) return false; |
| |
| if( setjmp( m_strm.JmpBuf()) == 0 ) |
| { |
| m_strm.Skip( 4 ); |
| m_width = m_strm.GetDWord(); |
| m_height = m_strm.GetDWord(); |
| m_bpp = m_strm.GetDWord(); |
| int palSize = 3*(1 << m_bpp); |
| |
| m_strm.Skip( 4 ); |
| m_type = (SunRasType)m_strm.GetDWord(); |
| m_maptype = (SunRasMapType)m_strm.GetDWord(); |
| m_maplength = m_strm.GetDWord(); |
| |
| if( m_width > 0 && m_height > 0 && |
| (m_bpp == 1 || m_bpp == 8 || m_bpp == 24 || m_bpp == 32) && |
| (m_type == RAS_OLD || m_type == RAS_STANDARD || |
| (m_type == RAS_BYTE_ENCODED && m_bpp == 8) || m_type == RAS_FORMAT_RGB) && |
| (m_maptype == RMT_NONE && m_maplength == 0 || |
| m_maptype == RMT_EQUAL_RGB && m_maplength <= palSize && m_bpp <= 8)) |
| { |
| memset( m_palette, 0, sizeof(m_palette)); |
| |
| if( m_maplength != 0 ) |
| { |
| int readed; |
| uchar buffer[256*3]; |
| |
| m_strm.GetBytes( buffer, m_maplength, &readed ); |
| if( readed == m_maplength ) |
| { |
| int i; |
| palSize = m_maplength/3; |
| |
| for( i = 0; i < palSize; i++ ) |
| { |
| m_palette[i].b = buffer[i + 2*palSize]; |
| m_palette[i].g = buffer[i + palSize]; |
| m_palette[i].r = buffer[i]; |
| m_palette[i].a = 0; |
| } |
| |
| m_iscolor = IsColorPalette( m_palette, m_bpp ); |
| m_offset = m_strm.GetPos(); |
| |
| assert( m_offset == 32 + m_maplength ); |
| result = true; |
| } |
| } |
| else |
| { |
| m_iscolor = m_bpp > 8; |
| |
| if( !m_iscolor ) |
| FillGrayPalette( m_palette, m_bpp ); |
| |
| m_offset = m_strm.GetPos(); |
| |
| assert( m_offset == 32 + m_maplength ); |
| result = true; |
| } |
| } |
| } |
| |
| if( !result ) |
| { |
| m_offset = -1; |
| m_width = m_height = -1; |
| m_strm.Close(); |
| } |
| return result; |
| } |
| |
| |
| bool GrFmtSunRasterReader::ReadData( uchar* data, int step, int color ) |
| { |
| const int buffer_size = 1 << 12; |
| uchar buffer[buffer_size]; |
| uchar bgr_buffer[buffer_size]; |
| uchar gray_palette[256]; |
| bool result = false; |
| uchar* src = buffer; |
| uchar* bgr = bgr_buffer; |
| int src_pitch = ((m_width*m_bpp + 7)/8 + 1) & -2; |
| int nch = color ? 3 : 1; |
| int width3 = m_width*nch; |
| int y; |
| |
| if( m_offset < 0 || !m_strm.IsOpened()) |
| return false; |
| |
| if( src_pitch+32 > buffer_size ) |
| src = new uchar[src_pitch+32]; |
| |
| if( m_width*3 + 32 > buffer_size ) |
| bgr = new uchar[m_width*3 + 32]; |
| |
| if( !color && m_maptype == RMT_EQUAL_RGB ) |
| CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp ); |
| |
| if( setjmp( m_strm.JmpBuf()) == 0 ) |
| { |
| m_strm.SetPos( m_offset ); |
| |
| switch( m_bpp ) |
| { |
| /************************* 1 BPP ************************/ |
| case 1: |
| if( m_type != RAS_BYTE_ENCODED ) |
| { |
| for( y = 0; y < m_height; y++, data += step ) |
| { |
| m_strm.GetBytes( src, src_pitch ); |
| if( color ) |
| FillColorRow1( data, src, m_width, m_palette ); |
| else |
| FillGrayRow1( data, src, m_width, gray_palette ); |
| } |
| result = true; |
| } |
| else |
| { |
| uchar* line_end = src + (m_width*m_bpp + 7)/8; |
| uchar* tsrc = src; |
| y = 0; |
| |
| for(;;) |
| { |
| int max_count = (int)(line_end - tsrc); |
| int code = 0, len = 0, len1 = 0; |
| |
| do |
| { |
| code = m_strm.GetByte(); |
| if( code == 0x80 ) |
| { |
| len = m_strm.GetByte(); |
| if( len != 0 ) break; |
| } |
| tsrc[len1] = (uchar)code; |
| } |
| while( ++len1 < max_count ); |
| |
| tsrc += len1; |
| |
| if( len > 0 ) // encoded mode |
| { |
| ++len; |
| code = m_strm.GetByte(); |
| if( len > line_end - tsrc ) |
| { |
| assert(0); |
| goto bad_decoding_1bpp; |
| } |
| |
| memset( tsrc, code, len ); |
| tsrc += len; |
| } |
| |
| if( tsrc >= line_end ) |
| { |
| tsrc = src; |
| if( color ) |
| FillColorRow1( data, src, m_width, m_palette ); |
| else |
| FillGrayRow1( data, src, m_width, gray_palette ); |
| data += step; |
| if( ++y >= m_height ) break; |
| } |
| } |
| result = true; |
| bad_decoding_1bpp: |
| ; |
| } |
| break; |
| /************************* 8 BPP ************************/ |
| case 8: |
| if( m_type != RAS_BYTE_ENCODED ) |
| { |
| for( y = 0; y < m_height; y++, data += step ) |
| { |
| m_strm.GetBytes( src, src_pitch ); |
| if( color ) |
| FillColorRow8( data, src, m_width, m_palette ); |
| else |
| FillGrayRow8( data, src, m_width, gray_palette ); |
| } |
| result = true; |
| } |
| else // RLE-encoded |
| { |
| uchar* line_end = data + width3; |
| y = 0; |
| |
| for(;;) |
| { |
| int max_count = (int)(line_end - data); |
| int code = 0, len = 0, len1; |
| uchar* tsrc = src; |
| |
| do |
| { |
| code = m_strm.GetByte(); |
| if( code == 0x80 ) |
| { |
| len = m_strm.GetByte(); |
| if( len != 0 ) break; |
| } |
| *tsrc++ = (uchar)code; |
| } |
| while( (max_count -= nch) > 0 ); |
| |
| len1 = (int)(tsrc - src); |
| |
| if( len1 > 0 ) |
| { |
| if( color ) |
| FillColorRow8( data, src, len1, m_palette ); |
| else |
| FillGrayRow8( data, src, len1, gray_palette ); |
| data += len1*nch; |
| } |
| |
| if( len > 0 ) // encoded mode |
| { |
| len = (len + 1)*nch; |
| code = m_strm.GetByte(); |
| |
| if( color ) |
| data = FillUniColor( data, line_end, step, width3, |
| y, m_height, len, |
| m_palette[code] ); |
| else |
| data = FillUniGray( data, line_end, step, width3, |
| y, m_height, len, |
| gray_palette[code] ); |
| if( y >= m_height ) |
| break; |
| } |
| |
| if( data == line_end ) |
| { |
| if( m_strm.GetByte() != 0 ) |
| goto bad_decoding_end; |
| line_end += step; |
| data = line_end - width3; |
| if( ++y >= m_height ) break; |
| } |
| } |
| |
| result = true; |
| bad_decoding_end: |
| ; |
| } |
| break; |
| /************************* 24 BPP ************************/ |
| case 24: |
| for( y = 0; y < m_height; y++, data += step ) |
| { |
| m_strm.GetBytes( color ? data : bgr, src_pitch ); |
| |
| if( color ) |
| { |
| if( m_type == RAS_FORMAT_RGB ) |
| icvCvt_RGB2BGR_8u_C3R( data, 0, data, 0, cvSize(m_width,1) ); |
| } |
| else |
| { |
| icvCvt_BGR2Gray_8u_C3C1R( bgr, 0, data, 0, cvSize(m_width,1), |
| m_type == RAS_FORMAT_RGB ? 2 : 0 ); |
| } |
| } |
| result = true; |
| break; |
| /************************* 32 BPP ************************/ |
| case 32: |
| for( y = 0; y < m_height; y++, data += step ) |
| { |
| /* hack: a0 b0 g0 r0 a1 b1 g1 r1 ... are written to src + 3, |
| so when we look at src + 4, we see b0 g0 r0 x b1 g1 g1 x ... */ |
| m_strm.GetBytes( src + 3, src_pitch ); |
| |
| if( color ) |
| icvCvt_BGRA2BGR_8u_C4C3R( src + 4, 0, data, 0, cvSize(m_width,1), |
| m_type == RAS_FORMAT_RGB ? 2 : 0 ); |
| else |
| icvCvt_BGRA2Gray_8u_C4C1R( src + 4, 0, data, 0, cvSize(m_width,1), |
| m_type == RAS_FORMAT_RGB ? 2 : 0 ); |
| } |
| result = true; |
| break; |
| default: |
| assert(0); |
| } |
| } |
| |
| if( src != buffer ) delete[] src; |
| if( bgr != bgr_buffer ) delete[] bgr; |
| |
| return result; |
| } |
| |
| |
| ////////////////////////////////////////////////////////////////////////////////////////// |
| |
| GrFmtSunRasterWriter::GrFmtSunRasterWriter( const char* filename ) : GrFmtWriter( filename ) |
| { |
| } |
| |
| |
| GrFmtSunRasterWriter::~GrFmtSunRasterWriter() |
| { |
| } |
| |
| |
| bool GrFmtSunRasterWriter::WriteImage( const uchar* data, int step, |
| int width, int height, int /*depth*/, int channels ) |
| { |
| bool result = false; |
| int fileStep = (width*channels + 1) & -2; |
| int y; |
| |
| assert( data && width > 0 && height > 0 && step >= fileStep); |
| |
| if( m_strm.Open( m_filename ) ) |
| { |
| m_strm.PutBytes( fmtSignSunRas, (int)strlen(fmtSignSunRas) ); |
| m_strm.PutDWord( width ); |
| m_strm.PutDWord( height ); |
| m_strm.PutDWord( channels*8 ); |
| m_strm.PutDWord( fileStep*height ); |
| m_strm.PutDWord( RAS_STANDARD ); |
| m_strm.PutDWord( RMT_NONE ); |
| m_strm.PutDWord( 0 ); |
| |
| for( y = 0; y < height; y++, data += step ) |
| m_strm.PutBytes( data, fileStep ); |
| |
| m_strm.Close(); |
| result = true; |
| } |
| return result; |
| } |
| |