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 && cspace != RGB && cspace != YUV422_PLANAR) {
73  throw Exception("Color space not supported, can only write YUV422_PLANAR images");
74  }
75  this->buffer = buffer;
76  colorspace_ = cspace;
77 }
78 
79 
80 void
82 {
83  if ( (filename == 0) ||
84  (width == 0) ||
85  (height == 0) ) {
86  throw Exception("PNGWriter::write(): Illegal data, width==0 || height == 0 || filename=\"\".");
87  }
88 
89  FILE *fp = fopen(filename, "wb");
90  if (!fp) {
91  throw Exception("Could not open file for writing");
92  }
93 
94  png_structp png_ptr = png_create_write_struct
95  (PNG_LIBPNG_VER_STRING,(png_voidp)NULL,
96  (png_error_ptr)NULL, (png_error_ptr)NULL);
97  if (!png_ptr) {
98  throw Exception("Could not create PNG write struct");
99  }
100 
101  png_infop info_ptr = png_create_info_struct(png_ptr);
102  if (!info_ptr) {
103  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
104  throw Exception("Could not create PNG info struct");
105  }
106 
107  if (setjmp(png_jmpbuf(png_ptr))) {
108  png_destroy_write_struct(&png_ptr, &info_ptr);
109  fclose(fp);
110  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
111  throw Exception("Could not create setjmp");
112  }
113 
114  // Use default io via fwrite
115  png_init_io(png_ptr, fp);
116 
117  // Can be used to get informed about progress
118  // png_set_write_status_fn(png_ptr, write_row_callback);
119 
120  png_set_IHDR(png_ptr, info_ptr, width, height,
121  8 /* bit per channel */, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
122  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
123 
124  png_write_info(png_ptr, info_ptr);
125 
126  // png_byte == unsigned char, create one row, three bytes
127  // png_byte row[width * 3];
128  png_byte row[width*3];
129  png_byte *row_p;
130  unsigned char *yp, *up, *vp;
131  unsigned char y1, y2, u = 0, v = 0;
132 
133 
134  yp = buffer;
135  up = YUV422_PLANAR_U_PLANE(buffer, width, height);
136  vp = YUV422_PLANAR_V_PLANE(buffer, width, height);
137 
138  for (unsigned int i = 0; i < height; ++i) {
139  if( colorspace_ == YUV422_PLANAR ) {
140  // pack row
141  row_p = row;
142  for (unsigned int j = 0; j < (width / 2); ++j) {
143  y1 = *yp++;
144  y2 = *yp++;
145  u = *up++;
146  v = *vp++;
147  pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
148  row_p += 3;
149  pixel_yuv_to_rgb(y2, u, v, &row_p[0], &row_p[1], &row_p[2]);
150  row_p += 3;
151  }
152 
153  if ( (width % 2) == 1 ) {
154  // odd number of columns, we have to take care of this
155  // use last u,v values and new y value for this
156  y1 = *yp++;
157  pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
158  }
159  } else if (colorspace_ == BGR) {
160  convert_line_bgr_rgb( (buffer + width*3*i), row,
161  width, height );
162 
163  } else { // RGB
164  memcpy(row, (buffer + width*3*i), width*3);
165  }
166  png_write_row(png_ptr, row);
167  }
168 
169  png_write_end(png_ptr, info_ptr);
170  png_destroy_write_struct(&png_ptr, &info_ptr);
171  fclose(fp);
172 
173 }
174 
175 } // 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:81
~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