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