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__source_manager__init_source(j_decompress_ptr cinfo)
00043 {
00044
00045 }
00046
00047
00052 METHODDEF(boolean)
00053 claw__graphic__jpeg__source_manager__fill_input_buffer(j_decompress_ptr cinfo)
00054 {
00055 claw::graphic::jpeg::reader::source_manager* self =
00056 (claw::graphic::jpeg::reader::source_manager*)cinfo->client_data;
00057
00058 CLAW_PRECOND( &self->pub == cinfo->src );
00059
00060 return self->fill_input_buffer();
00061 }
00062
00063
00069 METHODDEF(void)
00070 claw__graphic__jpeg__source_manager__skip_input_data(j_decompress_ptr cinfo,
00071 long num_bytes)
00072 {
00073 claw::graphic::jpeg::reader::source_manager* self =
00074 (claw::graphic::jpeg::reader::source_manager*)cinfo->client_data;
00075
00076 CLAW_PRECOND( &self->pub == cinfo->src );
00077
00078 return self->skip_input_data(num_bytes);
00079 }
00080
00081
00086 METHODDEF(void)
00087 claw__graphic__jpeg__source_manager__term_source(j_decompress_ptr cinfo)
00088 {
00089
00090 }
00091
00092
00097 claw::graphic::jpeg::reader::source_manager::source_manager( std::istream& is )
00098 : m_input(is), m_buffer_size(1024), m_stream_position(0)
00099 {
00100 std::istream::pos_type pos = is.tellg();
00101
00102 is.seekg( 0 , std::ios_base::end );
00103 m_stream_size = is.tellg() ;
00104
00105 is.seekg( pos, std::ios_base::beg ) ;
00106
00107 m_buffer = new JOCTET[m_buffer_size];
00108 pub.bytes_in_buffer = 0;
00109 }
00110
00111
00115 claw::graphic::jpeg::reader::source_manager::~source_manager()
00116 {
00117 delete[] m_buffer;
00118 }
00119
00120
00124 boolean
00125 claw::graphic::jpeg::reader::source_manager::fill_input_buffer()
00126 {
00127 unsigned int n = std::min( m_buffer_size, m_stream_size - m_stream_position );
00128 m_input.read( (char*)m_buffer, n );
00129
00130 pub.next_input_byte = m_buffer;
00131 pub.bytes_in_buffer = n;
00132
00133 m_stream_position += n;
00134
00135 if (m_input)
00136 return TRUE;
00137 else
00138 return FALSE;
00139 }
00140
00141
00146 void
00147 claw::graphic::jpeg::reader::source_manager::skip_input_data(long num_bytes)
00148 {
00149 CLAW_PRECOND(num_bytes >=0);
00150
00151 if ( (size_t)num_bytes <= pub.bytes_in_buffer )
00152 {
00153 pub.next_input_byte += num_bytes;
00154 pub.bytes_in_buffer -= num_bytes;
00155 }
00156 else
00157 {
00158 num_bytes -= pub.bytes_in_buffer;
00159
00160 long div = num_bytes / m_buffer_size;
00161 long rest = num_bytes % m_buffer_size;
00162
00163 for (long i=0; i!=(div+1); ++i)
00164 fill_input_buffer();
00165
00166 pub.next_input_byte += rest;
00167 pub.bytes_in_buffer -= rest;
00168 }
00169 }
00170
00171
00172
00173
00174
00178 claw::graphic::rgba_pixel_8
00179 claw::graphic::jpeg::reader::RGB_to_pixel32::operator()
00180 ( const JSAMPLE* pixel ) const
00181 {
00182 rgba_pixel_8 result;
00183
00184 result.components.alpha = 255;
00185 result.components.red = pixel[0];
00186 result.components.green = pixel[1];
00187 result.components.blue = pixel[2];
00188
00189 return result;
00190 }
00191
00192
00196 claw::graphic::rgba_pixel_8
00197 claw::graphic::jpeg::reader::grayscale_to_pixel32::operator()
00198 ( const JSAMPLE* pixel ) const
00199 {
00200 rgba_pixel_8 result;
00201
00202 result.components.alpha = 255;
00203 result.components.red = pixel[0];
00204 result.components.green = pixel[0];
00205 result.components.blue = pixel[0];
00206
00207 return result;
00208 }
00209
00210
00211
00212
00213
00218 claw::graphic::jpeg::reader::reader( image& img )
00219 : m_image( img )
00220 {
00221
00222 }
00223
00224
00231 claw::graphic::jpeg::reader::reader( image& img, std::istream& f )
00232 : m_image( img )
00233 {
00234 load(f);
00235 }
00236
00237
00242 void claw::graphic::jpeg::reader::load( std::istream& f )
00243 {
00244 CLAW_PRECOND( !!f );
00245
00246 std::istream::pos_type init_pos = f.tellg();
00247
00248 try
00249 {
00250 read_from_file(f);
00251 }
00252 catch(...)
00253 {
00254 f.clear();
00255 f.seekg( init_pos, std::ios_base::beg );
00256 throw;
00257 }
00258 }
00259
00260
00265 void claw::graphic::jpeg::reader::read_from_file( std::istream& f )
00266 {
00267 source_manager infile(f);
00268 jpeg_decompress_struct cinfo;
00269 error_manager jerr;
00270
00271 cinfo.err = jpeg_std_error(&jerr.pub);
00272
00273 if ( setjmp(jerr.setjmp_buffer) )
00274 throw CLAW_EXCEPTION(jerr.error_string);
00275
00276 create_decompress_info( cinfo, infile );
00277 jerr.pub.error_exit = jpeg__error_manager__error_exit;
00278
00279 try
00280 {
00281 decompress(f, cinfo);
00282 jpeg_destroy_decompress(&cinfo);
00283 }
00284 catch(...)
00285 {
00286 jpeg_destroy_decompress(&cinfo);
00287 throw;
00288 }
00289 }
00290
00291
00297 void claw::graphic::jpeg::reader::decompress
00298 ( std::istream& f, jpeg_decompress_struct& cinfo )
00299 {
00300 error_manager jerr;
00301 jpeg_error_mgr* jerr_saved = cinfo.err;
00302
00303 cinfo.err = jpeg_std_error(&jerr.pub);
00304 jerr.pub.error_exit = jpeg__error_manager__error_exit;
00305
00306 if ( setjmp(jerr.setjmp_buffer) )
00307 {
00308 jpeg_abort_decompress(&cinfo);
00309 throw CLAW_EXCEPTION(jerr.error_string);
00310 }
00311
00312 jpeg_read_header(&cinfo, TRUE);
00313 jpeg_start_decompress( &cinfo );
00314
00315 try
00316 {
00317 m_image.set_size( cinfo.image_width, cinfo.image_height );
00318
00319 if ( cinfo.out_color_components == 3 )
00320 read_data( cinfo, RGB_to_pixel32() );
00321 else if ( cinfo.out_color_components == 1 )
00322 read_data( cinfo, grayscale_to_pixel32() );
00323 else
00324 throw CLAW_EXCEPTION( "invalid number of colors per channel" );
00325
00326 jpeg_finish_decompress(&cinfo);
00327 }
00328 catch(...)
00329 {
00330 jpeg_abort_decompress(&cinfo);
00331 throw;
00332 }
00333
00334 cinfo.err = jerr_saved;
00335 }
00336
00337
00343 void claw::graphic::jpeg::reader::create_decompress_info
00344 ( jpeg_decompress_struct& cinfo, source_manager& infile ) const
00345 {
00346 jpeg_create_decompress(&cinfo);
00347
00348 cinfo.src = &infile.pub;
00349 cinfo.client_data = &infile;
00350
00351 infile.pub.fill_input_buffer =
00352 claw__graphic__jpeg__source_manager__fill_input_buffer;
00353 infile.pub.skip_input_data =
00354 claw__graphic__jpeg__source_manager__skip_input_data;
00355 infile.pub.init_source = claw__graphic__jpeg__source_manager__init_source;
00356 infile.pub.resync_to_restart = jpeg_resync_to_restart;
00357 infile.pub.term_source = claw__graphic__jpeg__source_manager__term_source;
00358 }