png_writer.cpp

Go to the documentation of this file.
00001 /*
00002   CLAW - a C++ Library Absolutely Wonderful
00003 
00004   CLAW is a free library without any particular aim but being useful to 
00005   anyone.
00006 
00007   Copyright (C) 2005-2008 Julien Jorge
00008 
00009   This library is free software; you can redistribute it and/or
00010   modify it under the terms of the GNU Lesser General Public
00011   License as published by the Free Software Foundation; either
00012   version 2.1 of the License, or (at your option) any later version.
00013 
00014   This library is distributed in the hope that it will be useful,
00015   but WITHOUT ANY WARRANTY; without even the implied warranty of
00016   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017   Lesser General Public License for more details.
00018 
00019   You should have received a copy of the GNU Lesser General Public
00020   License along with this library; if not, write to the Free Software
00021   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00022 
00023   contact: julien_jorge@yahoo.fr
00024 */
00030 #include <claw/png.hpp>
00031 
00032 #include <claw/exception.hpp>
00033 #include <claw/assert.hpp>
00034 
00035 /*----------------------------------------------------------------------------*/
00042 void claw__graphic__png__target_manager__write
00043 ( png_structp png_ptr, png_bytep data, png_size_t length )
00044 {
00045   claw::graphic::png::writer::target_manager* self =
00046     (claw::graphic::png::writer::target_manager*)png_get_io_ptr(png_ptr);
00047 
00048   self->write(data, length);
00049 } // claw__graphic__png__target_manager__write()
00050 
00051 /*----------------------------------------------------------------------------*/
00056 void claw__graphic__png__target_manager__flush( png_structp png_ptr )
00057 {
00058   claw::graphic::png::writer::target_manager* self =
00059     (claw::graphic::png::writer::target_manager*)png_get_io_ptr(png_ptr);
00060 
00061   self->flush();
00062 } // claw__graphic__png__target_manager__write()
00063 
00064 
00065 
00066 
00067 /*----------------------------------------------------------------------------*/
00072 claw::graphic::png::writer::target_manager::target_manager( std::ostream& os )
00073   : m_output(os)
00074 {
00075   CLAW_PRECOND( !!os );
00076 } // png::writer::target_manager::target_manager()
00077 
00078 /*----------------------------------------------------------------------------*/
00084 void claw::graphic::png::writer::target_manager::write
00085 ( png_bytep data, png_size_t length )
00086 {
00087   m_output.write( (char*)data, length * sizeof(png_byte) );
00088 } // png::writer::target_manager::write()
00089 
00090 /*----------------------------------------------------------------------------*/
00094 void claw::graphic::png::writer::target_manager::flush()
00095 {
00096   m_output.flush();
00097 } // png::writer::target_manager::flush()
00098 
00099 
00100 
00101 
00102 /*----------------------------------------------------------------------------*/
00106 claw::graphic::png::writer::options::options()
00107   : compression(default_compression), interlace(none)
00108 {
00109 
00110 } // png::writer::options::options()
00111 
00112 /*----------------------------------------------------------------------------*/
00118 claw::graphic::png::writer::options::options
00119 ( compression_level compression_level_, interlace_type interlace_ )
00120   : compression(compression_level_), interlace(interlace_)
00121 {
00122 
00123 } // png::writer::options::options()
00124 
00125 
00126 
00127 
00128 /*----------------------------------------------------------------------------*/
00129 const unsigned int claw::graphic::png::writer::s_rgba_pixel_size = 4;
00130 
00131 /*----------------------------------------------------------------------------*/
00136 claw::graphic::png::writer::writer( const image& img )
00137   : m_image( img )
00138 {
00139 
00140 } // png::writer::writer()
00141 
00142 /*----------------------------------------------------------------------------*/
00149 claw::graphic::png::writer::writer
00150 ( const image& img, std::ostream& f, const options& opt )
00151   : m_image( img )
00152 {
00153   save(f, opt);
00154 } // png::writer::writer()
00155 
00156 /*----------------------------------------------------------------------------*/
00162 void
00163 claw::graphic::png::writer::save( std::ostream& f, const options& opt ) const
00164 {
00165   CLAW_PRECOND( !!f );
00166 
00167   target_manager outfile(f);
00168   png_structp png_ptr;
00169   png_infop info_ptr;
00170 
00171   create_write_structures(png_ptr, info_ptr);
00172 
00173   if (setjmp(png_jmpbuf(png_ptr)))
00174     {
00175       /* If we get here, we had a problem reading the file */
00176       /* Free all of the memory associated with the png_ptr and info_ptr */
00177       png_destroy_write_struct(&png_ptr, &info_ptr);
00178       throw CLAW_EXCEPTION("Invalid PNG file.");
00179     }
00180       
00181   png_set_write_fn( png_ptr, (void *)&outfile,
00182                     claw__graphic__png__target_manager__write,
00183                     claw__graphic__png__target_manager__flush );
00184 
00185   set_options( png_ptr, info_ptr, opt );
00186   save_image( png_ptr, info_ptr );
00187       
00188   png_destroy_write_struct(&png_ptr, &info_ptr);
00189 } // png::writer::save()
00190 
00191 /*----------------------------------------------------------------------------*/
00198 void claw::graphic::png::writer::set_options
00199 ( png_structp png_ptr, png_infop info_ptr, const options& opt ) const
00200 {
00201   CLAW_PRECOND( png_ptr );
00202   CLAW_PRECOND( info_ptr );
00203 
00204   png_set_compression_level( png_ptr, opt.compression );
00205 
00206   png_set_IHDR( png_ptr, info_ptr, m_image.width(), m_image.height(),
00207                 sizeof(pixel_type::component_type) * 8, /* 8 bits per byte */
00208                 PNG_COLOR_TYPE_RGB_ALPHA,
00209                 opt.interlace, PNG_COMPRESSION_TYPE_DEFAULT,
00210                 PNG_FILTER_TYPE_DEFAULT );
00211 } // png::writer::set_options()
00212 
00213 /*----------------------------------------------------------------------------*/
00219 void claw::graphic::png::writer::save_image
00220 ( png_structp png_ptr, png_infop info_ptr ) const
00221 {
00222   CLAW_PRECOND( png_ptr );
00223   CLAW_PRECOND( info_ptr );
00224 
00225   const unsigned int row_length = s_rgba_pixel_size * m_image.width();
00226   png_bytepp data =
00227     (png_bytepp)png_malloc( png_ptr, sizeof(png_bytep) * m_image.height() );
00228   unsigned int i=0;
00229 
00230   try
00231     {
00232       for (i=0; i!=m_image.height(); ++i)
00233         {
00234           data[i] = (png_bytep)png_malloc( png_ptr, row_length );
00235 
00236           if (!data[i])
00237             throw std::bad_alloc();
00238 
00239           copy_pixel_line( data[i], i );
00240         }
00241 
00242       png_set_rows(png_ptr, info_ptr, data);
00243       png_write_png(png_ptr, info_ptr, PNG_TRANSFORM_IDENTITY, NULL);
00244     }
00245   catch(...)
00246     {
00247       for(unsigned int j=0; j!=i; ++j)
00248         png_free(png_ptr, data[j]);
00249 
00250       png_free(png_ptr, data);
00251       throw;
00252     }
00253 
00254   for(i=0; i!=m_image.height(); ++i)
00255     png_free(png_ptr, data[i]);
00256 
00257   png_free(png_ptr, data);
00258 } // png::writer::save_image()
00259 
00260 /*----------------------------------------------------------------------------*/
00267 void claw::graphic::png::writer::copy_pixel_line
00268 ( png_bytep data, unsigned int y ) const
00269 {
00270   CLAW_PRECOND( data );
00271   CLAW_PRECOND( y < m_image.height() );
00272 
00273   // four bytes for each pixel in the line
00274   for (unsigned int x=0; x!=m_image.width(); ++x, data+=s_rgba_pixel_size)
00275     {
00276       data[0] = m_image[y][x].components.red;
00277       data[1] = m_image[y][x].components.green;
00278       data[2] = m_image[y][x].components.blue;
00279       data[3] = m_image[y][x].components.alpha;
00280     }
00281 } // png::writer::copy_pixel_line()
00282 
00283 /*----------------------------------------------------------------------------*/
00289 void claw::graphic::png::writer::create_write_structures
00290 ( png_structp& png_ptr, png_infop& info_ptr ) const
00291 {
00292   png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
00293 
00294   if (png_ptr)
00295     {
00296       info_ptr = png_create_info_struct(png_ptr);
00297 
00298       if (!info_ptr)
00299         png_destroy_write_struct(&png_ptr, png_infopp_NULL);
00300     }
00301 
00302   if (!png_ptr || !info_ptr)
00303     throw CLAW_EXCEPTION("Can't create PNG write structures.");
00304 } // png::writer::create_write_structures()

Generated on 9 Nov 2009 for CLAW Library (a C++ Library Absolutely Wonderful) by  doxygen 1.6.1