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/color/yuvrgb.h>
26 #include <fvutils/writers/png.h>
27 
28 #include <cstdio>
29 #include <png.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 using namespace fawkes;
34 
35 namespace firevision {
36 
37 /** @class PNGWriter <fvutils/writers/png.h>
38  * PNG file writer.
39  */
40 
41 /** Constructor. */
42 PNGWriter::PNGWriter() : Writer("png")
43 {
44 }
45 
46 /** Constructor.
47  * @param filename filename
48  * @param width width
49  * @param height height
50  */
51 PNGWriter::PNGWriter(const char *filename, unsigned int width, unsigned int height) : Writer("png")
52 {
54 
55  this->width = width;
56  this->height = height;
57 }
58 
59 /** Destructor. */
61 {
62 }
63 
64 void
65 PNGWriter::set_buffer(colorspace_t cspace, unsigned char *buffer)
66 {
67  if (cspace != BGR && cspace != RGB && cspace != YUV422_PLANAR) {
68  throw Exception("Color space not supported, can only write YUV422_PLANAR images");
69  }
70  this->buffer = buffer;
71  colorspace_ = cspace;
72 }
73 
74 void
76 {
77  if ((filename == 0) || (width == 0) || (height == 0)) {
78  throw Exception("PNGWriter::write(): Illegal data, width==0 || height == 0 || filename=\"\".");
79  }
80 
81  FILE *fp = fopen(filename, "wb");
82  if (!fp) {
83  throw Exception("Could not open file for writing");
84  }
85 
86  png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,
87  (png_voidp)NULL,
88  (png_error_ptr)NULL,
89  (png_error_ptr)NULL);
90  if (!png_ptr) {
91  throw Exception("Could not create PNG write struct");
92  }
93 
94  png_infop info_ptr = png_create_info_struct(png_ptr);
95  if (!info_ptr) {
96  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
97  throw Exception("Could not create PNG info struct");
98  }
99 
100  if (setjmp(png_jmpbuf(png_ptr))) {
101  png_destroy_write_struct(&png_ptr, &info_ptr);
102  fclose(fp);
103  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
104  throw Exception("Could not create setjmp");
105  }
106 
107  // Use default io via fwrite
108  png_init_io(png_ptr, fp);
109 
110  // Can be used to get informed about progress
111  // png_set_write_status_fn(png_ptr, write_row_callback);
112 
113  png_set_IHDR(png_ptr,
114  info_ptr,
115  width,
116  height,
117  8 /* bit per channel */,
118  PNG_COLOR_TYPE_RGB,
119  PNG_INTERLACE_NONE,
120  PNG_COMPRESSION_TYPE_DEFAULT,
121  PNG_FILTER_TYPE_DEFAULT);
122 
123  png_write_info(png_ptr, info_ptr);
124 
125  // png_byte == unsigned char, create one row, three bytes
126  // png_byte row[width * 3];
127  png_byte row[width * 3];
128  png_byte * row_p;
129  unsigned char *yp, *up, *vp;
130  unsigned char y1, y2, u = 0, v = 0;
131 
132  yp = buffer;
133  up = YUV422_PLANAR_U_PLANE(buffer, width, height);
134  vp = YUV422_PLANAR_V_PLANE(buffer, width, height);
135 
136  for (unsigned int i = 0; i < height; ++i) {
137  if (colorspace_ == YUV422_PLANAR) {
138  // pack row
139  row_p = row;
140  for (unsigned int j = 0; j < (width / 2); ++j) {
141  y1 = *yp++;
142  y2 = *yp++;
143  u = *up++;
144  v = *vp++;
145  pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
146  row_p += 3;
147  pixel_yuv_to_rgb(y2, u, v, &row_p[0], &row_p[1], &row_p[2]);
148  row_p += 3;
149  }
150 
151  if ((width % 2) == 1) {
152  // odd number of columns, we have to take care of this
153  // use last u,v values and new y value for this
154  y1 = *yp++;
155  pixel_yuv_to_rgb(y1, u, v, &row_p[0], &row_p[1], &row_p[2]);
156  }
157  } else if (colorspace_ == BGR) {
158  convert_line_bgr_rgb((buffer + width * 3 * i), row, width, height);
159 
160  } else { // RGB
161  memcpy(row, (buffer + width * 3 * i), width * 3);
162  }
163  png_write_row(png_ptr, row);
164  }
165 
166  png_write_end(png_ptr, info_ptr);
167  png_destroy_write_struct(&png_ptr, &info_ptr);
168  fclose(fp);
169 }
170 
171 } // end namespace firevision
colorspace_t cspace
The colorspace of the image.
Definition: writer.h:52
Fawkes library namespace.
PNGWriter()
Constructor.
Definition: png.cpp:42
Interface to write images.
Definition: writer.h:31
virtual void write()
Write to file.
Definition: png.cpp:75
~PNGWriter()
Destructor.
Definition: png.cpp:60
Base class for exceptions in Fawkes.
Definition: exception.h:35
virtual void set_filename(const char *filename)
Set filename.
Definition: writer.cpp:102
unsigned int width
The width of the image.
Definition: writer.h:49
unsigned char * buffer
The image-buffer.
Definition: writer.h:54
virtual void set_buffer(colorspace_t cspace, unsigned char *buffer)
Set image buffer.
Definition: png.cpp:65
unsigned int height
The height of the image.
Definition: writer.h:50
char * filename
The complete filename.
Definition: writer.h:45