2
CLAW - a C++ Library Absolutely Wonderful
4
CLAW is a free library without any particular aim but being useful to
7
Copyright (C) 2005-2008 Julien Jorge
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.
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.
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
23
contact: julien_jorge@yahoo.fr
26
* \file png_reader.cpp
27
* \brief Implementation of the claw::graphic::png::reader class.
28
* \author Julien Jorge
30
#include <claw/png.hpp>
32
#include <claw/exception.hpp>
33
#include <claw/assert.hpp>
35
/*----------------------------------------------------------------------------*/
37
* \brief Read data from the input stream.
38
* \param png_ptr Informations about the PNG we are reading.
39
* \param data (out) Array of the bytes we have read.
40
* \param length Number of bytes to read.
42
void claw__graphic__png__source_manager__read
43
( png_structp png_ptr, png_bytep data, png_size_t length )
45
claw::graphic::png::reader::source_manager* self =
46
(claw::graphic::png::reader::source_manager*)png_get_io_ptr(png_ptr);
48
self->read(data, length);
49
} // claw__graphic__png__source_manager__read()
54
/*----------------------------------------------------------------------------*/
57
* \param is The stream we read from.
59
claw::graphic::png::reader::source_manager::source_manager( std::istream& is )
63
} // png::reader::source_manager::source_manager()
65
/*----------------------------------------------------------------------------*/
67
* \brief Read data from the input stream.
68
* \param data (out) Array of the bytes we have read.
69
* \param length Number of bytes to read.
71
void claw::graphic::png::reader::source_manager::read
72
( png_bytep data, png_size_t length )
74
m_input.read( (char*)data, length * sizeof(png_byte) );
75
} // png::reader::source_manager::read()
80
/*----------------------------------------------------------------------------*/
81
const unsigned int claw::graphic::png::reader::s_rgba_pixel_size = 4;
83
/*----------------------------------------------------------------------------*/
86
* \param img The image in which the data will be stored.
88
claw::graphic::png::reader::reader( image& img )
92
} // png::reader::reader()
94
/*----------------------------------------------------------------------------*/
97
* \param img The image in which the data will be stored.
98
* \param f The file from which we read the data.
99
* \post img contains the data from \a f.
101
claw::graphic::png::reader::reader( image& img, std::istream& f )
105
} // png::reader::reader()
107
/*----------------------------------------------------------------------------*/
109
* \brief Load an image from a png file.
112
void claw::graphic::png::reader::load( std::istream& f )
116
std::istream::pos_type init_pos = f.tellg();
125
f.seekg( init_pos, std::ios_base::beg );
128
} // png::reader::load()
130
/*----------------------------------------------------------------------------*/
132
* \brief Load an image from a png file.
135
void claw::graphic::png::reader::read_from_file( std::istream& f )
137
source_manager infile(f);
141
create_read_structures(png_ptr, info_ptr);
143
if (setjmp(png_jmpbuf(png_ptr)))
145
/* If we get here, we had a problem reading the file */
146
/* Free all of the memory associated with the png_ptr and info_ptr */
147
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
148
throw CLAW_EXCEPTION("Invalid PNG file.");
151
check_if_png( png_ptr, f );
153
png_set_read_fn( png_ptr, (void *)&infile,
154
claw__graphic__png__source_manager__read );
156
png_set_strip_16(png_ptr);
157
png_set_gray_1_2_4_to_8(png_ptr);
158
png_set_packing(png_ptr);
160
// transform palette index into RGB value
161
png_set_palette_to_rgb(png_ptr);
163
// add an alpha value if none
164
png_set_filler( png_ptr, std::numeric_limits<pixel32::component_type>::max(),
167
png_read_info(png_ptr, info_ptr);
168
read_image( png_ptr, info_ptr );
170
png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL);
171
} // png::reader::read_from_file()
173
/*----------------------------------------------------------------------------*/
175
* \brief Check that the stream contains a PNG file.
176
* \param png_ptr PNG file description.
177
* \param f The stream to read from.
179
void claw::graphic::png::reader::check_if_png
180
( png_structp png_ptr, std::istream& f ) const
184
const unsigned int bytes_to_check = 8;
185
png_byte buffer[bytes_to_check];
187
/* Read in some of the signature bytes */
188
f.read( (char*)buffer, bytes_to_check * sizeof(png_byte) );
190
if ( (png_sig_cmp(buffer, (png_size_t)0, bytes_to_check) != 0) || !f )
191
throw CLAW_EXCEPTION( "Not a PNG file." );
193
png_set_sig_bytes(png_ptr, bytes_to_check);
194
} // png::reader::check_if_png()
196
/*----------------------------------------------------------------------------*/
198
* \brief Read the image data of the PNG.
199
* \param png_ptr PNG file description.
200
* \param info_ptr PNG file informations.
202
void claw::graphic::png::reader::read_image
203
( png_structp png_ptr, png_infop info_ptr )
205
CLAW_PRECOND( png_ptr );
206
CLAW_PRECOND( info_ptr );
208
m_image.set_size( png_get_image_width(png_ptr, info_ptr),
209
png_get_image_height(png_ptr, info_ptr) );
211
if ( png_get_interlace_type(png_ptr, info_ptr) == PNG_INTERLACE_NONE )
212
read_sequential_image(png_ptr, info_ptr);
214
read_interlaced_image( png_ptr, info_ptr,
215
png_set_interlace_handling(png_ptr) );
216
} // png::reader::read_image()
218
/*----------------------------------------------------------------------------*/
220
* \brief Read the image data of a non interlaced PNG.
221
* \param png_ptr PNG file description.
222
* \param info_ptr PNG file informations.
224
void claw::graphic::png::reader::read_sequential_image
225
( png_structp png_ptr, png_infop info_ptr )
227
CLAW_PRECOND( png_ptr );
228
CLAW_PRECOND( info_ptr );
231
(png_bytep)png_malloc( png_ptr, s_rgba_pixel_size * m_image.width() );
235
for (unsigned int y=0; y!=m_image.height(); ++y)
237
png_read_row(png_ptr, data, NULL);
238
copy_pixel_line( data, y );
243
png_free(png_ptr, data);
247
png_free(png_ptr, data);
248
} // png::reader::read_sequential_image()
250
/*----------------------------------------------------------------------------*/
252
* \brief Read the image data of an interlaced PNG.
253
* \param png_ptr PNG file description.
254
* \param info_ptr PNG file informations.
255
* \param passes Number of passes (for interlaced images).
257
void claw::graphic::png::reader::read_interlaced_image
258
( png_structp png_ptr, png_infop info_ptr, unsigned int passes )
260
CLAW_PRECOND( passes > 1 );
261
CLAW_PRECOND( png_ptr );
262
CLAW_PRECOND( info_ptr );
264
const unsigned int row_length = s_rgba_pixel_size * m_image.width();
266
(png_bytepp)png_malloc( png_ptr, sizeof(png_bytep) * m_image.height() );
271
for (i=0; i!=m_image.height(); ++i)
273
data[i] = (png_bytep)png_malloc( png_ptr, row_length );
276
throw std::bad_alloc();
278
copy_pixel_line( data[i], i );
281
for (unsigned int p=0; p!=passes; ++p)
282
png_read_rows( png_ptr, data, NULL, m_image.height() );
284
for (unsigned int y=0; y!=m_image.height(); ++y)
285
copy_pixel_line( data[y], y );
289
for(unsigned int j=0; j!=i; ++j)
290
png_free(png_ptr, data[j]);
292
png_free(png_ptr, data);
296
for(i=0; i!=m_image.height(); ++i)
297
png_free(png_ptr, data[i]);
299
png_free(png_ptr, data);
300
} // png::reader::read_interlaced_image()
302
/*----------------------------------------------------------------------------*/
304
* \brief Copy the pixels taken from the PNG to the image.
305
* \param data the pixels from the PNG image.
306
* \param y Index of the line of the image in which we copy the pixels.
309
claw::graphic::png::reader::copy_pixel_line( png_bytep data, unsigned int y )
311
CLAW_PRECOND( data );
312
CLAW_PRECOND( y < m_image.height() );
314
// four bytes for each pixel in the line
315
for (unsigned int x=0; x!=m_image.width(); ++x, data+=s_rgba_pixel_size)
317
m_image[y][x].components.red = data[0];
318
m_image[y][x].components.green = data[1];
319
m_image[y][x].components.blue = data[2];
320
m_image[y][x].components.alpha = data[3];
322
} // png::reader::copy_pixel_line()
324
/*----------------------------------------------------------------------------*/
326
* \brief Initialize the png read structures.
327
* \param png_ptr PNG file description.
328
* \param info_ptr PNG file informations.
330
void claw::graphic::png::reader::create_read_structures
331
( png_structp& png_ptr, png_infop& info_ptr ) const
333
png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
337
info_ptr = png_create_info_struct(png_ptr);
340
png_destroy_read_struct(&png_ptr, png_infopp_NULL, png_infopp_NULL);
343
if (!png_ptr || !info_ptr)
344
throw CLAW_EXCEPTION("Can't create PNG read structures.");
345
} // png::reader::create_read_structures()