Fawkes API
Fawkes Development Version
|
00001 00002 /*************************************************************************** 00003 * png.cpp - Implementation of a PNG writer 00004 * 00005 * Generated: Thu Jun 02 15:23:56 2005 00006 * Copyright 2005-2007 Tim Niemueller [www.niemueller.de] 00007 * 00008 ****************************************************************************/ 00009 00010 /* This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. A runtime exception applies to 00014 * this software (see LICENSE.GPL_WRE file mentioned below for details). 00015 * 00016 * This program is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Library General Public License for more details. 00020 * 00021 * Read the full text in the LICENSE.GPL_WRE file in the doc directory. 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 /* just to make Emacs auto-indent happy */ 00037 } 00038 #endif 00039 00040 /** @class PNGWriter <fvutils/writers/png.h> 00041 * PNG file writer. 00042 */ 00043 00044 /** Constructor. */ 00045 PNGWriter::PNGWriter() 00046 : Writer("png") 00047 { 00048 } 00049 00050 /** Constructor. 00051 * @param filename filename 00052 * @param width width 00053 * @param height height 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 /** Destructor. */ 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 // Use default io via fwrite 00122 png_init_io(png_ptr, fp); 00123 00124 // Can be used to get informed about progress 00125 // png_set_write_status_fn(png_ptr, write_row_callback); 00126 00127 png_set_IHDR(png_ptr, info_ptr, width, height, 00128 8 /* bit per channel */, 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 // png_byte == unsigned char, create one row, three bytes 00134 // png_byte row[width * 3]; 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 // pack row 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 // odd number of columns, we have to take care of this 00162 // use last u,v values and new y value for this 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 } // end namespace firevision