36 #ifndef __INCLUDE_MIST_PNG__
37 #define __INCLUDE_MIST_PNG__
40 #ifndef __INCLUDE_MIST_H__
45 #ifndef __INCLUDE_MIST_COLOR_H__
46 #include "../config/color.h"
49 #ifndef __INCLUDE_MIST_LIMITS__
50 #include "../limits.h"
66 namespace __png_controller__
68 template <
class T,
class Allocator >
71 typedef _pixel_converter_< T > pixel_converter;
72 typedef typename pixel_converter::color_type color_type;
73 typedef typename array2< T, Allocator >::size_type size_type;
75 static bool read( array2< T, Allocator > &image,
const std::string &filename )
77 FILE *fp = fopen( filename.c_str( ),
"rb" );
84 png_structp png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
85 png_infop info_ptr = png_create_info_struct( png_ptr );
86 png_init_io( png_ptr, fp );
87 png_read_info( png_ptr, info_ptr );
90 png_uint_32 width, height;
91 png_colorp palette = NULL;
92 int bit_depth, color_type, interlace_type, npalette = 0;
94 png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
95 png_get_PLTE( png_ptr, info_ptr, &palette, &npalette );
99 png_set_packing( png_ptr );
103 if( color_type == PNG_COLOR_TYPE_PALETTE )
105 png_set_palette_to_rgb( png_ptr );
109 if( color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8 )
111 png_set_expand_gray_1_2_4_to_8( png_ptr );
115 if( png_get_valid( png_ptr, info_ptr, PNG_INFO_tRNS ) )
117 png_set_tRNS_to_alpha( png_ptr );
120 png_read_update_info( png_ptr, info_ptr );
123 png_get_IHDR( png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
125 image.resize( width, height );
129 if( interlace_type == 0 )
132 png_bytep png_buff = ( png_bytep )malloc( png_get_rowbytes( png_ptr, info_ptr ) );
134 for( size_type j = 0 ; j < ( size_type )height ; j++ )
137 png_read_rows( png_ptr, &png_buff, NULL, 1 );
140 typename array2< T, Allocator >::pointer op = &image( 0, j );
145 case PNG_COLOR_TYPE_GRAY:
146 for( size_type i = 0 ; i < ( size_type )width ; i++ )
148 op[ i ] = pixel_converter::convert_to( png_buff[ i ], png_buff[ i ], png_buff[ i ] );
152 case PNG_COLOR_TYPE_RGB:
153 for( size_type i = 0 ; i < ( size_type )width ; i++ )
155 op[ i ] = pixel_converter::convert_to( png_buff[ i * 3 + 0 ], png_buff[ i * 3 + 1 ], png_buff[ i * 3 + 2 ] );
159 case PNG_COLOR_TYPE_RGBA:
160 for( size_type i = 0 ; i < ( size_type )width ; i++ )
162 op[ i ] = pixel_converter::convert_to( png_buff[ i * 4 + 0 ], png_buff[ i * 4 + 1 ], png_buff[ i * 4 + 2 ], png_buff[ i * 4 + 3 ] );
166 case PNG_COLOR_TYPE_GA:
167 for( size_type i = 0 ; i < ( size_type )width ; i++ )
169 op[ i ] = pixel_converter::convert_to( png_buff[ i * 2 ], png_buff[ i * 2 ], png_buff[ i * 2 ], png_buff[ i * 2 + 1 ] );
173 case PNG_COLOR_TYPE_PALETTE:
174 for( size_type i = 0 ; i < ( size_type )width ; i++ )
176 png_color &p = palette[ png_buff[ i ] ];
177 op[ i ] = pixel_converter::convert_to( p.red, p.green, p.blue );
194 png_buff = ( png_bytepp )malloc( height *
sizeof( png_bytep ) );
195 for( size_type i = 0 ; i < ( size_type )height ; i++ )
197 png_size_t nbytes = png_get_rowbytes( png_ptr, info_ptr );
198 png_buff[ i ] = ( png_bytep )malloc( nbytes );
202 png_read_image( png_ptr, png_buff );
207 case PNG_COLOR_TYPE_GRAY:
208 for( size_type j = 0 ; j < ( size_type )height ; j++ )
210 for( size_type i = 0 ; i < ( size_type )width ; i++ )
212 image( i, j ) = pixel_converter::convert_to( png_buff[ j ][ i ], png_buff[ j ][ i ], png_buff[ j ][ i ] );
217 case PNG_COLOR_TYPE_RGB:
218 for( size_type j = 0 ; j < ( size_type )height ; j++ )
220 for( size_type i = 0 ; i < ( size_type )width ; i++ )
222 image( i, j ) = pixel_converter::convert_to( png_buff[ j ][ i * 3 + 0 ], png_buff[ j ][ i * 3 + 1 ], png_buff[ j ][ i * 3 + 2 ] );
227 case PNG_COLOR_TYPE_RGBA:
228 for( size_type j = 0 ; j < ( size_type )height ; j++ )
230 for( size_type i = 0 ; i < ( size_type )width ; i++ )
232 image( i, j ) = pixel_converter::convert_to( png_buff[ j ][ i * 4 + 0 ], png_buff[ j ][ i * 4 + 1 ], png_buff[ j ][ i * 4 + 2 ], png_buff[ j ][ i * 4 + 3 ] );
237 case PNG_COLOR_TYPE_GA:
238 for( size_type j = 0 ; j < ( size_type )height ; j++ )
240 for( size_type i = 0 ; i < ( size_type )width ; i++ )
242 image( i, j ) = pixel_converter::convert_to( png_buff[ j ][ i * 2 ], png_buff[ j ][ i * 2 ], png_buff[ j ][ i * 2 ], png_buff[ j ][ i * 2 + 1 ] );
247 case PNG_COLOR_TYPE_PALETTE:
248 for( size_type j = 0 ; j < ( size_type )height ; j++ )
250 for( size_type i = 0 ; i < ( size_type )width ; i++ )
252 png_color &p = palette[ png_buff[ j ][ i ] ];
253 image( i, j ) = pixel_converter::convert_to( p.red, p.green, p.blue );
264 for( size_type i = 0 ; i < ( size_type )height ; i++ )
266 free( png_buff[ i ] );
272 png_destroy_read_struct( &png_ptr, &info_ptr, NULL );
280 static bool write(
const array2< T, Allocator > &image,
const std::string &filename,
int compression_level__ )
282 int compression_level = compression_level__ > 9 ? 9 : compression_level__;
284 if( image.width( ) == 0 )
286 std::cerr <<
"Image width is zero!" << std::endl;
289 else if( image.height( ) == 0 )
291 std::cerr <<
"Image height is zero!" << std::endl;
298 size_type width = image.width( );
299 size_type height = image.height( );
301 if( ( fp = fopen( filename.c_str( ),
"wb" ) ) == NULL )
306 png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
307 if( png_ptr == NULL )
313 info_ptr = png_create_info_struct( png_ptr );
314 if( info_ptr == NULL )
316 png_destroy_write_struct( &png_ptr, (png_infopp)NULL );
320 if( setjmp( png_jmpbuf( png_ptr ) ) )
322 png_destroy_write_struct( &png_ptr, &info_ptr );
327 if( compression_level > 9 ) compression_level = 9;
329 png_init_io( png_ptr, fp );
331 png_set_filter( png_ptr, 0, PNG_ALL_FILTERS );
332 if( compression_level < 0 )
334 png_set_compression_level( png_ptr, 6 );
338 png_set_compression_level( png_ptr, compression_level );
341 int png_color_type = pixel_converter::color_num == 4 ? PNG_COLOR_TYPE_RGBA : PNG_COLOR_TYPE_RGB;
342 png_set_IHDR( png_ptr, info_ptr, static_cast< png_uint_32 >( width ), static_cast< png_uint_32 >( height ), 8, png_color_type, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
343 png_set_gAMA( png_ptr, info_ptr, 1.0 );
348 png_text text_ptr[5];
351 png_convert_from_time_t( &mod_time, gmt );
352 png_set_tIME( png_ptr, info_ptr, &mod_time );
354 static char text[][64] = {
360 "Created by using MIST library",
363 "MIST PNG converter",
366 text_ptr[ 0 ].key = text[ 0 ];
367 text_ptr[ 0 ].text = text[ 1 ];
368 text_ptr[ 0 ].compression = PNG_TEXT_COMPRESSION_NONE;
369 text_ptr[ 1 ].key = text[ 2 ];
370 text_ptr[ 1 ].text = text[ 3 ];
371 text_ptr[ 1 ].compression = PNG_TEXT_COMPRESSION_NONE;
372 text_ptr[ 2 ].key = text[ 4 ];
373 text_ptr[ 2 ].text = text[ 5 ];
374 text_ptr[ 2 ].compression = PNG_TEXT_COMPRESSION_NONE;
375 text_ptr[ 3 ].key = text[ 6 ];
376 text_ptr[ 3 ].text = ( png_charp )png_convert_to_rfc1123( png_ptr, &mod_time );
377 text_ptr[ 3 ].compression = PNG_TEXT_COMPRESSION_NONE;
378 text_ptr[ 4 ].key = text[ 7 ];
379 text_ptr[ 4 ].text = text[ 8 ];
380 text_ptr[ 4 ].compression = PNG_TEXT_COMPRESSION_NONE;
381 png_set_text( png_ptr, info_ptr, text_ptr, 5 );
384 png_write_info( png_ptr, info_ptr );
386 if( pixel_converter::color_num == 4 )
388 png_bytep png_buff =
new png_byte[ width * 4 ];
389 for( size_type j = 0 ; j < height ; j++ )
391 typename array2< T, Allocator >::const_pointer ip = &image( 0, j );
392 for( size_type i = 0 ; i < width ; i++ )
394 color_type c =
limits_0_255( pixel_converter::convert_from( ip[ i ] ) );
395 png_buff[ i * 4 + 0 ] =
static_cast< png_byte
>( c.r );
396 png_buff[ i * 4 + 1 ] =
static_cast< png_byte
>( c.g );
397 png_buff[ i * 4 + 2 ] =
static_cast< png_byte
>( c.b );
398 png_buff[ i * 4 + 3 ] =
static_cast< png_byte
>( c.a );
401 png_write_rows( png_ptr, &png_buff, 1 );
408 png_bytep png_buff =
new png_byte[ width * 4 ];
409 for( size_type j = 0 ; j < height ; j++ )
411 typename array2< T, Allocator >::const_pointer ip = &image( 0, j );
412 for( size_type i = 0 ; i < width ; i++ )
414 color_type c =
limits_0_255( pixel_converter::convert_from( ip[ i ] ) );
415 png_buff[ i * 3 + 0 ] =
static_cast< png_byte
>( c.r );
416 png_buff[ i * 3 + 1 ] =
static_cast< png_byte
>( c.g );
417 png_buff[ i * 3 + 2 ] =
static_cast< png_byte
>( c.b );
420 png_write_rows( png_ptr, &png_buff, 1 );
426 png_write_end( png_ptr, info_ptr );
427 png_destroy_write_struct( &png_ptr, &info_ptr );
462 template <
class T,
class Allocator >
465 return( __png_controller__::png_controller< T, Allocator >::read( image, filename ) );
479 template <
class T,
class Allocator >
497 template <
class T,
class Allocator >
500 return( __png_controller__::png_controller< T, Allocator >::write( image, filename, compression_level ) );
515 template <
class T,
class Allocator >
533 #endif // __INCLUDE_MIST_PNG__