Claw  1.7.3
jpeg_reader.cpp
Go to the documentation of this file.
1 /*
2  CLAW - a C++ Library Absolutely Wonderful
3 
4  CLAW is a free library without any particular aim but being useful to
5  anyone.
6 
7  Copyright (C) 2005-2011 Julien Jorge
8 
9  This library is free software; you can redistribute it and/or
10  modify it under the terms of the GNU Lesser General Public
11  License as published by the Free Software Foundation; either
12  version 2.1 of the License, or (at your option) any later version.
13 
14  This library is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17  Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public
20  License along with this library; if not, write to the Free Software
21  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22 
23  contact: julien.jorge@gamned.org
24 */
30 #include <claw/jpeg.hpp>
32 
33 #include <claw/exception.hpp>
34 #include <claw/assert.hpp>
35 
36 /*----------------------------------------------------------------------------*/
41 METHODDEF(void)
43 {
44  // nothing to do
45 } // claw__graphic__jpeg__source_manager__init_source()
46 
47 /*----------------------------------------------------------------------------*/
52 METHODDEF(boolean)
54 {
57 
58  CLAW_PRECOND( &self->pub == cinfo->src );
59 
60  return self->fill_input_buffer();
61 } // claw__graphic__jpeg__source_manager__fill_input_buffer()
62 
63 /*----------------------------------------------------------------------------*/
69 METHODDEF(void)
71  long num_bytes)
72 {
75 
76  CLAW_PRECOND( &self->pub == cinfo->src );
77 
78  return self->skip_input_data(num_bytes);
79 } // claw__graphic__jpeg__source_manager__skip_input_data()
80 
81 /*----------------------------------------------------------------------------*/
86 METHODDEF(void)
88 {
89  // nothing to do
90 } // claw__graphic__jpeg__source_manager__term_source()
91 
92 /*----------------------------------------------------------------------------*/
98  : m_input(is), m_buffer_size(1024), m_stream_position(0)
99 {
100  std::istream::pos_type pos = is.tellg();
101 
102  is.seekg( 0 , std::ios_base::end );
103  m_stream_size = is.tellg() ;
104 
105  is.seekg( pos, std::ios_base::beg ) ;
106 
107  m_buffer = new JOCTET[m_buffer_size];
108  pub.bytes_in_buffer = 0;
109 } // jpeg::reader::source_manager::source_manager()
110 
111 /*----------------------------------------------------------------------------*/
116 {
117  delete[] m_buffer;
118 } // jpeg::reader::source_manager::~source_manager()
119 
120 /*----------------------------------------------------------------------------*/
124 boolean
126 {
127  unsigned int n = std::min( m_buffer_size, m_stream_size - m_stream_position );
128  m_input.read( (char*)m_buffer, n );
129 
130  pub.next_input_byte = m_buffer;
131  pub.bytes_in_buffer = n;
132 
133  m_stream_position += n;
134 
135  if (m_input)
136  return TRUE;
137  else
138  return FALSE;
139 } // jpeg::reader::source_manager::fill_input_buffer()
140 
141 /*----------------------------------------------------------------------------*/
146 void
148 {
149  CLAW_PRECOND(num_bytes >=0);
150 
151  if ( (size_t)num_bytes <= pub.bytes_in_buffer )
152  {
153  pub.next_input_byte += num_bytes;
154  pub.bytes_in_buffer -= num_bytes;
155  }
156  else
157  {
158  num_bytes -= pub.bytes_in_buffer;
159 
160  long div = num_bytes / m_buffer_size;
161  long rest = num_bytes % m_buffer_size;
162 
163  for (long i=0; i!=(div+1); ++i)
164  fill_input_buffer();
165 
166  pub.next_input_byte += rest;
167  pub.bytes_in_buffer -= rest;
168  }
169 } // jpeg::reader::source_manager::skip_input_data()
170 
171 
172 
173 
174 /*----------------------------------------------------------------------------*/
179 claw::graphic::jpeg::reader::RGB_to_pixel32::operator()
180  ( const JSAMPLE* pixel ) const
181 {
182  rgba_pixel_8 result;
183 
184  result.components.alpha = 255;
185  result.components.red = pixel[0];
186  result.components.green = pixel[1];
187  result.components.blue = pixel[2];
188 
189  return result;
190 } // jpeg::reader::RGB_to_pixel32::operator()()
191 
192 /*----------------------------------------------------------------------------*/
197 claw::graphic::jpeg::reader::grayscale_to_pixel32::operator()
198  ( const JSAMPLE* pixel ) const
199 {
200  rgba_pixel_8 result;
201 
202  result.components.alpha = 255;
203  result.components.red = pixel[0];
204  result.components.green = pixel[0];
205  result.components.blue = pixel[0];
206 
207  return result;
208 } // jpeg::reader::grayscale_to_pixel32::operator()()
209 
210 
211 
212 
213 /*----------------------------------------------------------------------------*/
219  : m_image( img )
220 {
221 
222 } // jpeg::reader::reader()
223 
224 /*----------------------------------------------------------------------------*/
232  : m_image( img )
233 {
234  load(f);
235 } // jpeg::reader::reader()
236 
237 /*----------------------------------------------------------------------------*/
242 void claw::graphic::jpeg::reader::load( std::istream& f )
243 {
244  CLAW_PRECOND( !!f );
245 
246  std::istream::pos_type init_pos = f.tellg();
247 
248  try
249  {
250  read_from_file(f);
251  }
252  catch(...)
253  {
254  f.clear();
255  f.seekg( init_pos, std::ios_base::beg );
256  throw;
257  }
258 } // jpeg::reader::load()
259 
260 /*----------------------------------------------------------------------------*/
265 void claw::graphic::jpeg::reader::read_from_file( std::istream& f )
266 {
267  source_manager infile(f);
268  jpeg_decompress_struct cinfo;
269  error_manager jerr;
270 
271  cinfo.err = jpeg_std_error(&jerr.pub);
272 
273  if ( setjmp(jerr.setjmp_buffer) )
274  throw CLAW_EXCEPTION(jerr.error_string);
275 
276  create_decompress_info( cinfo, infile );
277  jerr.pub.error_exit = jpeg__error_manager__error_exit;
278 
279  try
280  {
281  decompress(f, cinfo);
282  jpeg_destroy_decompress(&cinfo);
283  }
284  catch(...)
285  {
286  jpeg_destroy_decompress(&cinfo);
287  throw;
288  }
289 } // jpeg::reader::read_from_file()
290 
291 /*----------------------------------------------------------------------------*/
297 void claw::graphic::jpeg::reader::decompress
298 ( std::istream& f, jpeg_decompress_struct& cinfo )
299 {
300  error_manager jerr;
301  jpeg_error_mgr* jerr_saved = cinfo.err;
302 
303  cinfo.err = jpeg_std_error(&jerr.pub);
304  jerr.pub.error_exit = jpeg__error_manager__error_exit;
305 
306  if ( setjmp(jerr.setjmp_buffer) )
307  {
308  jpeg_abort_decompress(&cinfo);
309  throw CLAW_EXCEPTION(jerr.error_string);
310  }
311 
312  jpeg_read_header(&cinfo, TRUE);
313  jpeg_start_decompress( &cinfo );
314 
315  try
316  {
317  m_image.set_size( cinfo.image_width, cinfo.image_height );
318 
319  if ( cinfo.out_color_components == 3 )
320  read_data( cinfo, RGB_to_pixel32() );
321  else if ( cinfo.out_color_components == 1 )
322  read_data( cinfo, grayscale_to_pixel32() );
323  else
324  throw CLAW_EXCEPTION( "invalid number of colors per channel" );
325 
326  jpeg_finish_decompress(&cinfo);
327  }
328  catch(...)
329  {
330  jpeg_abort_decompress(&cinfo);
331  throw;
332  }
333 
334  cinfo.err = jerr_saved;
335 } // jpeg::reader::decompress()
336 
337 /*----------------------------------------------------------------------------*/
343 void claw::graphic::jpeg::reader::create_decompress_info
344 ( jpeg_decompress_struct& cinfo, source_manager& infile ) const
345 {
346  jpeg_create_decompress(&cinfo);
347 
348  cinfo.src = &infile.pub;
349  cinfo.client_data = &infile;
350 
351  infile.pub.fill_input_buffer =
353  infile.pub.skip_input_data =
355  infile.pub.init_source = claw__graphic__jpeg__source_manager__init_source;
356  infile.pub.resync_to_restart = jpeg_resync_to_restart;
357  infile.pub.term_source = claw__graphic__jpeg__source_manager__term_source;
358 } // jpeg::reader::create_decompress_info()