00001 #include <stdio.h>
00002 #include <png.h>
00003
00004 #include "imageFilePNG.hpp"
00005
00006
00007 void pngError(png_structp png_ptr, png_const_charp msg)
00008
00009 {
00010 if(png_ptr)
00011 {
00012 printf("libpng error: %s\n", msg);
00013 }
00014 }
00015
00016
00017 void pngWarning(png_structp png_ptr, png_const_charp msg)
00018
00019 {
00020 if(png_ptr)
00021 {
00022 printf("libpng warning: %s\n", msg);
00023 }
00024 }
00025
00026
00027 imageFilePNG::imageFilePNG()
00028
00029 {
00030 }
00031
00032
00033 imageFilePNG::~imageFilePNG()
00034
00035 {
00036 }
00037
00038
00039 bool imageFilePNG::loadImage(String filename)
00040
00041 {
00042 FILE * fp;
00043 png_structp pngRead;
00044 png_infop pngInfo;
00045 UInt8 pngHeader[8];
00046 bool res = true;
00047 Int32 i;
00048
00049
00050 if (!(fp = fopen(filename, "rb")))
00051 {
00052 return false;
00053 }
00054
00055 fread(pngHeader, 1, 8, fp);
00056 if (0 != png_sig_cmp(pngHeader, 0, 8))
00057 {
00058 printf(__FILE__"This is not a valid PNG\n");
00059 return false;
00060 }
00061
00062
00063 pngRead = png_create_read_struct(PNG_LIBPNG_VER_STRING, (void *)this, (png_error_ptr)pngError, (png_error_ptr)pngWarning);
00064 if(0 == pngRead)
00065 {
00066 return false;
00067 }
00068
00069 pngInfo = png_create_info_struct(pngRead);
00070 if(0 == pngInfo)
00071 {
00072 png_destroy_read_struct(&pngRead, NULL, NULL);
00073 return false;
00074 }
00075
00076 do {
00077
00078 png_init_io(pngRead, fp);
00079 png_set_sig_bytes(pngRead, 8);
00080
00081
00082 png_read_info(pngRead, pngInfo);
00083
00084 Int32 bitWidth;
00085 Int32 colorType;
00086 Int32 width;
00087 Int32 height;
00088
00089
00090 png_get_IHDR(pngRead, pngInfo, (unsigned long *)&width, (unsigned long *)&height, &bitWidth, &colorType, NULL, NULL, NULL);
00091
00092
00093 if (8 != bitWidth)
00094 {
00095 printf(__FILE__"Bitwidths other than 8 are not supported\n");
00096 res = false;
00097 break;
00098 }
00099
00100 Int32 numberOfBytes = 0;
00101 Int32 bytesPerRow = 0;
00102 imageFile::ePixelFormat pixelFormat = imageFile::NONE;
00103
00104
00105 if ((PNG_COLOR_TYPE_GRAY == colorType) || (PNG_COLOR_TYPE_GRAY == colorType))
00106 {
00107 pixelFormat = imageFile::G8;
00108 numberOfBytes = width * height;
00109 bytesPerRow = width;
00110 }
00111 else if (PNG_COLOR_TYPE_RGB == colorType)
00112 {
00113 pixelFormat = imageFile::RGB888;
00114 numberOfBytes = width * height * 3;
00115 bytesPerRow = width * 3;
00116 }
00117 else if (PNG_COLOR_TYPE_RGB_ALPHA == colorType)
00118 {
00119 pixelFormat = imageFile::RGBA8888;
00120 numberOfBytes = width * height * 4;
00121 bytesPerRow = width * 4;
00122 }
00123 else
00124 {
00125 printf(__FILE__"Color type not supported\n");
00126 res = false;
00127 break;
00128 }
00129
00130
00131 cleanup();
00132
00133 mPixelFormat = pixelFormat;
00134 mWidth = width;
00135 mHeight = height;
00136
00137
00138 mPixels = new UInt8[numberOfBytes];
00139
00140
00141 UInt8 ** rowPointers = new UInt8*[height];
00142
00143
00144 for (i = 0; i < height; i++)
00145 {
00146 rowPointers[i] = mPixels + i * bytesPerRow;
00147 }
00148
00149
00150 png_read_image(pngRead, rowPointers);
00151
00152
00153 png_read_end(pngRead, NULL);
00154
00155
00156
00157 delete [] rowPointers;
00158
00159 }while(0);
00160
00161 png_destroy_read_struct(&pngRead, &pngInfo, NULL);
00162
00163 fclose(fp);
00164
00165 return res;
00166 }
00167
00168
00169 bool imageFilePNG::writeImage(String filename)
00170
00171 {
00172 FILE * fp;
00173 png_structp pngWrite;
00174 png_infop pngInfo;
00175 bool res = true;
00176 Int32 i;
00177
00178
00179 if (!(fp = fopen(filename, "wb")))
00180 {
00181 return false;
00182 }
00183
00184
00185
00186 pngWrite = png_create_write_struct(PNG_LIBPNG_VER_STRING, (void *)this, (png_error_ptr)pngError, (png_error_ptr)pngWarning);
00187 if (0 == pngWrite)
00188 {
00189 fclose(fp);
00190 return false;
00191 }
00192
00193 pngInfo = png_create_info_struct(pngWrite);
00194 if (0 == pngInfo)
00195 {
00196 fclose(fp);
00197 png_destroy_write_struct(&pngWrite, (png_infopp) NULL);
00198 return false;
00199 }
00200
00201 do
00202 {
00203 png_init_io(pngWrite, fp);
00204
00205 Int32 colorType = 0;
00206 Int32 channels = 0;
00207
00208 if(imageFile::RGB888 == mPixelFormat)
00209 {
00210 colorType = PNG_COLOR_TYPE_RGB;
00211 channels = 3;
00212 }
00213 else if(imageFile::RGBA8888 == mPixelFormat)
00214 {
00215 colorType = PNG_COLOR_TYPE_RGBA;
00216 channels = 4;
00217 }
00218 else if(imageFile::G8== mPixelFormat)
00219 {
00220 colorType = PNG_COLOR_TYPE_GRAY;
00221 channels = 1;
00222 }
00223 else
00224 {
00225 res = false;
00226 break;
00227 }
00228
00229
00230 png_set_IHDR(pngWrite, pngInfo, mWidth, mHeight, 8, colorType, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00231
00232
00233 png_write_info(pngWrite, pngInfo);
00234
00235
00236 UInt32 bytesPerRow = mWidth * channels;
00237
00238
00239
00240 png_bytepp ppbRowPointers = new png_bytep[mHeight];
00241
00242
00243 for (i = 0; i < mHeight; i++)
00244 {
00245 ppbRowPointers[i] = mPixels + i * bytesPerRow;
00246 }
00247
00248
00249
00250 png_write_image (pngWrite, ppbRowPointers);
00251
00252
00253
00254 png_write_end(pngWrite, pngInfo);
00255
00256
00257
00258 delete [] ppbRowPointers;
00259
00260
00261 }while(0);
00262
00263 png_destroy_write_struct(&pngWrite, (png_infopp) NULL);
00264
00265 fclose(fp);
00266 return res;
00267 }
00268
00269