Home | History | Annotate | Download | only in src
      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