Go to the documentation of this file.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/jpeg.hpp>
00031 #include <claw/jpeg_error_manager.hpp>
00032
00033 #include <claw/exception.hpp>
00034 #include <claw/assert.hpp>
00035
00036
00041 METHODDEF(void)
00042 claw__graphic__jpeg__destination_manager__init_destination(j_compress_ptr cinfo)
00043 {
00044
00045 }
00046
00047
00052 METHODDEF(boolean)
00053 claw__graphic__jpeg__destination_manager__empty_output_buffer
00054 (j_compress_ptr cinfo)
00055 {
00056 claw::graphic::jpeg::writer::destination_manager* self =
00057 (claw::graphic::jpeg::writer::destination_manager*)cinfo->client_data;
00058
00059 CLAW_PRECOND( &self->pub == cinfo->dest );
00060
00061 self->flush();
00062
00063 return TRUE;
00064 }
00065
00066
00071 METHODDEF(void)
00072 claw__graphic__jpeg__destination_manager__term_destination(j_compress_ptr cinfo)
00073 {
00074 claw::graphic::jpeg::writer::destination_manager* self =
00075 (claw::graphic::jpeg::writer::destination_manager*)cinfo->client_data;
00076
00077 CLAW_PRECOND( &self->pub == cinfo->dest );
00078
00079 self->term();
00080 }
00081
00082
00083
00084
00085
00090 claw::graphic::jpeg::writer::destination_manager::destination_manager
00091 ( std::ostream& os )
00092 : m_output(os), m_buffer_size(1024)
00093 {
00094 m_buffer = new JOCTET[m_buffer_size];
00095 pub.next_output_byte = m_buffer;
00096 pub.free_in_buffer = m_buffer_size;
00097 }
00098
00099
00103 claw::graphic::jpeg::writer::destination_manager::~destination_manager()
00104 {
00105 delete[] m_buffer;
00106 }
00107
00108
00112 void claw::graphic::jpeg::writer::destination_manager::flush()
00113 {
00114 m_output.write((char*)m_buffer, m_buffer_size);
00115
00116 pub.next_output_byte = m_buffer;
00117 pub.free_in_buffer = m_buffer_size;
00118 }
00119
00120
00124 void
00125 claw::graphic::jpeg::writer::destination_manager::term()
00126 {
00127 m_output.write((char*)m_buffer, m_buffer_size - pub.free_in_buffer);
00128 }
00129
00130
00131
00132
00137 claw::graphic::jpeg::writer::options::options()
00138 : quality(75), progressive(false)
00139 {
00140
00141 }
00142
00143
00150 claw::graphic::jpeg::writer::options::options
00151 ( unsigned char quality_, bool progressive_ )
00152 : quality(quality_), progressive(progressive_)
00153 {
00154
00155 }
00156
00157
00158
00159
00160
00161 const unsigned int claw::graphic::jpeg::writer::s_rgb_pixel_size = 3;
00162
00163
00168 claw::graphic::jpeg::writer::writer( const image& img )
00169 : m_image( img )
00170 {
00171
00172 }
00173
00174
00181 claw::graphic::jpeg::writer::writer
00182 ( const image& img, std::ostream& f, const options& opt )
00183 : m_image( img )
00184 {
00185 save(f, opt);
00186 }
00187
00188
00194 void
00195 claw::graphic::jpeg::writer::save( std::ostream& f, const options& opt ) const
00196 {
00197 CLAW_PRECOND( !!f );
00198
00199 destination_manager outfile(f);
00200 jpeg_compress_struct cinfo;
00201 error_manager jerr;
00202
00203 cinfo.err = jpeg_std_error(&jerr.pub);
00204 jerr.pub.error_exit = jpeg__error_manager__error_exit;
00205
00206 if ( setjmp(jerr.setjmp_buffer) )
00207 throw CLAW_EXCEPTION(jerr.error_string);
00208
00209 create_compress_info( cinfo, outfile );
00210
00211 try
00212 {
00213 set_options( cinfo, opt );
00214 save_image( cinfo );
00215 jpeg_destroy_compress(&cinfo);
00216 }
00217 catch(...)
00218 {
00219 jpeg_abort_compress(&cinfo);
00220 jpeg_destroy_compress(&cinfo);
00221 throw;
00222 }
00223 }
00224
00225
00231 void claw::graphic::jpeg::writer::set_options
00232 ( jpeg_compress_struct& cinfo, const options& opt ) const
00233 {
00234 cinfo.image_width = m_image.width();
00235 cinfo.image_height = m_image.height();
00236 cinfo.input_components = s_rgb_pixel_size;
00237 cinfo.in_color_space = JCS_RGB;
00238
00239 jpeg_set_defaults(&cinfo);
00240
00241 if (opt.quality > 100)
00242 jpeg_set_quality(&cinfo, 100, TRUE);
00243 else
00244 jpeg_set_quality(&cinfo, opt.quality, TRUE);
00245
00246 if (opt.progressive)
00247 jpeg_simple_progression(&cinfo);
00248 }
00249
00250
00255 void
00256 claw::graphic::jpeg::writer::save_image( jpeg_compress_struct& cinfo ) const
00257 {
00258 JSAMPLE* data = new JSAMPLE[ m_image.width() * s_rgb_pixel_size ];
00259
00260 error_manager jerr;
00261 jpeg_error_mgr* jerr_saved = cinfo.err;
00262
00263 cinfo.err = jpeg_std_error(&jerr.pub);
00264 jerr.pub.error_exit = jpeg__error_manager__error_exit;
00265
00266 if ( setjmp(jerr.setjmp_buffer) )
00267 {
00268 delete[] data;
00269 jpeg_abort_compress(&cinfo);
00270 throw CLAW_EXCEPTION(jerr.error_string);
00271 }
00272
00273 jpeg_start_compress( &cinfo, TRUE );
00274
00275 while (cinfo.next_scanline < cinfo.image_height)
00276 {
00277 copy_pixel_line( data, cinfo.next_scanline );
00278 jpeg_write_scanlines( &cinfo, &data, 1 );
00279 }
00280
00281 delete[] data;
00282 jpeg_finish_compress(&cinfo);
00283
00284 cinfo.err = jerr_saved;
00285 }
00286
00287
00294 void claw::graphic::jpeg::writer::copy_pixel_line
00295 ( JSAMPLE* data, unsigned int y ) const
00296 {
00297 CLAW_PRECOND( data );
00298 CLAW_PRECOND( y < m_image.height() );
00299
00300
00301 for (unsigned int x=0; x!=m_image.width(); ++x, data+=s_rgb_pixel_size)
00302 {
00303 data[0] = m_image[y][x].components.red;
00304 data[1] = m_image[y][x].components.green;
00305 data[2] = m_image[y][x].components.blue;
00306 }
00307 }
00308
00309
00315 void claw::graphic::jpeg::writer::create_compress_info
00316 ( jpeg_compress_struct& cinfo, destination_manager& outfile ) const
00317 {
00318 jpeg_create_compress(&cinfo);
00319
00320 cinfo.dest = &outfile.pub;
00321 cinfo.client_data = &outfile;
00322
00323 outfile.pub.init_destination =
00324 claw__graphic__jpeg__destination_manager__init_destination;
00325 outfile.pub.empty_output_buffer =
00326 claw__graphic__jpeg__destination_manager__empty_output_buffer;
00327 outfile.pub.term_destination =
00328 claw__graphic__jpeg__destination_manager__term_destination;
00329 }