initial check in
This commit is contained in:
213
pnginfo/pnginfo.cpp
Normal file
213
pnginfo/pnginfo.cpp
Normal file
@@ -0,0 +1,213 @@
|
||||
// pnginfo.cpp : Defines the entry point for the console application.
|
||||
//
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
#include <png.h>
|
||||
#include <pngstruct.h>
|
||||
|
||||
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] << " <png file name>" << 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;
|
||||
}}
|
||||
|
||||
Reference in New Issue
Block a user