png_writer.cpp
Go to the documentation of this file.
/*
CLAW - a C++ Library Absolutely Wonderful
CLAW is a free library without any particular aim but being useful to
anyone.
Copyright (C) 2005-2011 Julien Jorge
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
contact: julien.jorge@gamned.org
*/
#include <claw/png.hpp>
#include <claw/exception.hpp>
#include <claw/assert.hpp>
/*----------------------------------------------------------------------------*/
void claw__graphic__png__target_manager__write
( png_structp png_ptr, png_bytep data, png_size_t length )
{
claw::graphic::png::writer::target_manager* self =
(claw::graphic::png::writer::target_manager*)png_get_io_ptr(png_ptr);
self->write(data, length);
} // claw__graphic__png__target_manager__write()
/*----------------------------------------------------------------------------*/
void claw__graphic__png__target_manager__flush( png_structp png_ptr )
{
claw::graphic::png::writer::target_manager* self =
(claw::graphic::png::writer::target_manager*)png_get_io_ptr(png_ptr);
self->flush();
} // claw__graphic__png__target_manager__write()
/*----------------------------------------------------------------------------*/
claw::graphic::png::writer::target_manager::target_manager( std::ostream& os )
: m_output(os)
{
CLAW_PRECOND( !!os );
} // png::writer::target_manager::target_manager()
/*----------------------------------------------------------------------------*/
void claw::graphic::png::writer::target_manager::write
( png_bytep data, png_size_t length )
{
m_output.write( (char*)data, length * sizeof(png_byte) );
} // png::writer::target_manager::write()
/*----------------------------------------------------------------------------*/
void claw::graphic::png::writer::target_manager::flush()
{
m_output.flush();
} // png::writer::target_manager::flush()
/*----------------------------------------------------------------------------*/
claw::graphic::png::writer::options::options()
: compression(default_compression), interlace(none)
{
} // png::writer::options::options()
/*----------------------------------------------------------------------------*/
claw::graphic::png::writer::options::options
( compression_level compression_level_, interlace_type interlace_ )
: compression(compression_level_), interlace(interlace_)
{
} // png::writer::options::options()
/*----------------------------------------------------------------------------*/
const unsigned int claw::graphic::png::writer::s_rgba_pixel_size = 4;
/*----------------------------------------------------------------------------*/
claw::graphic::png::writer::writer( const image& img )
: m_image( img )
{
} // png::writer::writer()
/*----------------------------------------------------------------------------*/
claw::graphic::png::writer::writer
( const image& img, std::ostream& f, const options& opt )
: m_image( img )
{
save(f, opt);
} // png::writer::writer()
/*----------------------------------------------------------------------------*/
void
claw::graphic::png::writer::save( std::ostream& f, const options& opt ) const
{
CLAW_PRECOND( !!f );
target_manager outfile(f);
png_structp png_ptr;
png_infop info_ptr;
create_write_structures(png_ptr, info_ptr);
if (setjmp(png_jmpbuf(png_ptr)))
{
/* If we get here, we had a problem reading the file */
/* Free all of the memory associated with the png_ptr and info_ptr */
png_destroy_write_struct(&png_ptr, &info_ptr);
throw CLAW_EXCEPTION("Invalid PNG file.");
}
png_set_write_fn( png_ptr, (void *)&outfile,
claw__graphic__png__target_manager__write,
claw__graphic__png__target_manager__flush );
set_options( png_ptr, info_ptr, opt );
save_image( png_ptr, info_ptr );
png_destroy_write_struct(&png_ptr, &info_ptr);
} // png::writer::save()
/*----------------------------------------------------------------------------*/
void claw::graphic::png::writer::set_options
( png_structp png_ptr, png_infop info_ptr, const options& opt ) const
{
CLAW_PRECOND( png_ptr );
CLAW_PRECOND( info_ptr );
png_set_compression_level( png_ptr, opt.compression );
png_set_IHDR( png_ptr, info_ptr, m_image.width(), m_image.height(),
sizeof(pixel_type::component_type) * 8, /* 8 bits per byte */
PNG_COLOR_TYPE_RGB_ALPHA,
opt.interlace, PNG_COMPRESSION_TYPE_DEFAULT,
PNG_FILTER_TYPE_DEFAULT );
} // png::writer::set_options()
/*----------------------------------------------------------------------------*/
void claw::graphic::png::writer::save_image
( png_structp png_ptr, png_infop info_ptr ) const
{
CLAW_PRECOND( png_ptr );
CLAW_PRECOND( info_ptr );
const unsigned int row_length = s_rgba_pixel_size * m_image.width();
png_bytepp data =
(png_bytepp)png_malloc( png_ptr, sizeof(png_bytep) * m_image.height() );
unsigned int i=0;
try
{
for (i=0; i!=m_image.height(); ++i)
{
data[i] = (png_bytep)png_malloc( png_ptr, row_length );
if (!data[i])
throw std::bad_alloc();
copy_pixel_line( data[i], i );
}
png_set_rows(png_ptr, info_ptr, data);
png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
}
catch(...)
{
for(unsigned int j=0; j!=i; ++j)
png_free(png_ptr, data[j]);
png_free(png_ptr, data);
throw;
}
for(i=0; i!=m_image.height(); ++i)
png_free(png_ptr, data[i]);
png_free(png_ptr, data);
} // png::writer::save_image()
/*----------------------------------------------------------------------------*/
void claw::graphic::png::writer::copy_pixel_line
( png_bytep data, unsigned int y ) const
{
CLAW_PRECOND( data );
CLAW_PRECOND( y < m_image.height() );
// four bytes for each pixel in the line
for (unsigned int x=0; x!=m_image.width(); ++x, data+=s_rgba_pixel_size)
{
data[0] = m_image[y][x].components.red;
data[1] = m_image[y][x].components.green;
data[2] = m_image[y][x].components.blue;
data[3] = m_image[y][x].components.alpha;
}
} // png::writer::copy_pixel_line()
/*----------------------------------------------------------------------------*/
void claw::graphic::png::writer::create_write_structures
( png_structp& png_ptr, png_infop& info_ptr ) const
{
png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (png_ptr)
{
info_ptr = png_create_info_struct(png_ptr);
if (!info_ptr)
png_destroy_write_struct(&png_ptr, (png_infopp)NULL);
}
if (!png_ptr || !info_ptr)
throw CLAW_EXCEPTION("Can't create PNG write structures.");
} // png::writer::create_write_structures()
claw::graphic::png::writer::options::compression_level
compression_level
Compression level in the interlaced image.
Definition: png.hpp:125
claw::graphic::png::writer::options::options
options()
Default constructor.
Definition: png_writer.cpp:106
claw::graphic::png::writer::save
void save(std::ostream &f, const options &opt=options()) const
Save the image in a PNG file.
Definition: png_writer.cpp:163
claw::graphic::png::writer::options::interlace_type
interlace_type
The algorithm to use to interlace the saved image.
Definition: png.hpp:134
claw::graphic::image::height
unsigned int height() const
Gets image&#39;s height.
Definition: image.cpp:159
claw__graphic__png__target_manager__flush
void claw__graphic__png__target_manager__flush(png_structp png_ptr)
Flush the output stream.
Definition: png_writer.cpp:56
claw::graphic::png::writer::target_manager::write
void write(png_bytep data, png_size_t length)
Write data in the ouput stream.
Definition: png_writer.cpp:85
png.hpp
A class for png pictures.
claw::graphic::png::writer::target_manager
Target manager that allow us to write in a std::ostream.
Definition: png.hpp:165
claw::graphic::image::width
unsigned int width() const
Gets image&#39;s width.
Definition: image.cpp:147
claw::graphic::png::writer::writer
writer(const image &img)
Constructor.
Definition: png_writer.cpp:136
exception.hpp
A simple class to use as exception with string message.
claw::graphic::png::writer::target_manager::flush
void flush()
Flush the output stream.
Definition: png_writer.cpp:94
claw::graphic::rgba_pixel::component_type
unsigned char component_type
The type of the components of the color.
Definition: pixel.hpp:82
assert.hpp
Some assert macros to strengthen you code.
claw::graphic::png::writer::options::compression
compression_level compression
Compression level to use in the saved stream.
Definition: png.hpp:151
claw::graphic::png::writer::target_manager::target_manager
target_manager(std::ostream &os)
Constructor.
Definition: png_writer.cpp:72
claw::graphic::png::writer::options::interlace
interlace_type interlace
Interlace method to apply to the saved image.
Definition: png.hpp:154
claw::graphic::image
A class to deal with images.
Definition: image.hpp:49
claw::graphic::png::writer::options
Parameters of the writing algorithm.
Definition: png.hpp:121
CLAW_EXCEPTION
#define CLAW_EXCEPTION(m)
Create an exception and add the name of the current function to the message.
Definition: exception.hpp:90
CLAW_PRECOND
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition: assert.hpp:98
claw__graphic__png__target_manager__write
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:43