Claw
1.7.3
|
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-2011 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@gamned.org 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 // nothing to do 00045 } // claw__graphic__jpeg__source_manager__init_source() 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 } // claw__graphic__jpeg__source_manager__fill_input_buffer() 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 } // claw__graphic__jpeg__source_manager__skip_input_data() 00080 00081 /*----------------------------------------------------------------------------*/ 00086 METHODDEF(void) 00087 claw__graphic__jpeg__source_manager__term_source(j_decompress_ptr cinfo) 00088 { 00089 // nothing to do 00090 } // claw__graphic__jpeg__source_manager__term_source() 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 } // jpeg::reader::source_manager::source_manager() 00110 00111 /*----------------------------------------------------------------------------*/ 00115 claw::graphic::jpeg::reader::source_manager::~source_manager() 00116 { 00117 delete[] m_buffer; 00118 } // jpeg::reader::source_manager::~source_manager() 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 } // jpeg::reader::source_manager::fill_input_buffer() 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 } // jpeg::reader::source_manager::skip_input_data() 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 } // jpeg::reader::RGB_to_pixel32::operator()() 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 } // jpeg::reader::grayscale_to_pixel32::operator()() 00209 00210 00211 00212 00213 /*----------------------------------------------------------------------------*/ 00218 claw::graphic::jpeg::reader::reader( image& img ) 00219 : m_image( img ) 00220 { 00221 00222 } // jpeg::reader::reader() 00223 00224 /*----------------------------------------------------------------------------*/ 00231 claw::graphic::jpeg::reader::reader( image& img, std::istream& f ) 00232 : m_image( img ) 00233 { 00234 load(f); 00235 } // jpeg::reader::reader() 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 } // jpeg::reader::load() 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 } // jpeg::reader::read_from_file() 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 } // jpeg::reader::decompress() 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 } // jpeg::reader::create_decompress_info()