jpeg_reader.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__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 }