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