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
33using namespace fawkes;
34
35namespace firevision {
36
37/** @class PNGWriter <fvutils/writers/png.h>
38 * PNG file writer.
39 */
40
41/** Constructor. */
43{
44}
45
46/** Constructor.
47 * @param filename filename
48 * @param width width
49 * @param height height
50 */
51PNGWriter::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
64void
65PNGWriter::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
74void
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
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual void set_buffer(colorspace_t cspace, unsigned char *buffer)
Set image buffer.
Definition: png.cpp:65
~PNGWriter()
Destructor.
Definition: png.cpp:60
PNGWriter()
Constructor.
Definition: png.cpp:42
virtual void write()
Write to file.
Definition: png.cpp:75
Interface to write images.
Definition: writer.h:32
unsigned int width
The width of the image.
Definition: writer.h:49
colorspace_t cspace
The colorspace of the image.
Definition: writer.h:52
virtual void set_filename(const char *filename)
Set filename.
Definition: writer.cpp:102
unsigned char * buffer
The image-buffer.
Definition: writer.h:54
unsigned int height
The height of the image.
Definition: writer.h:50
char * filename
The complete filename.
Definition: writer.h:45
Fawkes library namespace.