00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "pent_include.h"
00020 #include "TexturePNG.h"
00021
00022 #include "IDataSource.h"
00023
00024
00025 #include <png.h>
00026
00027
00028 static void idatasource_png_read_data(png_structp png_ptr,
00029 png_bytep data, png_size_t length)
00030 {
00031 voidp read_io_ptr = png_get_io_ptr(png_ptr);
00032 IDataSource* ds = reinterpret_cast<IDataSource*>(read_io_ptr);
00033 ds->read(data, length);
00034 }
00035
00036 bool TexturePNG::Read(IDataSource *ds)
00037 {
00038 png_bytep* row_pointers = 0;
00039
00040 png_byte header[8];
00041 if (ds->read(header, 8) < 8) return false;
00042 if (png_sig_cmp(header, 0, 8)) {
00043 return false;
00044 }
00045 png_structp png_ptr = png_create_read_struct(
00046 PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00047 if (!png_ptr)
00048 return false;
00049
00050 png_infop info_ptr = png_create_info_struct(png_ptr);
00051 if (!info_ptr)
00052 {
00053 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
00054 return false;
00055 }
00056
00057 png_infop end_info = png_create_info_struct(png_ptr);
00058 if (!end_info)
00059 {
00060 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00061 return false;
00062 }
00063
00064 if (setjmp(png_jmpbuf(png_ptr))) {
00065 delete[] row_pointers;
00066 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00067 return false;
00068 }
00069
00070 png_set_read_fn(png_ptr, ds, idatasource_png_read_data);
00071 png_set_sig_bytes(png_ptr, 8);
00072
00073 png_read_info(png_ptr, info_ptr);
00074
00075 png_uint_32 width, height;
00076 int bit_depth, color_type;
00077 int interlace_type, compression_type, filter_method;
00078 png_get_IHDR(png_ptr, info_ptr, &width, &height,
00079 &bit_depth, &color_type,
00080 &interlace_type, &compression_type, &filter_method);
00081
00082 if (color_type == PNG_COLOR_TYPE_PALETTE)
00083 png_set_palette_to_rgb(png_ptr);
00084
00085 if (color_type == PNG_COLOR_TYPE_GRAY ||
00086 color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
00087 png_set_gray_to_rgb(png_ptr);
00088
00089 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
00090 png_set_tRNS_to_alpha(png_ptr);
00091
00092 if (bit_depth == 16)
00093 png_set_strip_16(png_ptr);
00094
00095 if (color_type == PNG_COLOR_TYPE_RGB)
00096 png_set_filler(png_ptr, 0xFF, PNG_FILLER_AFTER);
00097
00098 png_read_update_info(png_ptr, info_ptr);
00099
00100 png_uint_32 rowbytes = png_get_rowbytes(png_ptr, info_ptr);
00101 if (rowbytes != width * 4) {
00102 perr << "TexturePNG::Read(): failed to convert PNG to 32 bit RGBA"
00103 << std::endl;
00104 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00105 return false;
00106 }
00107
00108 buffer = new uint32[width*height];
00109 if (!buffer) {
00110 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00111 return false;
00112 }
00113
00114 row_pointers = new png_bytep[height];
00115 for (unsigned int i = 0; i < height; ++i) {
00116 row_pointers[i] = reinterpret_cast<png_bytep>(&buffer[i*width]);
00117 }
00118
00119 png_read_image(png_ptr, row_pointers);
00120
00121 delete[] row_pointers;
00122 row_pointers = 0;
00123
00124
00125 png_read_end(png_ptr, end_info);
00126
00127 png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
00128
00129 this->width = width;
00130 this->height = height;
00131 this->format = TEX_FMT_STANDARD;
00132 this->wlog2 = -1;
00133 this->hlog2 = -1;
00134
00135
00136 for (unsigned int i = 0; i < height * width; ++i) {
00137 png_bytep p = reinterpret_cast<png_bytep>(&buffer[i]);
00138 buffer[i] =(p[0] << TEX32_R_SHIFT)
00139 | (p[1] << TEX32_G_SHIFT)
00140 | (p[2] << TEX32_B_SHIFT)
00141 | (p[3] << TEX32_A_SHIFT);
00142 }
00143
00144 return true;
00145 }