png.cpp

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

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1