jpeg_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/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   // nothing to do
00045 } // claw__graphic__jpeg__destination_manager__init_destination()
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 } // claw__graphic__jpeg__destination_manager__empty_output_buffer()
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 } // claw__graphic__jpeg__destination_manager__term_destination()
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 } // jpeg::writer::destination_manager::destination_manager()
00098 
00099 /*----------------------------------------------------------------------------*/
00103 claw::graphic::jpeg::writer::destination_manager::~destination_manager()
00104 {
00105   delete[] m_buffer;
00106 } // jpeg::writer::destination_manager::~destination_manager()
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 } // jpeg::writer::destination_manager::fill_output_buffer()
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 } // jpeg::writer::destination_manager::term()
00129 
00130 
00131 
00132 /*----------------------------------------------------------------------------*/
00137 claw::graphic::jpeg::writer::options::options()
00138   : quality(75), progressive(false)
00139 {
00140 
00141 } // jpeg::writer::options::options()
00142 
00143 /*----------------------------------------------------------------------------*/
00150 claw::graphic::jpeg::writer::options::options
00151 ( unsigned char quality_, bool progressive_ )
00152   : quality(quality_), progressive(progressive_)
00153 {
00154 
00155 } // jpeg::writer::options::options()
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 } // jpeg::writer::writer()
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 } // jpeg::writer::writer()
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 } // jpeg::writer::save()
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();       /* image width, in pixels */
00235   cinfo.image_height = m_image.height();     /* image height, in pixels */
00236   cinfo.input_components = s_rgb_pixel_size; /* # of components per pixel */
00237   cinfo.in_color_space = JCS_RGB;            /* colorspace of input image */
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 } // jpeg::writer::set_options()
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 } // jpeg::writer::load()
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   // three bytes for each pixel in the line
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 } // jpeg::writer::copy_pixel_line()
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 } // jpeg::writer::create_compress_info()

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