00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
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
00077
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 {
00111 png_set_expand(png_ptr);
00112 DestBPP = 32;
00113 }
00114 bHasAlpha = false;
00115 break;
00116 }
00117
00118 if (DestBPP == 32)
00119 {
00120
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
00140 pBmp->Create (width, height,
00141 DestBPP, true);
00142 else
00143
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
00197 png_read_end(png_ptr, info_ptr);
00198
00199
00200 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00201 }
00202 catch (PLTextException)
00203 {
00204
00205
00206
00207
00208
00209 throw;
00210 }
00211 catch(...)
00212 {
00213 PLASSERT(false);
00214
00215
00216
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
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294