claw  1.9.0
png_writer.cpp
Go to the documentation of this file.
1 /*
2  CLAW - a C++ Library Absolutely Wonderful
3 
4  CLAW is a free library without any particular aim but being useful to
5  anyone.
6 
7  Copyright (C) 2005-2011 Julien Jorge
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 
23  contact: julien.jorge@stuff-o-matic.com
24 */
30 #include <claw/graphic/png.hpp>
31 
32 #include <claw/assert.hpp>
33 #include <claw/exception.hpp>
34 
42  png_bytep data,
43  png_size_t length)
44 {
46  = (claw::graphic::png::writer::target_manager*)png_get_io_ptr(png_ptr);
47 
48  self->write(data, length);
49 }
50 
56 {
58  = (claw::graphic::png::writer::target_manager*)png_get_io_ptr(png_ptr);
59 
60  self->flush();
61 }
62 
68  : m_output(os)
69 {
70  CLAW_PRECOND(!!os);
71 }
72 
79  png_size_t length)
80 {
81  m_output.write((char*)data, length * sizeof(png_byte));
82 }
83 
88 {
89  m_output.flush();
90 }
91 
96  : compression(default_compression)
97  , interlace(none)
98 {}
99 
106  compression_level compression_level_, interlace_type interlace_)
107  : compression(compression_level_)
108  , interlace(interlace_)
109 {}
110 
111 const unsigned int claw::graphic::png::writer::s_rgba_pixel_size = 4;
112 
118  : m_image(img)
119 {}
120 
127 claw::graphic::png::writer::writer(const image& img, std::ostream& f,
128  const options& opt)
129  : m_image(img)
130 {
131  save(f, opt);
132 }
133 
139 void claw::graphic::png::writer::save(std::ostream& f,
140  const options& opt) const
141 {
142  CLAW_PRECOND(!!f);
143 
144  target_manager outfile(f);
145  png_structp png_ptr;
146  png_infop info_ptr;
147 
148  create_write_structures(png_ptr, info_ptr);
149 
150  if(setjmp(png_jmpbuf(png_ptr)))
151  {
152  /* If we get here, we had a problem reading the file */
153  /* Free all of the memory associated with the png_ptr and info_ptr */
154  png_destroy_write_struct(&png_ptr, &info_ptr);
155  throw CLAW_EXCEPTION("Invalid PNG file.");
156  }
157 
158  png_set_write_fn(png_ptr, (void*)&outfile,
161 
162  set_options(png_ptr, info_ptr, opt);
163  save_image(png_ptr, info_ptr);
164 
165  png_destroy_write_struct(&png_ptr, &info_ptr);
166 }
167 
174 void claw::graphic::png::writer::set_options(png_structp png_ptr,
175  png_infop info_ptr,
176  const options& opt) const
177 {
178  CLAW_PRECOND(png_ptr);
179  CLAW_PRECOND(info_ptr);
180 
181  png_set_compression_level(png_ptr, opt.compression);
182 
183  png_set_IHDR(png_ptr, info_ptr, m_image.width(), m_image.height(),
184  sizeof(pixel_type::component_type) * 8, /* 8 bits per byte */
185  PNG_COLOR_TYPE_RGB_ALPHA, opt.interlace,
186  PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
187 }
188 
194 void claw::graphic::png::writer::save_image(png_structp png_ptr,
195  png_infop info_ptr) const
196 {
197  CLAW_PRECOND(png_ptr);
198  CLAW_PRECOND(info_ptr);
199 
200  const unsigned int row_length = s_rgba_pixel_size * m_image.width();
201  png_bytepp data
202  = (png_bytepp)png_malloc(png_ptr, sizeof(png_bytep) * m_image.height());
203  unsigned int i = 0;
204 
205  try
206  {
207  for(i = 0; i != m_image.height(); ++i)
208  {
209  data[i] = (png_bytep)png_malloc(png_ptr, row_length);
210 
211  if(!data[i])
212  throw std::bad_alloc();
213 
214  copy_pixel_line(data[i], i);
215  }
216 
217  png_set_rows(png_ptr, info_ptr, data);
218  png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
219  }
220  catch(...)
221  {
222  for(unsigned int j = 0; j != i; ++j)
223  png_free(png_ptr, data[j]);
224 
225  png_free(png_ptr, data);
226  throw;
227  }
228 
229  for(i = 0; i != m_image.height(); ++i)
230  png_free(png_ptr, data[i]);
231 
232  png_free(png_ptr, data);
233 }
234 
241 void claw::graphic::png::writer::copy_pixel_line(png_bytep data,
242  unsigned int y) const
243 {
244  CLAW_PRECOND(data);
245  CLAW_PRECOND(y < m_image.height());
246 
247  // four bytes for each pixel in the line
248  for(unsigned int x = 0; x != m_image.width(); ++x, data += s_rgba_pixel_size)
249  {
250  data[0] = m_image[y][x].components.red;
251  data[1] = m_image[y][x].components.green;
252  data[2] = m_image[y][x].components.blue;
253  data[3] = m_image[y][x].components.alpha;
254  }
255 }
256 
262 void claw::graphic::png::writer::create_write_structures(
263  png_structp& png_ptr, png_infop& info_ptr) const
264 {
265  png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
266 
267  if(png_ptr)
268  {
269  info_ptr = png_create_info_struct(png_ptr);
270 
271  if(!info_ptr)
272  png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
273  }
274 
275  if(!png_ptr || !info_ptr)
276  throw CLAW_EXCEPTION("Can't create PNG write structures.");
277 }
compression_level
Compression level in the interlaced image.
Definition: png.hpp:122
options()
Default constructor.
Definition: png_writer.cpp:95
void save(std::ostream &f, const options &opt=options()) const
Save the image in a PNG file.
Definition: png_writer.cpp:139
interlace_type
The algorithm to use to interlace the saved image.
Definition: png.hpp:131
void claw__graphic__png__target_manager__flush(png_structp png_ptr)
Flush the output stream.
Definition: png_writer.cpp:55
void write(png_bytep data, png_size_t length)
Write data in the ouput stream.
Definition: png_writer.cpp:78
A class for png pictures.
Target manager that allow us to write in a std::ostream.
Definition: png.hpp:161
writer(const image &img)
Constructor.
Definition: png_writer.cpp:117
A simple class to use as exception with string message.
void flush()
Flush the output stream.
Definition: png_writer.cpp:87
unsigned char component_type
The type of the components of the color.
Definition: pixel.hpp:82
Some assert macros to strengthen you code.
target_manager(std::ostream &os)
Constructor.
Definition: png_writer.cpp:67
A class to deal with images.
Definition: image.hpp:50
Parameters of the writing algorithm.
Definition: png.hpp:118
#define CLAW_EXCEPTION(m)
Create an exception and add the name of the current function to the message.
Definition: exception.hpp:92
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition: assert.hpp:94
void claw__graphic__png__target_manager__write(png_structp png_ptr, png_bytep data, png_size_t length)
Write data in the ouput stream.
Definition: png_writer.cpp:41