Claw  1.7.3
jpeg_writer.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__destination_manager__init_destination()
46 
47 /*----------------------------------------------------------------------------*/
52 METHODDEF(boolean)
54 (j_compress_ptr cinfo)
55 {
58 
59  CLAW_PRECOND( &self->pub == cinfo->dest );
60 
61  self->flush();
62 
63  return TRUE;
64 } // claw__graphic__jpeg__destination_manager__empty_output_buffer()
65 
66 /*----------------------------------------------------------------------------*/
71 METHODDEF(void)
73 {
76 
77  CLAW_PRECOND( &self->pub == cinfo->dest );
78 
79  self->term();
80 } // claw__graphic__jpeg__destination_manager__term_destination()
81 
82 
83 
84 
85 /*----------------------------------------------------------------------------*/
91 ( std::ostream& os )
92  : m_output(os), m_buffer_size(1024)
93 {
94  m_buffer = new JOCTET[m_buffer_size];
95  pub.next_output_byte = m_buffer;
96  pub.free_in_buffer = m_buffer_size;
97 } // jpeg::writer::destination_manager::destination_manager()
98 
99 /*----------------------------------------------------------------------------*/
104 {
105  delete[] m_buffer;
106 } // jpeg::writer::destination_manager::~destination_manager()
107 
108 /*----------------------------------------------------------------------------*/
113 {
114  m_output.write((char*)m_buffer, m_buffer_size);
115 
116  pub.next_output_byte = m_buffer;
117  pub.free_in_buffer = m_buffer_size;
118 } // jpeg::writer::destination_manager::fill_output_buffer()
119 
120 /*----------------------------------------------------------------------------*/
124 void
126 {
127  m_output.write((char*)m_buffer, m_buffer_size - pub.free_in_buffer);
128 } // jpeg::writer::destination_manager::term()
129 
130 
131 
132 /*----------------------------------------------------------------------------*/
138  : quality(75), progressive(false)
139 {
140 
141 } // jpeg::writer::options::options()
142 
143 /*----------------------------------------------------------------------------*/
151 ( unsigned char quality_, bool progressive_ )
152  : quality(quality_), progressive(progressive_)
153 {
154 
155 } // jpeg::writer::options::options()
156 
157 
158 
159 
160 /*----------------------------------------------------------------------------*/
161 const unsigned int claw::graphic::jpeg::writer::s_rgb_pixel_size = 3;
162 
163 /*----------------------------------------------------------------------------*/
169  : m_image( img )
170 {
171 
172 } // jpeg::writer::writer()
173 
174 /*----------------------------------------------------------------------------*/
182 ( const image& img, std::ostream& f, const options& opt )
183  : m_image( img )
184 {
185  save(f, opt);
186 } // jpeg::writer::writer()
187 
188 /*----------------------------------------------------------------------------*/
194 void
195 claw::graphic::jpeg::writer::save( std::ostream& f, const options& opt ) const
196 {
197  CLAW_PRECOND( !!f );
198 
199  destination_manager outfile(f);
200  jpeg_compress_struct cinfo;
201  error_manager jerr;
202 
203  cinfo.err = jpeg_std_error(&jerr.pub);
204  jerr.pub.error_exit = jpeg__error_manager__error_exit;
205 
206  if ( setjmp(jerr.setjmp_buffer) )
207  throw CLAW_EXCEPTION(jerr.error_string);
208 
209  create_compress_info( cinfo, outfile );
210 
211  try
212  {
213  set_options( cinfo, opt );
214  save_image( cinfo );
215  jpeg_destroy_compress(&cinfo);
216  }
217  catch(...)
218  {
219  jpeg_abort_compress(&cinfo);
220  jpeg_destroy_compress(&cinfo);
221  throw;
222  }
223 } // jpeg::writer::save()
224 
225 /*----------------------------------------------------------------------------*/
231 void claw::graphic::jpeg::writer::set_options
232 ( jpeg_compress_struct& cinfo, const options& opt ) const
233 {
234  cinfo.image_width = m_image.width(); /* image width, in pixels */
235  cinfo.image_height = m_image.height(); /* image height, in pixels */
236  cinfo.input_components = s_rgb_pixel_size; /* # of components per pixel */
237  cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
238 
239  jpeg_set_defaults(&cinfo);
240 
241  if (opt.quality > 100)
242  jpeg_set_quality(&cinfo, 100, TRUE);
243  else
244  jpeg_set_quality(&cinfo, opt.quality, TRUE);
245 
246  if (opt.progressive)
247  jpeg_simple_progression(&cinfo);
248 } // jpeg::writer::set_options()
249 
250 /*----------------------------------------------------------------------------*/
255 void
256 claw::graphic::jpeg::writer::save_image( jpeg_compress_struct& cinfo ) const
257 {
258  JSAMPLE* data = new JSAMPLE[ m_image.width() * s_rgb_pixel_size ];
259 
260  error_manager jerr;
261  jpeg_error_mgr* jerr_saved = cinfo.err;
262 
263  cinfo.err = jpeg_std_error(&jerr.pub);
264  jerr.pub.error_exit = jpeg__error_manager__error_exit;
265 
266  if ( setjmp(jerr.setjmp_buffer) )
267  {
268  delete[] data;
269  jpeg_abort_compress(&cinfo);
270  throw CLAW_EXCEPTION(jerr.error_string);
271  }
272 
273  jpeg_start_compress( &cinfo, TRUE );
274 
275  while (cinfo.next_scanline < cinfo.image_height)
276  {
277  copy_pixel_line( data, cinfo.next_scanline );
278  jpeg_write_scanlines( &cinfo, &data, 1 );
279  }
280 
281  delete[] data;
282  jpeg_finish_compress(&cinfo);
283 
284  cinfo.err = jerr_saved;
285 } // jpeg::writer::load()
286 
287 /*----------------------------------------------------------------------------*/
294 void claw::graphic::jpeg::writer::copy_pixel_line
295 ( JSAMPLE* data, unsigned int y ) const
296 {
297  CLAW_PRECOND( data );
298  CLAW_PRECOND( y < m_image.height() );
299 
300  // three bytes for each pixel in the line
301  for (unsigned int x=0; x!=m_image.width(); ++x, data+=s_rgb_pixel_size)
302  {
303  data[0] = m_image[y][x].components.red;
304  data[1] = m_image[y][x].components.green;
305  data[2] = m_image[y][x].components.blue;
306  }
307 } // jpeg::writer::copy_pixel_line()
308 
309 /*----------------------------------------------------------------------------*/
315 void claw::graphic::jpeg::writer::create_compress_info
316 ( jpeg_compress_struct& cinfo, destination_manager& outfile ) const
317 {
318  jpeg_create_compress(&cinfo);
319 
320  cinfo.dest = &outfile.pub;
321  cinfo.client_data = &outfile;
322 
323  outfile.pub.init_destination =
325  outfile.pub.empty_output_buffer =
327  outfile.pub.term_destination =
329 } // jpeg::writer::create_compress_info()