/* /-------------------------------------------------------------------- | | $Id: plpngdec.cpp,v 1.13 2004/10/02 22:23:12 uzadow Exp $ | PNG Decoder Class | | PNG file decoder. Uses LibPng to do the actual decoding. | PNG supports many pixel formats not supported by paintlib. | These pixel formats are converted to the nearest paintlib | equivalent. Images with less or more than 8 bits per channel | are converted to 8 bits per channel. Images with 16-bit | palettes or grayscale images with an alpha channel are | returned as full 32-bit RGBA bitmaps. | | Copyright (c) 1996-2002 Ulrich von Zadow | \-------------------------------------------------------------------- */ #include "plpngdec.h" #include "plexcept.h" #include "png.h" PLPNGDecoder::PLPNGDecoder () : PLPicDecoder() // Creates a decoder { } PLPNGDecoder::~PLPNGDecoder () { } void my_read_data(png_structp png_ptr, png_bytep data, png_size_t length) { // todo : check data erasing PLBYTE *ptr; PLDataSource* pSourceInfo=(PLDataSource*)png_get_io_ptr(png_ptr); ptr = pSourceInfo->ReadNBytes(length); memcpy(data,ptr,length); } void PLPNGDecoder::Open (PLDataSource * pDataSrc) { png_uint_32 width, height; int interlace_type; m_png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, (void *)NULL, user_error_fn, user_warning_fn); PLASSERT (m_png_ptr); m_info_ptr = png_create_info_struct(m_png_ptr); PLASSERT (m_info_ptr); png_set_read_fn(m_png_ptr, (void*)pDataSrc, my_read_data); /* The call to png_read_info() gives us all of the information from the * PNG file before the first IDAT (image data chunk). */ png_read_info(m_png_ptr, m_info_ptr); png_get_IHDR(m_png_ptr, m_info_ptr, &width, &height, &m_bit_depth, &m_color_type, &interlace_type, NULL, NULL); PLPixelFormat pf; switch (m_color_type) { case PNG_COLOR_TYPE_RGB: pf = PLPixelFormat::R8G8B8; break; case PNG_COLOR_TYPE_RGB_ALPHA: pf = PLPixelFormat::A8R8G8B8; break; case PNG_COLOR_TYPE_GRAY: pf = PLPixelFormat::L8; break; case PNG_COLOR_TYPE_GRAY_ALPHA: png_set_gray_to_rgb(m_png_ptr); png_set_expand(m_png_ptr); pf = PLPixelFormat::A8R8G8B8; break; case PNG_COLOR_TYPE_PALETTE: if (m_bit_depth != 16) pf = PLPixelFormat::I8; else { // 16-bit palette image png_set_expand(m_png_ptr); pf = PLPixelFormat::R8G8B8; } break; } if (pf.GetBitsPerPixel() == 32 || pf.GetBitsPerPixel() == 24) { png_set_bgr (m_png_ptr); } SetBmpInfo (PLPoint (width, height), PLPoint(0,0), pf); PLULONG XRes, YRes; int UnitType; png_get_pHYs (m_png_ptr, m_info_ptr, &XRes, &YRes, &UnitType); if (UnitType == PNG_RESOLUTION_METER) m_Resolution = PLPoint (int (XRes/39.37f+0.5), int (YRes/39.37f+0.5)); } void PLPNGDecoder::GetImage (PLBmpBase & Bmp) { if (m_color_type == PNG_COLOR_TYPE_GRAY) { int i; int NumColors = 1<<(m_bit_depth); for (i=0; i