Home | History | Annotate | Download | only in highgui
      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 "utils.h"
     44 #include "grfmt_pxm.h"
     45 
     46 // P?M filter factory
     47 
     48 GrFmtPxM::GrFmtPxM()
     49 {
     50     m_sign_len = 3;
     51     m_signature = "";
     52     m_description = "Portable image format (*.pbm;*.pgm;*.ppm;*.pxm;*.pnm)";
     53 }
     54 
     55 
     56 GrFmtPxM::~GrFmtPxM()
     57 {
     58 }
     59 
     60 
     61 bool GrFmtPxM::CheckSignature( const char* signature )
     62 {
     63     return signature[0] == 'P' &&
     64            '1' <= signature[1] && signature[1] <= '6' &&
     65            isspace(signature[2]);
     66 }
     67 
     68 
     69 GrFmtReader* GrFmtPxM::NewReader( const char* filename )
     70 {
     71     return new GrFmtPxMReader( filename );
     72 }
     73 
     74 
     75 GrFmtWriter* GrFmtPxM::NewWriter( const char* filename )
     76 {
     77     return new GrFmtPxMWriter( filename );
     78 }
     79 
     80 
     81 ///////////////////////// P?M reader //////////////////////////////
     82 
     83 static int ReadNumber( RLByteStream& strm, int maxdigits )
     84 {
     85     int code;
     86     int val = 0;
     87     int digits = 0;
     88 
     89     code = strm.GetByte();
     90 
     91     if( !isdigit(code))
     92     {
     93         do
     94         {
     95             if( code == '#' )
     96             {
     97                 do
     98                 {
     99                     code = strm.GetByte();
    100                 }
    101                 while( code != '\n' && code != '\r' );
    102             }
    103 
    104             code = strm.GetByte();
    105 
    106             while( isspace(code))
    107                 code = strm.GetByte();
    108         }
    109         while( !isdigit( code ));
    110     }
    111 
    112     do
    113     {
    114         val = val*10 + code - '0';
    115         if( ++digits >= maxdigits ) break;
    116         code = strm.GetByte();
    117     }
    118     while( isdigit(code));
    119 
    120     return val;
    121 }
    122 
    123 
    124 GrFmtPxMReader::GrFmtPxMReader( const char* filename ) : GrFmtReader( filename )
    125 {
    126     m_offset = -1;
    127 }
    128 
    129 
    130 GrFmtPxMReader::~GrFmtPxMReader()
    131 {
    132 }
    133 
    134 
    135 void  GrFmtPxMReader::Close()
    136 {
    137     m_strm.Close();
    138 }
    139 
    140 
    141 bool  GrFmtPxMReader::ReadHeader()
    142 {
    143     bool result = false;
    144 
    145     assert( strlen(m_filename) != 0 );
    146     if( !m_strm.Open( m_filename )) return false;
    147 
    148     if( setjmp( m_strm.JmpBuf()) == 0 )
    149     {
    150         int code = m_strm.GetByte();
    151         if( code != 'P' )
    152             BAD_HEADER_ERR();
    153 
    154         code = m_strm.GetByte();
    155         switch( code )
    156         {
    157         case '1': case '4': m_bpp = 1; break;
    158         case '2': case '5': m_bpp = 8; break;
    159         case '3': case '6': m_bpp = 24; break;
    160         default: BAD_HEADER_ERR();
    161         }
    162 
    163         m_binary = code >= '4';
    164         m_iscolor = m_bpp > 8;
    165 
    166         m_width = ReadNumber( m_strm, INT_MAX );
    167         m_height = ReadNumber( m_strm, INT_MAX );
    168 
    169         m_maxval = m_bpp == 1 ? 1 : ReadNumber( m_strm, INT_MAX );
    170         if( m_maxval > 65535 )
    171             BAD_HEADER_ERR();
    172 
    173         //if( m_maxval > 255 ) m_binary = false; nonsense
    174         if( m_maxval > 255 )
    175             m_bit_depth = 16;
    176 
    177         if( m_width > 0 && m_height > 0 && m_maxval > 0 && m_maxval < (1 << 16))
    178         {
    179             m_offset = m_strm.GetPos();
    180             result = true;
    181         }
    182 bad_header_exit:
    183         ;
    184     }
    185 
    186     if( !result )
    187     {
    188         m_offset = -1;
    189         m_width = m_height = -1;
    190         m_strm.Close();
    191     }
    192     return result;
    193 }
    194 
    195 
    196 bool  GrFmtPxMReader::ReadData( uchar* data, int step, int color )
    197 {
    198     const  int buffer_size = 1 << 12;
    199     uchar  buffer[buffer_size];
    200     uchar  pal_buffer[buffer_size];
    201     PaletteEntry palette[256];
    202     bool   result = false;
    203     uchar* src = buffer;
    204     uchar* gray_palette = pal_buffer;
    205     int  src_pitch = (m_width*m_bpp*m_bit_depth/8 + 7)/8;
    206     int  nch = m_iscolor ? 3 : 1;
    207     int  width3 = m_width*nch;
    208     int  i, x, y;
    209 
    210     if( m_offset < 0 || !m_strm.IsOpened())
    211         return false;
    212 
    213     if( src_pitch+32 > buffer_size )
    214         src = new uchar[width3*m_bit_depth/8 + 32];
    215 
    216     // create LUT for converting colors
    217     if( m_bit_depth == 8 )
    218     {
    219         if( m_maxval + 1 > buffer_size )
    220             gray_palette = new uchar[m_maxval + 1];
    221 
    222         for( i = 0; i <= m_maxval; i++ )
    223         {
    224             gray_palette[i] = (uchar)((i*255/m_maxval)^(m_bpp == 1 ? 255 : 0));
    225         }
    226 
    227         FillGrayPalette( palette, m_bpp==1 ? 1 : 8 , m_bpp == 1 );
    228     }
    229 
    230     if( setjmp( m_strm.JmpBuf()) == 0 )
    231     {
    232         m_strm.SetPos( m_offset );
    233 
    234         switch( m_bpp )
    235         {
    236         ////////////////////////// 1 BPP /////////////////////////
    237         case 1:
    238             if( !m_binary )
    239             {
    240                 for( y = 0; y < m_height; y++, data += step )
    241                 {
    242                     for( x = 0; x < m_width; x++ )
    243                         src[x] = ReadNumber( m_strm, 1 ) != 0;
    244 
    245                     if( color )
    246                         FillColorRow8( data, src, m_width, palette );
    247                     else
    248                         FillGrayRow8( data, src, m_width, gray_palette );
    249                 }
    250             }
    251             else
    252             {
    253                 for( y = 0; y < m_height; y++, data += step )
    254                 {
    255                     m_strm.GetBytes( src, src_pitch );
    256 
    257                     if( color )
    258                         FillColorRow1( data, src, m_width, palette );
    259                     else
    260                         FillGrayRow1( data, src, m_width, gray_palette );
    261                 }
    262             }
    263             result = true;
    264             break;
    265 
    266         ////////////////////////// 8 BPP /////////////////////////
    267         case 8:
    268         case 24:
    269             for( y = 0; y < m_height; y++, data += step )
    270             {
    271                 if( !m_binary )
    272                 {
    273                     for( x = 0; x < width3; x++ )
    274                     {
    275                         int code = ReadNumber( m_strm, INT_MAX );
    276                         if( (unsigned)code > (unsigned)m_maxval ) code = m_maxval;
    277                         if( m_bit_depth == 8 )
    278                             src[x] = gray_palette[code];
    279                         else
    280                             ((ushort *)src)[x] = (ushort)code;
    281                     }
    282                 }
    283                 else
    284                 {
    285                     m_strm.GetBytes( src, src_pitch );
    286                     if( m_bit_depth == 16 && !isBigEndian() )
    287                     {
    288                         for( x = 0; x < width3; x++ )
    289                         {
    290                             uchar v = src[x * 2];
    291                             src[x * 2] = src[x * 2 + 1];
    292                             src[x * 2 + 1] = v;
    293                         }
    294                     }
    295                 }
    296 
    297                 if( !m_native_depth && m_bit_depth == 16 )
    298                 {
    299                     for( x = 0; x < width3; x++ )
    300                     {
    301                         int v = ((ushort *)src)[x];
    302                         src[x] = (uchar)(v >> 8);
    303                     }
    304                 }
    305 
    306                 if( m_bpp == 8 ) // image has one channel
    307                 {
    308                     if( color )
    309                     {
    310                         if( m_bit_depth == 8 || !m_native_depth ) {
    311                             uchar *d = data, *s = src, *end = src + m_width;
    312                             for( ; s < end; d += 3, s++)
    313                                 d[0] = d[1] = d[2] = *s;
    314                         } else {
    315                             ushort *d = (ushort *)data, *s = (ushort *)src, *end = ((ushort *)src) + m_width;
    316                             for( ; s < end; s++, d += 3)
    317                                 d[0] = d[1] = d[2] = *s;
    318                         }
    319                     }
    320                     else if( m_native_depth )
    321                         memcpy( data, src, m_width*m_bit_depth/8 );
    322                     else
    323                         memcpy( data, src, m_width );
    324                 }
    325                 else
    326                 {
    327                     if( color )
    328                     {
    329                         if( m_bit_depth == 8 || !m_native_depth )
    330                             icvCvt_RGB2BGR_8u_C3R( src, 0, data, 0, cvSize(m_width,1) );
    331                         else
    332                             icvCvt_RGB2BGR_16u_C3R( (ushort *)src, 0, (ushort *)data, 0, cvSize(m_width,1) );
    333                     }
    334                     else if( m_bit_depth == 8 || !m_native_depth )
    335                         icvCvt_BGR2Gray_8u_C3C1R( src, 0, data, 0, cvSize(m_width,1), 2 );
    336                     else
    337                         icvCvt_BGR2Gray_16u_C3C1R( (ushort *)src, 0, (ushort *)data, 0, cvSize(m_width,1), 2 );
    338                 }
    339             }
    340             result = true;
    341             break;
    342         default:
    343             assert(0);
    344         }
    345     }
    346 
    347     if( src != buffer )
    348         delete[] src;
    349 
    350     if( gray_palette != pal_buffer )
    351         delete[] gray_palette;
    352 
    353     return result;
    354 }
    355 
    356 
    357 //////////////////////////////////////////////////////////////////////////////////////////
    358 
    359 GrFmtPxMWriter::GrFmtPxMWriter( const char* filename ) : GrFmtWriter( filename )
    360 {
    361 }
    362 
    363 
    364 GrFmtPxMWriter::~GrFmtPxMWriter()
    365 {
    366 }
    367 
    368 
    369 bool  GrFmtPxMWriter::IsFormatSupported( int depth )
    370 {
    371     return depth == IPL_DEPTH_8U || depth == IPL_DEPTH_16U;
    372 }
    373 
    374 
    375 bool  GrFmtPxMWriter::WriteImage( const uchar* data, int step,
    376                                   int width, int height, int depth, int _channels )
    377 {
    378     bool isBinary = true;
    379     bool result = false;
    380 
    381     int  channels = _channels > 1 ? 3 : 1;
    382     int  fileStep = width*channels*(depth/8);
    383     int  x, y;
    384 
    385     assert( data && width > 0 && height > 0 && step >= fileStep );
    386 
    387     if( m_strm.Open( m_filename ) )
    388     {
    389         int  lineLength;
    390         int  bufferSize = 128; // buffer that should fit a header
    391         char* buffer = 0;
    392 
    393         if( isBinary )
    394             lineLength = channels * width * depth / 8;
    395         else
    396             lineLength = (6 * channels + (channels > 1 ? 2 : 0)) * width + 32;
    397 
    398         if( bufferSize < lineLength )
    399             bufferSize = lineLength;
    400 
    401         buffer = new char[bufferSize];
    402         if( !buffer )
    403         {
    404             m_strm.Close();
    405             return false;
    406         }
    407 
    408         // write header;
    409         sprintf( buffer, "P%c\n%d %d\n%d\n",
    410                  '2' + (channels > 1 ? 1 : 0) + (isBinary ? 3 : 0),
    411                  width, height, (1 << depth) - 1 );
    412 
    413         m_strm.PutBytes( buffer, (int)strlen(buffer) );
    414 
    415         for( y = 0; y < height; y++, data += step )
    416         {
    417             if( isBinary )
    418             {
    419                 if( _channels == 3 )
    420                 {
    421                     if( depth == 8 )
    422                         icvCvt_BGR2RGB_8u_C3R( (uchar*)data, 0,
    423                             (uchar*)buffer, 0, cvSize(width,1) );
    424                     else
    425                         icvCvt_BGR2RGB_16u_C3R( (ushort*)data, 0,
    426                             (ushort*)buffer, 0, cvSize(width,1) );
    427                 }
    428 
    429                 // swap endianness if necessary
    430                 if( depth == 16 && !isBigEndian() )
    431                 {
    432                     if( _channels == 1 )
    433                         memcpy( buffer, data, fileStep );
    434                     for( x = 0; x < width*channels*2; x += 2 )
    435                     {
    436                         uchar v = buffer[x];
    437                         buffer[x] = buffer[x + 1];
    438                         buffer[x + 1] = v;
    439                     }
    440                 }
    441                 m_strm.PutBytes( (channels > 1 || depth > 8) ? buffer : (char*)data, fileStep );
    442             }
    443             else
    444             {
    445                 char* ptr = buffer;
    446 
    447                 if( channels > 1 )
    448                 {
    449                     if( depth == 8 )
    450                     {
    451                         for( x = 0; x < width*channels; x += channels )
    452                         {
    453                             sprintf( ptr, "% 4d", data[x + 2] );
    454                             ptr += 4;
    455                             sprintf( ptr, "% 4d", data[x + 1] );
    456                             ptr += 4;
    457                             sprintf( ptr, "% 4d", data[x] );
    458                             ptr += 4;
    459                             *ptr++ = ' ';
    460                             *ptr++ = ' ';
    461                         }
    462                     }
    463                     else
    464                     {
    465                         for( x = 0; x < width*channels; x += channels )
    466                         {
    467                             sprintf( ptr, "% 6d", ((ushort *)data)[x + 2] );
    468                             ptr += 6;
    469                             sprintf( ptr, "% 6d", ((ushort *)data)[x + 1] );
    470                             ptr += 6;
    471                             sprintf( ptr, "% 6d", ((ushort *)data)[x] );
    472                             ptr += 6;
    473                             *ptr++ = ' ';
    474                             *ptr++ = ' ';
    475                         }
    476                     }
    477                 }
    478                 else
    479                 {
    480                     if( depth == 8 )
    481                     {
    482                         for( x = 0; x < width; x++ )
    483                         {
    484                             sprintf( ptr, "% 4d", data[x] );
    485                             ptr += 4;
    486                         }
    487                     }
    488                     else
    489                     {
    490                         for( x = 0; x < width; x++ )
    491                         {
    492                             sprintf( ptr, "% 6d", ((ushort *)data)[x] );
    493                             ptr += 6;
    494                         }
    495                     }
    496                 }
    497 
    498                 *ptr++ = '\n';
    499 
    500                 m_strm.PutBytes( buffer, (int)(ptr - buffer) );
    501             }
    502         }
    503         delete[] buffer;
    504         m_strm.Close();
    505         result = true;
    506     }
    507 
    508     return result;
    509 }
    510 
    511