png.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <core/exception.h>
00025 #include <fvutils/readers/png.h>
00026 #include <fvutils/color/rgbyuv.h>
00027
00028 #include <cstdio>
00029 #include <cstdlib>
00030 #include <png.h>
00031
00032 using namespace fawkes;
00033
00034
00035 class PNGReaderData
00036 {
00037 public:
00038 FILE *infile;
00039 png_structp png_ptr;
00040 png_infop info_ptr;
00041 int number_passes;
00042 bool read;
00043 };
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 PNGReader::PNGReader(const char *filename)
00055 {
00056 opened = false;
00057 buffer = NULL;
00058
00059 __d = setup_read(filename);
00060
00061 opened = true;
00062 }
00063
00064
00065 PNGReaderData *
00066 PNGReader::setup_read(const char *filename)
00067 {
00068 PNGReaderData *d = new PNGReaderData();
00069 d->read = false;
00070
00071 if ((d->infile = fopen(filename, "rb")) == NULL) {
00072 throw Exception("Cannot open PNG file");
00073 }
00074
00075 d->png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00076
00077 if (d->png_ptr == NULL) {
00078 fclose(d->infile);
00079 throw Exception("Could not create PNG read struct");
00080 }
00081
00082
00083 d->info_ptr = png_create_info_struct(d->png_ptr);
00084 if (d->info_ptr == NULL) {
00085 fclose(d->infile);
00086 png_destroy_read_struct(&d->png_ptr, png_infopp_NULL, png_infopp_NULL);
00087 throw Exception("Could not create PNG info struct");
00088 }
00089
00090
00091
00092
00093
00094 if (setjmp(png_jmpbuf(d->png_ptr))) {
00095
00096 png_destroy_read_struct(&d->png_ptr, &d->info_ptr, png_infopp_NULL);
00097 fclose(d->infile);
00098
00099 throw Exception("Could not read PNG file");
00100 }
00101
00102
00103 png_init_io(d->png_ptr, d->infile);
00104
00105
00106
00107 png_read_info(d->png_ptr, d->info_ptr);
00108
00109
00110 png_set_strip_16(d->png_ptr);
00111
00112
00113
00114 png_set_strip_alpha(d->png_ptr);
00115
00116
00117
00118 png_set_packing(d->png_ptr);
00119
00120 png_byte color_type = png_get_color_type(d->png_ptr, d->info_ptr);
00121
00122
00123 if (color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(d->png_ptr);
00124
00125
00126 if (color_type == PNG_COLOR_TYPE_GRAY) png_set_gray_to_rgb(d->png_ptr);
00127
00128
00129
00130
00131
00132
00133 int intent;
00134 double screen_gamma = 2.2;
00135 if (png_get_sRGB(d->png_ptr, d->info_ptr, &intent)) {
00136 png_set_gamma(d->png_ptr, screen_gamma, 0.45455);
00137 } else {
00138 double image_gamma;
00139 if (png_get_gAMA(d->png_ptr, d->info_ptr, &image_gamma)) {
00140 png_set_gamma(d->png_ptr, screen_gamma, image_gamma);
00141 } else {
00142 png_set_gamma(d->png_ptr, screen_gamma, 0.45455);
00143 }
00144 }
00145
00146
00147
00148
00149 d->number_passes = png_set_interlace_handling(d->png_ptr);
00150
00151
00152
00153
00154 png_read_update_info(d->png_ptr, d->info_ptr);
00155
00156 return d;
00157 }
00158
00159
00160 PNGReader::~PNGReader()
00161 {
00162 fclose( __d->infile );
00163
00164 png_destroy_read_struct(&__d->png_ptr, &__d->info_ptr, png_infopp_NULL);
00165
00166 delete __d;
00167
00168 opened = false;
00169 }
00170
00171
00172 void
00173 PNGReader::set_buffer(unsigned char *yuv422planar_buffer)
00174 {
00175 buffer = yuv422planar_buffer;
00176 }
00177
00178
00179 colorspace_t
00180 PNGReader::colorspace()
00181 {
00182 return YUV422_PLANAR;
00183 }
00184
00185
00186 unsigned int
00187 PNGReader::pixel_width()
00188 {
00189 if ( opened ) {
00190 return png_get_image_width(__d->png_ptr, __d->info_ptr);
00191 } else {
00192 return 0;
00193 }
00194 }
00195
00196
00197 unsigned int
00198 PNGReader::pixel_height()
00199 {
00200 if ( opened ) {
00201 return png_get_image_height(__d->png_ptr, __d->info_ptr);
00202 } else {
00203 return 0;
00204 }
00205 }
00206
00207
00208 void
00209 PNGReader::read()
00210 {
00211 if ( buffer == NULL ) {
00212 throw Exception("PNGReader::read: buffer == NULL");
00213 }
00214 if ( __d->read ) {
00215 throw Exception("Can read PNG file only once.");
00216 }
00217 __d->read = true;
00218
00219 png_bytep row_pointer;
00220 row_pointer = (png_bytep)png_malloc(__d->png_ptr, png_get_rowbytes(__d->png_ptr, __d->info_ptr));
00221
00222 unsigned int lheight = pixel_height();
00223 unsigned int lwidth = pixel_width();
00224
00225 for (int pass = 0; pass < __d->number_passes; ++pass) {
00226 for (unsigned y = 0; y < lheight; ++y) {
00227 png_read_rows(__d->png_ptr, &row_pointer, png_bytepp_NULL, 1);
00228 convert_line_rgb_to_yuv422planar( row_pointer, buffer, lwidth, lheight, 0, y );
00229 }
00230 }
00231
00232
00233 png_read_end(__d->png_ptr, __d->info_ptr);
00234 png_free(__d->png_ptr, row_pointer);
00235
00236 }