00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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 }
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 }
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 }
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 }
00089
00090
00094 void claw::graphic::png::writer::target_manager::flush()
00095 {
00096 m_output.flush();
00097 }
00098
00099
00100
00101
00102
00106 claw::graphic::png::writer::options::options()
00107 : compression(default_compression), interlace(none)
00108 {
00109
00110 }
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 }
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 }
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 }
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
00176
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 }
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,
00208 PNG_COLOR_TYPE_RGB_ALPHA,
00209 opt.interlace, PNG_COMPRESSION_TYPE_DEFAULT,
00210 PNG_FILTER_TYPE_DEFAULT );
00211 }
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 }
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
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 }
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 }