00001
00008 #ifndef __LIBPNG_HELPERS__
00009 #define __LIBPNG_HELPERS__
00010
00011
00012 #define PNG_NO_TYPECAST_NULL
00013
00014 #include <png.h>
00015 #include <cstdio>
00016 #include <iostream>
00017
00018 static unsigned const int PNG_BYTES_TO_CHECK = 8;
00019
00020
00021
00022 using namespace std;
00023
00024
00025 int check_if_png(const char *file_name, FILE **fp)
00026 {
00027 png_byte buf[PNG_BYTES_TO_CHECK];
00028
00029
00030 if ((*fp = fopen(file_name, "rb")) == NULL)
00031 return 0;
00032
00033
00034 if (fread(buf, 1, PNG_BYTES_TO_CHECK, *fp) != PNG_BYTES_TO_CHECK)
00035 return 0;
00036
00037
00038
00039
00040 bool res = (!png_sig_cmp(buf, static_cast<png_size_t>(0), PNG_BYTES_TO_CHECK));
00041 fclose(*fp);
00042 return res;
00043 }
00044
00045
00046 void read_png( const char * file_name,
00047 unsigned char *& buffer,
00048 int & width,
00049 int & height,
00050 int & channels,
00051 int & bit_depth,
00052 int & color_type,
00053 bool flip_vert )
00054 {
00055 png_structp png_ptr;
00056 png_infop info_ptr;
00057 FILE * fp;
00058 bool check = check_if_png(file_name, &fp);
00059
00060 if (!check)
00061 {
00062 std::cerr << "This is not a PNG file !!" << endl;
00063 exit(1);
00064 }
00065
00066 fp = fopen(file_name, "rb");
00067
00068
00069
00070
00071
00072
00073
00074 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00075
00076 if (png_ptr == NULL)
00077 {
00078 fclose(fp);
00079 std::cerr << "Error initializing png_ptr !" << endl;
00080 exit(1);
00081 }
00082
00083
00084 info_ptr = png_create_info_struct(png_ptr);
00085 if (info_ptr == NULL)
00086 {
00087 fclose(fp);
00088 png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
00089 std::cerr << "Error initializing info_ptr !" << endl;
00090 exit(1);
00091 }
00092
00093
00094
00095
00096
00097 if (setjmp(png_jmpbuf(png_ptr)))
00098 {
00099
00100 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00101 fclose(fp);
00102
00103 std::cerr << "Error initializing png_ptr !" << endl;
00104 exit(1);
00105 }
00106
00107 png_init_io(png_ptr, fp);
00108
00109
00110 png_set_sig_bytes(png_ptr, 0);
00111
00112
00113
00114
00115
00116
00117
00118
00119 png_read_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
00120
00121 width = png_get_image_width(png_ptr, info_ptr);
00122 height = png_get_image_height(png_ptr, info_ptr);
00123 channels = png_get_channels(png_ptr, info_ptr);
00124 bit_depth = png_get_bit_depth(png_ptr, info_ptr);
00125 color_type = png_get_color_type(png_ptr, info_ptr);
00126
00127 png_uint_32 valid = 0;
00128 png_get_valid(png_ptr, info_ptr, valid);
00129
00130 png_bytep* row_pointers = png_get_rows(png_ptr, info_ptr);
00131
00132
00133 const int c = width*channels*bit_depth/8;
00134 buffer = new unsigned char[channels * width * height * bit_depth / 8];
00135
00136 if (!flip_vert)
00137 {
00138 for (int y = 0;y<height;++y)
00139 {
00140 memcpy(static_cast<void*>(&(buffer[y*c])), static_cast<void*>(row_pointers[y]), c);
00141 }
00142 }
00143 else
00144 {
00145 for (int y = 0;y<height;++y)
00146 {
00147 memcpy(static_cast<void*>(&(buffer[(height-1-y)*c])), static_cast<void*>(row_pointers[y]), c);
00148 }
00149 }
00150
00151 png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
00152 fclose(fp);
00153 }
00154
00155
00156
00157
00168 void write_png( const char * file_name,
00169 unsigned char * buffer,
00170 int width,
00171 int height,
00172 int channels,
00173 int bit_depth,
00174 png_uint_32 color_type,
00175 bool flip_vert)
00176 {
00177 FILE * fp;
00178 png_structp png_ptr;
00179 png_infop info_ptr;
00180
00181
00182
00183 fp = fopen(file_name, "wb");
00184 if (fp == NULL)
00185 {
00186 std::cerr << "Error opening file " << endl;
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00196
00197 if (png_ptr == NULL)
00198 {
00199 fclose(fp);
00200 std::cerr << "Error allocating png_ptr !!" << endl;
00201 exit(1);
00202 }
00203
00204
00205 info_ptr = png_create_info_struct(png_ptr);
00206 if (info_ptr == NULL)
00207 {
00208 fclose(fp);
00209 png_destroy_write_struct(&png_ptr, png_infopp_NULL);
00210 std::cerr << "Error allocating info ptr !!" << endl;
00211 exit(1);
00212 }
00213
00214
00215
00216
00217 if (setjmp(png_jmpbuf(png_ptr)))
00218 {
00219
00220 fclose(fp);
00221 png_destroy_write_struct(&png_ptr, &info_ptr);
00222 exit(1);
00223 }
00224
00225 png_init_io(png_ptr, fp);
00226
00227 png_set_IHDR( png_ptr, info_ptr,
00228 static_cast<png_uint_32>(width), static_cast<png_uint_32>(height),
00229 static_cast<png_byte>(bit_depth), static_cast<png_byte>(color_type),
00230 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT );
00231
00232
00233
00234 png_bytep * row_pointers = new png_bytep[height];
00235 const int c = width * channels * bit_depth / 8;
00236 if (!flip_vert)
00237 {
00238 for (int y = 0;y<height;++y)
00239 {
00240 row_pointers[y] = static_cast<png_bytep>(&(buffer[y*c]));
00241 }
00242 }
00243 else
00244 {
00245 for (int y = 0;y<height;++y)
00246 {
00247 row_pointers[height-1-y] = static_cast<png_bytep>(&(buffer[y*c]));
00248 }
00249 }
00250
00251
00252 png_set_rows(png_ptr, info_ptr, row_pointers);
00253 png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, png_voidp_NULL);
00254
00255 png_destroy_write_struct(&png_ptr, &info_ptr);
00256 delete [] row_pointers;
00257 fclose(fp);
00258 }
00259
00260 #endif
00261