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 
     44 #ifdef HAVE_PNG
     45 
     46 /****************************************************************************************\
     47     This part of the file implements PNG codec on base of libpng library,
     48     in particular, this code is based on example.c from libpng
     49     (see otherlibs/_graphics/readme.txt for copyright notice)
     50     and png2bmp sample from libpng distribution (Copyright (C) 1999-2001 MIYASAKA Masaru)
     51 \****************************************************************************************/
     52 
     53 #if defined WIN32 || defined HAVE_PNG_H
     54 #include <png.h>
     55 #else
     56 #include <libpng/png.h>
     57 #endif
     58 #include "grfmt_png.h"
     59 
     60 // PNG Filter Factory
     61 GrFmtPng::GrFmtPng()
     62 {
     63     m_sign_len = 8;
     64     m_signature = "\x89\x50\x4e\x47\xd\xa\x1a\xa";
     65     m_description = "Portable Network Graphics files (*.png)";
     66 }
     67 
     68 
     69 GrFmtPng::~GrFmtPng()
     70 {
     71 }
     72 
     73 
     74 GrFmtReader* GrFmtPng::NewReader( const char* filename )
     75 {
     76     return new GrFmtPngReader( filename );
     77 }
     78 
     79 
     80 GrFmtWriter* GrFmtPng::NewWriter( const char* filename )
     81 {
     82     return new GrFmtPngWriter( filename );
     83 }
     84 
     85 
     86 bool  GrFmtPng::CheckSignature( const char* signature )
     87 {
     88     return png_check_sig( (uchar*)signature, m_sign_len ) != 0;
     89 }
     90 
     91 /////////////////////// GrFmtPngReader ///////////////////
     92 
     93 GrFmtPngReader::GrFmtPngReader( const char* filename ) : GrFmtReader( filename )
     94 {
     95     m_color_type = m_bit_depth = 0;
     96     m_png_ptr = 0;
     97     m_info_ptr = m_end_info = 0;
     98     m_f = 0;
     99 }
    100 
    101 
    102 GrFmtPngReader::~GrFmtPngReader()
    103 {
    104 }
    105 
    106 
    107 void  GrFmtPngReader::Close()
    108 {
    109     if( m_f )
    110     {
    111         fclose( m_f );
    112         m_f = 0;
    113     }
    114 
    115     if( m_png_ptr )
    116     {
    117         png_structp png_ptr = (png_structp)m_png_ptr;
    118         png_infop info_ptr = (png_infop)m_info_ptr;
    119         png_infop end_info = (png_infop)m_end_info;
    120         png_destroy_read_struct( &png_ptr, &info_ptr, &end_info );
    121         m_png_ptr = m_info_ptr = m_end_info = 0;
    122     }
    123     GrFmtReader::Close();
    124 }
    125 
    126 
    127 bool  GrFmtPngReader::ReadHeader()
    128 {
    129     bool result = false;
    130 
    131     Close();
    132 
    133     png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    134 
    135     if( png_ptr )
    136     {
    137         png_infop info_ptr = png_create_info_struct( png_ptr );
    138         png_infop end_info = png_create_info_struct( png_ptr );
    139 
    140         m_png_ptr = png_ptr;
    141         m_info_ptr = info_ptr;
    142         m_end_info = end_info;
    143 
    144         if( info_ptr && end_info )
    145         {
    146             if( setjmp( png_ptr->jmpbuf ) == 0 )
    147             {
    148                 m_f = fopen( m_filename, "rb" );
    149                 if( m_f )
    150                 {
    151                     png_uint_32 width, height;
    152                     int bit_depth, color_type;
    153 
    154                     png_init_io( png_ptr, m_f );
    155                     png_read_info( png_ptr, info_ptr );
    156 
    157                     png_get_IHDR( png_ptr, info_ptr, &width, &height,
    158                                   &bit_depth, &color_type, 0, 0, 0 );
    159 
    160                     m_iscolor = color_type == PNG_COLOR_TYPE_RGB ||
    161                                 color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
    162                                 color_type == PNG_COLOR_TYPE_PALETTE;
    163 
    164                     m_width = (int)width;
    165                     m_height = (int)height;
    166                     m_color_type = color_type;
    167                     m_bit_depth = bit_depth;
    168 
    169                     result = true;
    170                 }
    171             }
    172         }
    173     }
    174 
    175     if( !result )
    176         Close();
    177 
    178     return result;
    179 }
    180 
    181 
    182 bool  GrFmtPngReader::ReadData( uchar* data, int step, int color )
    183 {
    184     bool result = false;
    185     uchar** buffer = 0;
    186 
    187     color = color > 0 || ( m_iscolor && color < 0 );
    188 
    189     if( m_png_ptr && m_info_ptr && m_end_info && m_width && m_height )
    190     {
    191         png_structp png_ptr = (png_structp)m_png_ptr;
    192         png_infop info_ptr = (png_infop)m_info_ptr;
    193         png_infop end_info = (png_infop)m_end_info;
    194 
    195         if( setjmp(png_ptr->jmpbuf) == 0 )
    196         {
    197             int y;
    198 
    199             if( m_bit_depth > 8 && !m_native_depth )
    200                 png_set_strip_16( png_ptr );
    201             else if( !isBigEndian() )
    202                 png_set_swap( png_ptr );
    203 
    204             /* observation: png_read_image() writes 400 bytes beyond
    205              * end of data when reading a 400x118 color png
    206              * "mpplus_sand.png".  OpenCV crashes even with demo
    207              * programs.  Looking at the loaded image I'd say we get 4
    208              * bytes per pixel instead of 3 bytes per pixel.  Test
    209              * indicate that it is a good idea to always ask for
    210              * stripping alpha..  18.11.2004 Axel Walthelm
    211              */
    212             png_set_strip_alpha( png_ptr );
    213 
    214             if( m_color_type == PNG_COLOR_TYPE_PALETTE )
    215                 png_set_palette_to_rgb( png_ptr );
    216 
    217             if( m_color_type == PNG_COLOR_TYPE_GRAY && m_bit_depth < 8 )
    218                 png_set_gray_1_2_4_to_8( png_ptr );
    219 
    220             if( m_iscolor && color )
    221                 png_set_bgr( png_ptr ); // convert RGB to BGR
    222             else if( color )
    223                 png_set_gray_to_rgb( png_ptr ); // Gray->RGB
    224             else
    225                 png_set_rgb_to_gray( png_ptr, 1, -1, -1 ); // RGB->Gray
    226 
    227             png_read_update_info( png_ptr, info_ptr );
    228 
    229             buffer = new uchar*[m_height];
    230 
    231             for( y = 0; y < m_height; y++ )
    232                 buffer[y] = data + y*step;
    233 
    234             png_read_image( png_ptr, buffer );
    235             png_read_end( png_ptr, end_info );
    236 
    237             result = true;
    238         }
    239     }
    240 
    241     Close();
    242     delete[] buffer;
    243 
    244     return result;
    245 }
    246 
    247 
    248 /////////////////////// GrFmtPngWriter ///////////////////
    249 
    250 
    251 GrFmtPngWriter::GrFmtPngWriter( const char* filename ) : GrFmtWriter( filename )
    252 {
    253 }
    254 
    255 
    256 GrFmtPngWriter::~GrFmtPngWriter()
    257 {
    258 }
    259 
    260 
    261 bool  GrFmtPngWriter::IsFormatSupported( int depth )
    262 {
    263     return depth == IPL_DEPTH_8U || depth == IPL_DEPTH_16U;
    264 }
    265 
    266 bool  GrFmtPngWriter::WriteImage( const uchar* data, int step,
    267                                   int width, int height, int depth, int channels )
    268 {
    269     png_structp png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
    270     png_infop info_ptr = 0;
    271     FILE* f = 0;
    272     uchar** buffer = 0;
    273     int y;
    274     bool result = false;
    275 
    276     if( depth != IPL_DEPTH_8U && depth != IPL_DEPTH_16U )
    277         return false;
    278 
    279     if( png_ptr )
    280     {
    281         info_ptr = png_create_info_struct( png_ptr );
    282 
    283         if( info_ptr )
    284         {
    285             if( setjmp( png_ptr->jmpbuf ) == 0 )
    286             {
    287                 f = fopen( m_filename, "wb" );
    288 
    289                 if( f )
    290                 {
    291                     png_init_io( png_ptr, f );
    292 
    293                     png_set_compression_mem_level( png_ptr, MAX_MEM_LEVEL );
    294 
    295                     png_set_IHDR( png_ptr, info_ptr, width, height, depth,
    296                         channels == 1 ? PNG_COLOR_TYPE_GRAY :
    297                         channels == 3 ? PNG_COLOR_TYPE_RGB : PNG_COLOR_TYPE_RGBA,
    298                         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT,
    299                         PNG_FILTER_TYPE_DEFAULT );
    300 
    301                     png_write_info( png_ptr, info_ptr );
    302 
    303                     png_set_bgr( png_ptr );
    304                     if( !isBigEndian() )
    305                         png_set_swap( png_ptr );
    306 
    307                     buffer = new uchar*[height];
    308                     for( y = 0; y < height; y++ )
    309                         buffer[y] = (uchar*)(data + y*step);
    310 
    311                     png_write_image( png_ptr, buffer );
    312                     png_write_end( png_ptr, info_ptr );
    313 
    314                     delete[] buffer;
    315 
    316                     result = true;
    317                 }
    318             }
    319         }
    320     }
    321 
    322     png_destroy_write_struct( &png_ptr, &info_ptr );
    323 
    324     if(f) fclose( f );
    325 
    326     return result;
    327 }
    328 
    329 #endif
    330 
    331 /* End of file. */
    332 
    333 
    334