Fawkes API  Fawkes Development Version
png.cpp
1 
2 /***************************************************************************
3  * png.cpp - Implementation of a PNG writer
4  *
5  * Generated: Thu Jun 02 15:23:56 2005
6  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <core/exception.h>
25 #include <fvutils/writers/png.h>
26 #include <fvutils/color/yuvrgb.h>
27 
28 #include <cstdio>
29 #include <png.h>
30 #include <string.h>
31 #include <stdlib.h>
32 
33 using namespace fawkes;
34 
35 namespace firevision {
36 #if 0 /* just to make Emacs auto-indent happy */
37 }
38 #endif
39 
40 /** @class PNGWriter <fvutils/writers/png.h>
41  * PNG file writer.
42  */
43 
44 /** Constructor. */
45 PNGWriter::PNGWriter()
46  : Writer("png")
47 {
48 }
49 
50 /** Constructor.
51  * @param filename filename
52  * @param width width
53  * @param height height
54  */
55 PNGWriter::PNGWriter(const char *filename, unsigned int width, unsigned int height)
56  : Writer("png")
57 {
58  set_filename(filename);
59 
60  this->width = width;
61  this->height = height;
62 }
63 
64 /** Destructor. */
66 {
67 }
68 
69 void
70 PNGWriter::set_buffer(colorspace_t cspace, unsigned char *buffer)
71 {
72  if( cspace == BGR )
73  {
74  __isBGR = true;
75  this->buffer = buffer;
76  }
77  else if (cspace == YUV422_PLANAR) {
78  this->buffer = buffer;
79  __isBGR = false;
80  } else {
81  __isBGR = false;
82  throw Exception("Color space not supported, can only write YUV422_PLANAR images");
83  }
84 }
85 
86 
87 void
89 {
90  if ( (filename == 0) ||
91  (width == 0) ||
92  (height == 0) ) {
93  throw Exception("PNGWriter::write(): Illegal data, width==0 || height == 0 || filename=\"\".");
94  }
95 
96  FILE *fp = fopen(filename, "wb");
97  if (!fp) {
98  throw Exception("Could not open file for writing");
99  }
100 
101  png_structp png_ptr = png_create_write_struct
102  (PNG_LIBPNG_VER_STRING,(png_voidp)NULL,
103  (png_error_ptr)NULL, (png_error_ptr)NULL);
104  if (!png_ptr) {
105  throw Exception("Could not create PNG write struct");
106  }
107 
108  png_infop info_ptr = png_create_info_struct(png_ptr);
109  if (!info_ptr) {
110  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
111  throw Exception("Could not create PNG info struct");
112  }
113 
114  if (setjmp(png_jmpbuf(png_ptr))) {
115  png_destroy_write_struct(&png_ptr, &info_ptr);
116  fclose(fp);
117  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
118  throw Exception("Could not create setjmp");
119  }
120 
121  // Use default io via fwrite
122  png_init_io(png_ptr, fp);
123 
124  // Can be used to get informed about progress
125  // png_set_write_status_fn(png_ptr, write_row_callback);
126 
127  png_set_IHDR(png_ptr, info_ptr, width, height,
128  8 /* bit per channel */, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
129  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
130 
131  png_write_info(png_ptr, info_ptr);
132 
133  // png_byte == unsigned char, create one row, three bytes
134  // png_byte row[width * 3];
135  png_byte row[width*3];
136  png_byte *row_p;
137  unsigned char *yp, *up, *vp;
138  unsigned char y1, y2, u = 0, v = 0;
139 
140 
141  yp = buffer;
142  up = YUV422_PLANAR_U_PLANE(buffer, width, height);
143  vp = YUV422_PLANAR_V_PLANE(buffer, width, height);
144 
145  for (unsigned int i = 0; i < height; ++i) {
146  if( !__isBGR ) {
147  // pack row
148  row_p = row;
149  for (unsigned int j = 0; j < (width / 2); ++j) {
150  y1 = *yp++;
151  y2 = *yp++;
152  u = *up++;
153  v = *vp++;
154  pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
155  row_p += 3;
156  pixel_yuv_to_rgb(y2, u, v, &row_p[0], &row_p[1], &row_p[2]);
157  row_p += 3;
158  }
159 
160  if ( (width % 2) == 1 ) {
161  // odd number of columns, we have to take care of this
162  // use last u,v values and new y value for this
163  y1 = *yp++;
164  pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
165  }
166  } else {
167  convert_line_bgr_rgb( (buffer + width*3*i), row,
168  width, height );
169 
170  }
171  png_write_row(png_ptr, row);
172  }
173 
174  png_write_end(png_ptr, info_ptr);
175  png_destroy_write_struct(&png_ptr, &info_ptr);
176  fclose(fp);
177 
178 }
179 
180 } // end namespace firevision
colorspace_t cspace
The colorspace of the image.
Definition: writer.h:55
Fawkes library namespace.
PNGWriter()
Constructor.
Definition: png.cpp:45
Interface to write images.
Definition: writer.h:34
virtual void write()
Write to file.
Definition: png.cpp:88
~PNGWriter()
Destructor.
Definition: png.cpp:65
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void set_filename(const char *filename)
Set filename.
Definition: writer.cpp:106
unsigned int width
The width of the image.
Definition: writer.h:52
unsigned char * buffer
The image-buffer.
Definition: writer.h:57
virtual void set_buffer(colorspace_t cspace, unsigned char *buffer)
Set image buffer.
Definition: png.cpp:70
unsigned int height
The height of the image.
Definition: writer.h:53
char * filename
The complete filename.
Definition: writer.h:48