Path: blob/master/modules/imgcodecs/src/grfmt_sunras.cpp
16337 views
/*M///////////////////////////////////////////////////////////////////////////////////////1//2// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.3//4// By downloading, copying, installing or using the software you agree to this license.5// If you do not agree to this license, do not download, install,6// copy or use the software.7//8//9// License Agreement10// For Open Source Computer Vision Library11//12// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.13// Copyright (C) 2009, Willow Garage Inc., 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 documentation24// and/or other materials provided with the distribution.25//26// * The name of the copyright holders may not be used to endorse or promote products27// derived from this software without specific prior written permission.28//29// This software is provided by the copyright holders and contributors "as is" and30// any express or implied warranties, including, but not limited to, the implied31// 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 damages34// (including, but not limited to, procurement of substitute goods or services;35// loss of use, data, or profits; or business interruption) however caused36// and on any theory of liability, whether in contract, strict liability,37// or tort (including negligence or otherwise) arising in any way out of38// the use of this software, even if advised of the possibility of such damage.39//40//M*/4142#include "precomp.hpp"43#include "grfmt_sunras.hpp"4445#ifdef HAVE_IMGCODEC_SUNRASTER4647namespace cv48{4950static const char* fmtSignSunRas = "\x59\xA6\x6A\x95";5152/************************ Sun Raster reader *****************************/5354SunRasterDecoder::SunRasterDecoder()55{56m_offset = -1;57m_signature = fmtSignSunRas;58m_bpp = 0;59m_encoding = RAS_STANDARD;60m_maptype = RMT_NONE;61m_maplength = 0;62}636465SunRasterDecoder::~SunRasterDecoder()66{67}6869ImageDecoder SunRasterDecoder::newDecoder() const70{71return makePtr<SunRasterDecoder>();72}7374void SunRasterDecoder::close()75{76m_strm.close();77}787980bool SunRasterDecoder::readHeader()81{82bool result = false;8384if( !m_strm.open( m_filename )) return false;8586CV_TRY87{88m_strm.skip( 4 );89m_width = m_strm.getDWord();90m_height = m_strm.getDWord();91m_bpp = m_strm.getDWord();92int palSize = 3*(1 << m_bpp);9394m_strm.skip( 4 );95m_encoding = (SunRasType)m_strm.getDWord();96m_maptype = (SunRasMapType)m_strm.getDWord();97m_maplength = m_strm.getDWord();9899if( m_width > 0 && m_height > 0 &&100(m_bpp == 1 || m_bpp == 8 || m_bpp == 24 || m_bpp == 32) &&101(m_encoding == RAS_OLD || m_encoding == RAS_STANDARD ||102(m_type == RAS_BYTE_ENCODED && m_bpp == 8) || m_type == RAS_FORMAT_RGB) &&103((m_maptype == RMT_NONE && m_maplength == 0) ||104(m_maptype == RMT_EQUAL_RGB && m_maplength <= palSize && m_maplength > 0 && m_bpp <= 8)))105{106memset( m_palette, 0, sizeof(m_palette));107108if( m_maplength != 0 )109{110uchar buffer[256*3];111112if( m_strm.getBytes( buffer, m_maplength ) == m_maplength )113{114int i;115palSize = m_maplength/3;116117for( i = 0; i < palSize; i++ )118{119m_palette[i].b = buffer[i + 2*palSize];120m_palette[i].g = buffer[i + palSize];121m_palette[i].r = buffer[i];122m_palette[i].a = 0;123}124125m_type = IsColorPalette( m_palette, m_bpp ) ? CV_8UC3 : CV_8UC1;126m_offset = m_strm.getPos();127128CV_Assert(m_offset == 32 + m_maplength);129result = true;130}131}132else133{134m_type = m_bpp > 8 ? CV_8UC3 : CV_8UC1;135136if( CV_MAT_CN(m_type) == 1 )137FillGrayPalette( m_palette, m_bpp );138139m_offset = m_strm.getPos();140141CV_Assert(m_offset == 32 + m_maplength);142result = true;143}144}145}146CV_CATCH_ALL147{148}149150if( !result )151{152m_offset = -1;153m_width = m_height = -1;154m_strm.close();155}156return result;157}158159160bool SunRasterDecoder::readData( Mat& img )161{162bool color = img.channels() > 1;163uchar* data = img.ptr();164size_t step = img.step;165uchar gray_palette[256] = {0};166bool result = false;167int src_pitch = ((m_width*m_bpp + 7)/8 + 1) & -2;168int nch = color ? 3 : 1;169int width3 = m_width*nch;170int y;171172if( m_offset < 0 || !m_strm.isOpened())173return false;174175AutoBuffer<uchar> _src(src_pitch + 32);176uchar* src = _src.data();177178if( !color && m_maptype == RMT_EQUAL_RGB )179CvtPaletteToGray( m_palette, gray_palette, 1 << m_bpp );180181CV_TRY182{183m_strm.setPos( m_offset );184185switch( m_bpp )186{187/************************* 1 BPP ************************/188case 1:189if( m_type != RAS_BYTE_ENCODED )190{191for( y = 0; y < m_height; y++, data += step )192{193m_strm.getBytes( src, src_pitch );194if( color )195FillColorRow1( data, src, m_width, m_palette );196else197FillGrayRow1( data, src, m_width, gray_palette );198}199result = true;200}201else202{203uchar* line_end = src + (m_width*m_bpp + 7)/8;204uchar* tsrc = src;205y = 0;206207for(;;)208{209int max_count = (int)(line_end - tsrc);210int code = 0, len = 0, len1 = 0;211212do213{214code = m_strm.getByte();215if( code == 0x80 )216{217len = m_strm.getByte();218if( len != 0 ) break;219}220tsrc[len1] = (uchar)code;221}222while( ++len1 < max_count );223224tsrc += len1;225226if( len > 0 ) // encoded mode227{228++len;229code = m_strm.getByte();230if( len > line_end - tsrc )231{232CV_Error(Error::StsInternal, "");233goto bad_decoding_1bpp;234}235236memset( tsrc, code, len );237tsrc += len;238}239240if( tsrc >= line_end )241{242tsrc = src;243if( color )244FillColorRow1( data, src, m_width, m_palette );245else246FillGrayRow1( data, src, m_width, gray_palette );247data += step;248if( ++y >= m_height ) break;249}250}251result = true;252bad_decoding_1bpp:253;254}255break;256/************************* 8 BPP ************************/257case 8:258if( m_type != RAS_BYTE_ENCODED )259{260for( y = 0; y < m_height; y++, data += step )261{262m_strm.getBytes( src, src_pitch );263if( color )264FillColorRow8( data, src, m_width, m_palette );265else266FillGrayRow8( data, src, m_width, gray_palette );267}268result = true;269}270else // RLE-encoded271{272uchar* line_end = data + width3;273y = 0;274275for(;;)276{277int max_count = (int)(line_end - data);278int code = 0, len = 0, len1;279uchar* tsrc = src;280281do282{283code = m_strm.getByte();284if( code == 0x80 )285{286len = m_strm.getByte();287if( len != 0 ) break;288}289*tsrc++ = (uchar)code;290}291while( (max_count -= nch) > 0 );292293len1 = (int)(tsrc - src);294295if( len1 > 0 )296{297if( color )298FillColorRow8( data, src, len1, m_palette );299else300FillGrayRow8( data, src, len1, gray_palette );301data += len1*nch;302}303304if( len > 0 ) // encoded mode305{306len = (len + 1)*nch;307code = m_strm.getByte();308309if( color )310data = FillUniColor( data, line_end, validateToInt(step), width3,311y, m_height, len,312m_palette[code] );313else314data = FillUniGray( data, line_end, validateToInt(step), width3,315y, m_height, len,316gray_palette[code] );317if( y >= m_height )318break;319}320321if( data == line_end )322{323if( m_strm.getByte() != 0 )324goto bad_decoding_end;325line_end += step;326data = line_end - width3;327if( ++y >= m_height ) break;328}329}330331result = true;332bad_decoding_end:333;334}335break;336/************************* 24 BPP ************************/337case 24:338for( y = 0; y < m_height; y++, data += step )339{340m_strm.getBytes(src, src_pitch );341342if( color )343{344if( m_type == RAS_FORMAT_RGB )345icvCvt_RGB2BGR_8u_C3R(src, 0, data, 0, cvSize(m_width,1) );346else347memcpy(data, src, std::min(step, (size_t)src_pitch));348}349else350{351icvCvt_BGR2Gray_8u_C3C1R(src, 0, data, 0, cvSize(m_width,1),352m_type == RAS_FORMAT_RGB ? 2 : 0 );353}354}355result = true;356break;357/************************* 32 BPP ************************/358case 32:359for( y = 0; y < m_height; y++, data += step )360{361/* hack: a0 b0 g0 r0 a1 b1 g1 r1 ... are written to src + 3,362so when we look at src + 4, we see b0 g0 r0 x b1 g1 g1 x ... */363m_strm.getBytes( src + 3, src_pitch );364365if( color )366icvCvt_BGRA2BGR_8u_C4C3R( src + 4, 0, data, 0, cvSize(m_width,1),367m_type == RAS_FORMAT_RGB ? 2 : 0 );368else369icvCvt_BGRA2Gray_8u_C4C1R( src + 4, 0, data, 0, cvSize(m_width,1),370m_type == RAS_FORMAT_RGB ? 2 : 0 );371}372result = true;373break;374default:375CV_Error(Error::StsInternal, "");376}377}378CV_CATCH_ALL379{380}381382return result;383}384385386//////////////////////////////////////////////////////////////////////////////////////////387388SunRasterEncoder::SunRasterEncoder()389{390m_description = "Sun raster files (*.sr;*.ras)";391}392393394ImageEncoder SunRasterEncoder::newEncoder() const395{396return makePtr<SunRasterEncoder>();397}398399SunRasterEncoder::~SunRasterEncoder()400{401}402403bool SunRasterEncoder::write( const Mat& img, const std::vector<int>& )404{405bool result = false;406int y, width = img.cols, height = img.rows, channels = img.channels();407int fileStep = (width*channels + 1) & -2;408WMByteStream strm;409410if( strm.open(m_filename) )411{412strm.putBytes( fmtSignSunRas, (int)strlen(fmtSignSunRas) );413strm.putDWord( width );414strm.putDWord( height );415strm.putDWord( channels*8 );416strm.putDWord( fileStep*height );417strm.putDWord( RAS_STANDARD );418strm.putDWord( RMT_NONE );419strm.putDWord( 0 );420421for( y = 0; y < height; y++ )422strm.putBytes( img.ptr(y), fileStep );423424strm.close();425result = true;426}427return result;428}429430}431432#endif // HAVE_IMGCODEC_SUNRASTER433434435