00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 #include "cxutils/images/png/png.h"
00042 #include <assert.h>
00043 #include <string.h>
00044 #include <stdlib.h>
00045 #include <string.h>
00046
00047 extern "C"
00048 {
00049 #include <png.h>
00050 }
00051
00052 #ifdef WIN32
00053
00054 #define XMD_H // prevent redefinition of INT32
00055 #undef FAR // prevent FAR redefinition
00056
00057 #endif
00058
00059 namespace CxUtils
00060 {
00061 namespace PNG
00062 {
00069 struct InputSource
00070 {
00071 unsigned char* mpImage;
00072 unsigned int mImageSize;
00073 unsigned int mNumBytesRead;
00074 };
00075
00076
00077 void ReadData(png_structp png_ptr, png_bytep data, png_size_t length)
00078 {
00079 unsigned int bytesToRead = (unsigned int)length;
00080 struct InputSource* input = (struct InputSource*)png_ptr->io_ptr;
00081
00082 if(bytesToRead > input->mImageSize - input->mNumBytesRead)
00083 {
00084 bytesToRead = input->mImageSize - input->mNumBytesRead;
00085 }
00086 if(bytesToRead > 0)
00087 {
00088 memcpy(data, &input->mpImage[input->mNumBytesRead], bytesToRead);
00089 input->mNumBytesRead += bytesToRead;
00090 }
00091 }
00092 }
00093 }
00094
00112 int CxUtils::PNG::DecompressImage(const unsigned char* png,
00113 const unsigned int pngSize,
00114 unsigned char** image,
00115 unsigned short* width,
00116 unsigned short* height,
00117 unsigned char* channels)
00118 {
00119 png_structp png_ptr = NULL;
00120 png_infop info_ptr = NULL;
00121 png_byte *ptr = (png_byte *)png;
00122
00123 int is_png = !png_sig_cmp(ptr, 0, 8);
00124
00125 if (is_png)
00126 {
00127 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00128 if(png_ptr)
00129 {
00130 info_ptr = png_create_info_struct(png_ptr);
00131 }
00132 else
00133 {
00134 return 0;
00135 }
00136 }
00137 else
00138 {
00139 return 0;
00140 }
00141
00142 if (info_ptr)
00143 {
00144
00145
00146
00147 struct InputSource input;
00148
00149 input.mImageSize = pngSize;
00150 input.mpImage = (unsigned char *)png;
00151 input.mNumBytesRead = 0;
00152
00153 png_ptr->io_ptr = &input;
00154 png_ptr->read_data_fn = ReadData;
00155
00156 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_BGR, NULL);
00157
00158
00159 unsigned int outputSize;
00160 outputSize = info_ptr->width*info_ptr->height*info_ptr->channels;
00161
00162
00163 if(*image != NULL)
00164 {
00165
00166 if(outputSize >= (unsigned int)(*width)*(*height)*(*channels))
00167 {
00168 delete[] *image;
00169 *image = new unsigned char[outputSize + 100];
00170 }
00171 }
00172 else
00173 {
00174 *image = new unsigned char[outputSize + 100];
00175 }
00176
00177 *width = (unsigned short)info_ptr->width;
00178 *height = (unsigned short)info_ptr->height;
00179 *channels = (unsigned char)info_ptr->channels;
00180
00181 png_bytep * row_pointers = NULL;
00182 row_pointers = NULL;
00183
00184 int row_stride = (*width)*(*channels)*sizeof(unsigned char);
00185 if (info_ptr->color_type == PNG_COLOR_TYPE_RGB || info_ptr->color_type == PNG_COLOR_TYPE_GRAY)
00186 {
00187 row_pointers = png_get_rows(png_ptr, info_ptr);
00188
00189 for (unsigned int i = 0; i < *height; i++)
00190 {
00191 memcpy( *image + i*row_stride, row_pointers[i], row_stride);
00192 }
00193 }
00194
00195 if(png_ptr && info_ptr)
00196 {
00197 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
00198 }
00199 else if(png_ptr)
00200 {
00201 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
00202 }
00203
00204 return 1;
00205 }
00206
00207 return 0;
00208 }
00209
00210 namespace CxUtils
00211 {
00212 namespace PNG
00213 {
00220 struct OutputSource
00221 {
00222 unsigned char* mpCompressedPNG;
00223 unsigned int mCompressedBufferSize;
00224 unsigned int mNumBytesCompressed;
00225 };
00226
00227
00228 void WriteData(png_structp png_ptr, png_bytep data, png_size_t length)
00229 {
00230 struct OutputSource* output = (struct OutputSource*)png_ptr->io_ptr;
00231
00232 if(output->mNumBytesCompressed + length > output->mCompressedBufferSize)
00233 {
00234 unsigned char* temp = new unsigned char[output->mCompressedBufferSize + length];
00235 memcpy(temp, output->mpCompressedPNG, output->mNumBytesCompressed);
00236 delete[] output->mpCompressedPNG;
00237 output->mpCompressedPNG = temp;
00238 output->mCompressedBufferSize += (unsigned int)length;
00239 }
00240 memcpy(&output->mpCompressedPNG[output->mNumBytesCompressed], data, length);
00241 output->mNumBytesCompressed += (unsigned int)length;
00242 }
00243 }
00244 }
00245
00265 int CxUtils::PNG::CompressImage(const unsigned short width,
00266 const unsigned short height,
00267 const unsigned char channels,
00268 const unsigned char* image,
00269 unsigned char** png,
00270 unsigned int* pngBufferSize,
00271 unsigned int* pngSize)
00272 {
00273 int result = 0;
00274
00275 if( width == 0 ||
00276 height == 0 ||
00277 !(channels == 1 || channels == 3) ||
00278 image == NULL ||
00279 png == NULL )
00280 {
00281 return result;
00282 }
00283
00284 if( channels == 3 || channels == 1 )
00285 {
00286 if(*pngBufferSize == 0 || *png == NULL)
00287 {
00288
00289 if( (*png) )
00290 {
00291 delete[] *png;
00292 *png = NULL;
00293 }
00294 *png = new unsigned char[4096];
00295 *pngBufferSize = 4096;
00296 }
00297 *pngSize = 0;
00298
00299 png_structp png_ptr = NULL;
00300 png_bytep * row_pointers = NULL;
00301
00302 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00303 png_infop info_ptr = png_create_info_struct(png_ptr);
00304
00305
00306
00307 struct OutputSource output;
00308 output.mCompressedBufferSize = *pngBufferSize;
00309 output.mNumBytesCompressed = 0;
00310 output.mpCompressedPNG = *png;
00311
00312 png_ptr->io_ptr = &output;
00313 png_ptr->write_data_fn = WriteData;
00314
00315 png_byte color;
00316 if (channels == 1)
00317 {
00318 color = PNG_COLOR_TYPE_GRAY;
00319 }
00320 else if (channels == 3)
00321 {
00322 color = PNG_COLOR_TYPE_RGB;
00323 }
00324 else
00325 {
00326 color = PNG_COLOR_TYPE_RGB;
00327 }
00328
00329
00330 png_set_IHDR(png_ptr, info_ptr, width, height,
00331 8, color, PNG_INTERLACE_NONE,
00332 PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
00333
00334 row_pointers = (png_bytep*)malloc(height*sizeof(png_bytep));
00335 int row_stride = width*channels*sizeof(unsigned char);
00336
00337 for (int i=0 ; i< height; i++)
00338 {
00339 row_pointers[i] = (png_byte*)&image[i*row_stride];
00340
00341 }
00342
00343 png_set_rows(png_ptr, info_ptr, row_pointers);
00344 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_STRIP_16 | PNG_TRANSFORM_BGR, NULL);
00345
00346 free(row_pointers);
00347
00348 *png = output.mpCompressedPNG;
00349 *pngBufferSize = output.mCompressedBufferSize;
00350 *pngSize = output.mNumBytesCompressed;
00351
00352 png_destroy_write_struct(&png_ptr, &info_ptr);
00353
00354 result = 1;
00355
00356 }
00357
00358 return result;
00359 }
00360
00361
00362