// pnginfo.cpp : Defines the entry point for the console application. // #include #include #include #include #include static void error_handler(png_structp png_ptr, png_const_charp msg) { // if (png_ptr) // ; throw std::logic_error( boost::str(boost::format("libpng: %1") % msg).c_str() ); } static void warning_handler(png_structp png_ptr, png_const_charp msg) { // if (png_ptr) // ; std::cerr << "Warning: libpng: " << msg << std::endl; } void print_info( const std::string& name ) { png_structp png_ptr = 0; png_infop info_ptr = 0; try { // // Open the file. // FILE * file = fopen( name.c_str(), "rb"); if ( !file ) throw std::logic_error( "fopen failed." ); // // First check the eight byte PNG signature. // png_byte signature[8]; fread(signature, 1, 8, file); if (png_sig_cmp(signature, 0, 8)) throw std::logic_error( "Bad signature." ); // // Create the two png(-info) structures. // png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0/*this*/, (png_error_ptr)error_handler, (png_error_ptr)warning_handler); if (!png_ptr) throw std::logic_error( "png_create_read_struct failed." ); info_ptr = png_create_info_struct(png_ptr); if (!info_ptr) throw std::logic_error( "png_create_info_struct failed." ); // // Initialize the png structure. // png_init_io(png_ptr, file); png_set_sig_bytes(png_ptr, 8); // // Read all PNG info up to image data. // png_read_info(png_ptr, info_ptr); // // Get width, height, bit-depth and color-type. // png_uint_32 width; png_uint_32 height; int bitDepth; int colorType; png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType, NULL, NULL, NULL); png_size_t rowBytes = png_get_rowbytes(png_ptr, info_ptr); int channels = png_get_channels(png_ptr, info_ptr); std::string colorTypeStr; switch ( colorType ) { case PNG_COLOR_TYPE_GRAY: colorTypeStr = "PNG_COLOR_TYPE_GRAY"; break; case PNG_COLOR_TYPE_GRAY_ALPHA: colorTypeStr = "PNG_COLOR_TYPE_GRAY_ALPHA"; break; case PNG_COLOR_TYPE_PALETTE: colorTypeStr = "PNG_COLOR_TYPE_PALETTE"; break; case PNG_COLOR_TYPE_RGB: colorTypeStr = "PNG_COLOR_TYPE_RGB"; break; case PNG_COLOR_TYPE_RGB_ALPHA: colorTypeStr = "PNG_COLOR_TYPE_RGB_ALPHA"; break; default: colorTypeStr = boost::str( boost::format( "%02x" ) % colorType ); } std::cout << "Name: " << name << std::endl; std::cout << "Width: " << width << std::endl; std::cout << "Height: " << height << std::endl; std::cout << "Bit Depth: " << bitDepth << std::endl; std::cout << "Channels: " << channels << std::endl; std::cout << "Color Type: " << colorTypeStr << std::endl; #if 0 // // Expand images of all color-type and bit-depth to 3x8-bit RGB. // let the library process alpha, transparency, background, etc. // if (colorType == PNG_COLOR_TYPE_PALETTE) png_set_expand(png_ptr); if (bitDepth < 8) png_set_expand(png_ptr); if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) png_set_expand(png_ptr); if (colorType == PNG_COLOR_TYPE_GRAY || colorType == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); if (colorType == PNG_COLOR_TYPE_RGB_ALPHA || colorType == PNG_COLOR_TYPE_GRAY_ALPHA || png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS) ) png_set_swap_alpha(png_ptr); else png_set_filler(png_ptr, ~0, PNG_FILLER_BEFORE); if (bitDepth == 16) # ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED png_set_scale_16(png_ptr); # else png_set_strip_16(png_ptr); # endif // // Set the background color to draw transparent and alpha images over. // png_color_16 * bg16; if (png_get_bKGD(png_ptr, info_ptr, &bg16)) png_set_background(png_ptr, bg16, PNG_BACKGROUND_GAMMA_FILE, 1, 1.0); // // If required set gamma conversion. // double dGamma; if (png_get_gAMA(png_ptr, info_ptr, &dGamma)) png_set_gamma(png_ptr, (double) 2.2, dGamma); // // After the transformations are registered, update info_ptr data. // png_read_update_info(png_ptr, info_ptr); // // Get again width, height and the new bit-depth and color-type. // png_get_IHDR(png_ptr, info_ptr, &width, &height, &bitDepth, &colorType, 0, 0, 0); // // Row_bytes is the width x number of channels. // if ( rowBytes != channels * width * bitDepth / 8 ) throw std::logic_error( "row bytes is not equal to channels*width*bitDepth/8" ); // // Check if the image can store data. // if ( I::bit_depth != bitDepth ) throw std::logic_error( "bit depth don't match." ); if ( I::channels != channels ) throw std::logic_error( "channels don't match." ); // // Now we can allocate memory to store the image. // image.resize( width, height ); // // Read data raw by raw. // for (png_uint_32 i = 0; i < height; i++) png_read_row( png_ptr, (png_bytep)image.getData( 0, i ), 0 ); // // Read the additional chunks in the PNG file (not really needed). // png_read_end(png_ptr, 0); #endif // // Destroy reader and info. // png_destroy_read_struct( &png_ptr, &info_ptr, 0 ); png_ptr = 0; info_ptr = 0; } catch ( ... ) { if ( png_ptr ) png_destroy_read_struct( &png_ptr, &info_ptr, 0 ); throw; }} int main(int argc, char * argv[]) {try{ if ( argc != 2 ) { std::cerr << "Usage: " << argv[0] << " " << std::endl; return 3; } print_info(argv[1]); return 0; } catch ( const std::exception& e ) { std::cerr << "Error: " << e.what() << std::endl; return 2; } catch (...) { std::cerr << "Error: unknown." << std::endl; return 1; }}