Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

plpngdec.cpp

Go to the documentation of this file.
00001 /*
00002 /--------------------------------------------------------------------
00003 |
00004 |      $Id: plpngdec.cpp,v 1.1 2004/05/21 21:02:53 maxx Exp $
00005 |      PNG Decoder Class
00006 |
00007 |      PNG file decoder. Uses LibPng to do the actual decoding.
00008 |      PNG supports many pixel formats not supported by paintlib.
00009 |      These pixel formats are converted to the nearest paintlib
00010 |      equivalent. Images with less or more than 8 bits per channel
00011 |      are converted to 8 bits per channel. Images with 16-bit
00012 |      palettes or grayscale images with an alpha channel are
00013 |      returned as full 32-bit RGBA bitmaps.
00014 |
00015 |      Copyright (c) 1996-1998 Ulrich von Zadow
00016 |
00017 \--------------------------------------------------------------------
00018 */
00019 
00020 #include "plstdpch.h"
00021 #include "plpngdec.h"
00022 #include "plexcept.h"
00023 #include "png.h"
00024 
00025 
00026 PLPNGDecoder::PLPNGDecoder
00027     ()
00028     : PLPicDecoder()
00029     // Creates a decoder
00030 {
00031 }
00032 
00033 
00034 PLPNGDecoder::~PLPNGDecoder
00035     ()
00036 {
00037 }
00038 
00039 
00040 
00041 void my_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
00042 {
00043   // todo : check data erasing
00044   PLBYTE *ptr;
00045   PLDataSource* pSourceInfo=(PLDataSource*)png_get_io_ptr(png_ptr);
00046 
00047   ptr = pSourceInfo->ReadNBytes(length);
00048   memcpy(data,ptr,length);
00049 }
00050 
00051 
00052 void PLPNGDecoder::DoDecode
00053     ( PLBmp * pBmp,
00054       PLDataSource * pDataSrc
00055     )
00056 {
00057   png_uint_32 width, height;
00058   int bit_depth, color_type, interlace_type;
00059   png_structp png_ptr = NULL;
00060   png_infop info_ptr;
00061 
00062   try
00063   {
00064     png_ptr = png_create_read_struct
00065                 (PNG_LIBPNG_VER_STRING,
00066                  (void *)NULL,
00067                  user_error_fn,
00068                  user_warning_fn);
00069     PLASSERT (png_ptr);
00070 
00071     info_ptr = png_create_info_struct(png_ptr);
00072     PLASSERT (info_ptr);
00073 
00074     png_set_read_fn(png_ptr, (void*)pDataSrc, my_read_data);
00075 
00076     /* The call to png_read_info() gives us all of the information from the
00077      * PNG file before the first IDAT (image data chunk).  REQUIRED
00078      */
00079     png_read_info(png_ptr, info_ptr);
00080 
00081     png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
00082                  &interlace_type, NULL, NULL);
00083 
00084     int DestBPP;
00085     bool bHasAlpha;
00086     switch (color_type)
00087     {
00088       case PNG_COLOR_TYPE_RGB:
00089         DestBPP = 32;
00090         bHasAlpha = false;
00091         break;
00092       case PNG_COLOR_TYPE_RGB_ALPHA:
00093         DestBPP = 32;
00094         bHasAlpha = true;
00095         break;
00096       case PNG_COLOR_TYPE_GRAY:
00097         DestBPP = 8;
00098         bHasAlpha = false;
00099         break;
00100       case PNG_COLOR_TYPE_GRAY_ALPHA:
00101         DestBPP = 32;
00102         png_set_gray_to_rgb(png_ptr);
00103         png_set_expand(png_ptr);
00104         bHasAlpha = true;
00105         break;
00106       case PNG_COLOR_TYPE_PALETTE:
00107         if (bit_depth != 16)
00108           DestBPP = 8;
00109         else
00110         { // 16-bit palette image
00111           png_set_expand(png_ptr);
00112           DestBPP = 32;
00113         }
00114         bHasAlpha = false;
00115         break;
00116     }
00117 
00118     if (DestBPP == 32)
00119     { // Make sure we use the correct byte order
00120 // Jose Miguel Buenaposada 2000/06/30
00121 #ifdef PL_PIXEL_BGRA_ORDER
00122       png_set_bgr (png_ptr);
00123 #else
00124   #ifdef PL_PIXEL_RGBA_ORDER 
00125   #else
00126   #error Unsupported byte ordering!
00127   #endif
00128 #endif
00129       
00130       if (!bHasAlpha)
00131 #if (PL_RGBA_ALPHA == 3)
00132         png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
00133 #else
00134         png_set_filler(png_ptr, 0xff, PNG_FILLER_BEFORE);
00135 #endif
00136     }
00137 
00138     if (bHasAlpha)
00139       // Image has alpha channel
00140       pBmp->Create (width, height,
00141                     DestBPP, true);
00142     else
00143       // Image doesn't have alpha channel
00144       pBmp->Create (width, height,
00145                     DestBPP, false);
00146 
00147     if (color_type == PNG_COLOR_TYPE_GRAY)
00148     {
00149       int i;
00150       int NumColors = 1<<(bit_depth);
00151       for (i=0; i<NumColors; i++)
00152       {
00153         int CurColor = (i*255)/(NumColors-1);
00154         pBmp->SetPaletteEntry(i, CurColor, CurColor, CurColor, 0xFF);
00155       }
00156     }
00157 
00158     if (color_type == PNG_COLOR_TYPE_PALETTE)
00159     {
00160       png_color* ppng_color_tab=NULL;
00161 
00162       int   i;
00163       int   nbColor=0;
00164 
00165       png_get_PLTE(png_ptr,info_ptr,&ppng_color_tab,&nbColor);
00166 
00167       for (i=0; i<nbColor; i++)
00168       {
00169         pBmp->SetPaletteEntry(i,
00170                               (*(ppng_color_tab+i)).red,
00171                               (*(ppng_color_tab+i)).green,
00172                               (*(ppng_color_tab+i)).blue,
00173                               0xFF);
00174       }
00175     }
00176 
00177     if (bit_depth == 16)
00178       png_set_strip_16(png_ptr);
00179     if (bit_depth < 8)
00180       png_set_packing(png_ptr);
00181 
00182     pBmp->Lock(false, true);
00183     PLBYTE ** pLineArray = pBmp->GetLineArray();
00184     png_read_image(png_ptr, pLineArray);
00185     pBmp->Unlock();
00186 
00187     PLULONG XRes, YRes;
00188     int UnitType;
00189     png_get_pHYs (png_ptr, info_ptr, &XRes, &YRes,
00190                   &UnitType);
00191     if (UnitType == PNG_RESOLUTION_METER)
00192       pBmp->SetResolution (PLPoint (int (XRes/39.37f+0.5), int (YRes/39.37f+0.5)));
00193     else
00194       pBmp->SetResolution (PLPoint (0,0));
00195 
00196     /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
00197     png_read_end(png_ptr, info_ptr);
00198 
00199     /* clean up after the read, and free any memory allocated - REQUIRED */
00200     png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00201   }
00202   catch (PLTextException)
00203   {
00204     // Cleaning up in this catch seems to break Visual C++ memory management
00205     // completely in some cases, so we don't do it.
00206     // The result is a small memory leak whenever a png file can't be decoded.
00207     // if (png_ptr)
00208     //   png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00209     throw;
00210   }
00211   catch(...)
00212   {
00213           PLASSERT(false);
00214     // Cleaning up in this catch seems to break Visual C++ memory management
00215     // completely in some cases, so we don't do it.
00216           // png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00217           throw;
00218   }
00219 }
00220 
00221 void PLPNGDecoder::user_error_fn
00222     ( png_structp png_ptr,
00223       png_const_charp error_msg
00224     )
00225 {
00226   raiseError (PL_ERRFORMAT_UNKNOWN, (char *)error_msg);
00227 }
00228 
00229 void PLPNGDecoder::user_warning_fn
00230     ( png_structp png_ptr,
00231       png_const_charp warning_msg
00232     )
00233 {
00234   PLTRACE ((char *)warning_msg);
00235 }
00236 
00237 /*
00238 /--------------------------------------------------------------------
00239 |
00240 |      $Log: plpngdec.cpp,v $
00241 |      Revision 1.1  2004/05/21 21:02:53  maxx
00242 |      Initial Version of vuVolume, moderatly changed to make it compile on my windows and linux machine.
00243 |
00244 |      Revision 1.1  2002/11/13 01:58:22  mspindle
00245 |      *** empty log message ***
00246 |
00247 |      Revision 1.6  2001/10/21 17:12:40  uzadow
00248 |      Added PSD decoder beta, removed BPPWanted from all decoders, added PLFilterPixel.
00249 |
00250 |      Revision 1.5  2001/10/16 18:00:19  uzadow
00251 |      Linux compatibility
00252 |
00253 |      Revision 1.4  2001/10/16 17:12:26  uzadow
00254 |      Added support for resolution information (Luca Piergentili)
00255 |
00256 |      Revision 1.3  2001/10/06 22:37:08  uzadow
00257 |      Linux compatibility.
00258 |
00259 |      Revision 1.2  2001/09/28 19:50:56  uzadow
00260 |      Added some 24 bpp stuff & other minor features.
00261 |
00262 |      Revision 1.1  2001/09/16 19:03:22  uzadow
00263 |      Added global name prefix PL, changed most filenames.
00264 |
00265 |      Revision 1.11  2001/02/04 14:31:52  uzadow
00266 |      Member initialization list cleanup (Erik Hoffmann).
00267 |
00268 |      Revision 1.10  2000/12/18 22:42:52  uzadow
00269 |      Replaced RGBAPIXEL with PLPixel32.
00270 |
00271 |      Revision 1.9  2000/08/13 12:11:43  Administrator
00272 |      Added experimental DirectDraw-Support
00273 |
00274 |      Revision 1.8  2000/07/11 17:11:01  Ulrich von Zadow
00275 |      Added support for RGBA pixel ordering (Jose Miguel Buenaposada Biencinto).
00276 |
00277 |      Revision 1.7  2000/01/16 20:43:14  anonymous
00278 |      Removed MFC dependencies
00279 |
00280 |      Revision 1.6  2000/01/04 18:35:23  Ulrich von Zadow
00281 |      no message
00282 |
00283 |      Revision 1.5  1999/12/08 16:31:40  Ulrich von Zadow
00284 |      Unix compatibility
00285 |
00286 |      Revision 1.4  1999/12/08 15:39:45  Ulrich von Zadow
00287 |      Unix compatibility changes
00288 |
00289 |      Revision 1.3  1999/10/03 18:50:51  Ulrich von Zadow
00290 |      Added automatic logging of changes.
00291 |
00292 |
00293 --------------------------------------------------------------------
00294 */

Generated on Wed Dec 15 21:20:30 2004 for vuVolume by  doxygen 1.3.9.1