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/writers/png.h>
00026 #include <fvutils/color/yuvrgb.h>
00027
00028 #include <cstdio>
00029 #include <png.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032
00033 using namespace fawkes;
00034
00035
00036
00037
00038
00039
00040 PNGWriter::PNGWriter()
00041 : Writer("png")
00042 {
00043 }
00044
00045
00046
00047
00048
00049
00050 PNGWriter::PNGWriter(const char *filename, unsigned int width, unsigned int height)
00051 : Writer("png")
00052 {
00053 set_filename(filename);
00054
00055 this->width = width;
00056 this->height = height;
00057 }
00058
00059
00060 PNGWriter::~PNGWriter()
00061 {
00062 }
00063
00064 void
00065 PNGWriter::set_buffer(colorspace_t cspace, unsigned char *buffer)
00066 {
00067 if( cspace == BGR )
00068 {
00069 __isBGR = true;
00070 this->buffer = buffer;
00071 }
00072 else if (cspace == YUV422_PLANAR) {
00073 this->buffer = buffer;
00074 __isBGR = false;
00075 } else {
00076 __isBGR = false;
00077 throw Exception("Color space not supported, can only write YUV422_PLANAR images");
00078 }
00079 }
00080
00081
00082 void
00083 PNGWriter::write()
00084 {
00085 if ( (filename == 0) ||
00086 (width == 0) ||
00087 (height == 0) ) {
00088 throw Exception("PNGWriter::write(): Illegal data, width==0 || height == 0 || filename=\"\".");
00089 }
00090
00091 FILE *fp = fopen(filename, "wb");
00092 if (!fp) {
00093 throw Exception("Could not open file for writing");
00094 }
00095
00096 png_structp png_ptr = png_create_write_struct
00097 (PNG_LIBPNG_VER_STRING,png_voidp_NULL,
00098 png_error_ptr_NULL, png_error_ptr_NULL);
00099 if (!png_ptr) {
00100 throw Exception("Could not create PNG write struct");
00101 }
00102
00103 png_infop info_ptr = png_create_info_struct(png_ptr);
00104 if (!info_ptr) {
00105 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00106 throw Exception("Could not create PNG info struct");
00107 }
00108
00109 if (setjmp(png_jmpbuf(png_ptr))) {
00110 png_destroy_write_struct(&png_ptr, &info_ptr);
00111 fclose(fp);
00112 png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
00113 throw Exception("Could not create setjmp");
00114 }
00115
00116
00117 png_init_io(png_ptr, fp);
00118
00119
00120
00121
00122 png_set_IHDR(png_ptr, info_ptr, width, height,
00123 8 , PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
00124 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
00125
00126 png_write_info(png_ptr, info_ptr);
00127
00128
00129
00130 png_byte row[width*3];
00131 png_byte *row_p;
00132 unsigned char *yp, *up, *vp;
00133 unsigned char y1, y2, u = 0, v = 0;
00134
00135
00136 yp = buffer;
00137 up = YUV422_PLANAR_U_PLANE(buffer, width, height);
00138 vp = YUV422_PLANAR_V_PLANE(buffer, width, height);
00139
00140 for (unsigned int i = 0; i < height; ++i) {
00141 if( !__isBGR ) {
00142
00143 row_p = row;
00144 for (unsigned int j = 0; j < (width / 2); ++j) {
00145 y1 = *yp++;
00146 y2 = *yp++;
00147 u = *up++;
00148 v = *vp++;
00149 pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
00150 row_p += 3;
00151 pixel_yuv_to_rgb(y2, u, v, &row_p[0], &row_p[1], &row_p[2]);
00152 row_p += 3;
00153 }
00154
00155 if ( (width % 2) == 1 ) {
00156
00157
00158 y1 = *yp++;
00159 pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
00160 }
00161 } else {
00162 convert_line_bgr_rgb( (buffer + width*3*i), row,
00163 width, height );
00164
00165 }
00166 png_write_row(png_ptr, row);
00167 }
00168
00169 png_write_end(png_ptr, info_ptr);
00170 png_destroy_write_struct(&png_ptr, &info_ptr);
00171 fclose(fp);
00172
00173 }