jpeg_writer.cpp
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 }