claw  1.9.0
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@stuff-o-matic.com
24 */
30 #include <claw/graphic/jpeg.hpp>
31 
33 
34 #include <claw/assert.hpp>
35 #include <claw/exception.hpp>
36 
41 METHODDEF(void)
43  j_compress_ptr cinfo)
44 {
45  // nothing to do
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 }
65 
70 METHODDEF(void)
72  j_compress_ptr cinfo)
73 {
76 
77  CLAW_PRECOND(&self->pub == cinfo->dest);
78 
79  self->term();
80 }
81 
87  std::ostream& os)
88  : m_output(os)
89  , m_buffer_size(1024)
90 {
91  m_buffer = new JOCTET[m_buffer_size];
92  pub.next_output_byte = m_buffer;
93  pub.free_in_buffer = m_buffer_size;
94 }
95 
100 {
101  delete[] m_buffer;
102 }
103 
108 {
109  m_output.write((char*)m_buffer, m_buffer_size);
110 
111  pub.next_output_byte = m_buffer;
112  pub.free_in_buffer = m_buffer_size;
113 }
114 
119 {
120  m_output.write((char*)m_buffer, m_buffer_size - pub.free_in_buffer);
121 }
122 
128  : quality(75)
129  , progressive(false)
130 {}
131 
139  bool progressive_)
140  : quality(quality_)
141  , progressive(progressive_)
142 {}
143 
144 const unsigned int claw::graphic::jpeg::writer::s_rgb_pixel_size = 3;
145 
151  : m_image(img)
152 {}
153 
160 claw::graphic::jpeg::writer::writer(const image& img, std::ostream& f,
161  const options& opt)
162  : m_image(img)
163 {
164  save(f, opt);
165 }
166 
173  const options& opt) const
174 {
175  CLAW_PRECOND(!!f);
176 
177  destination_manager outfile(f);
178  jpeg_compress_struct cinfo;
179  error_manager jerr;
180 
181  cinfo.err = jpeg_std_error(&jerr.pub);
182  jerr.pub.error_exit = jpeg__error_manager__error_exit;
183 
184  if(setjmp(jerr.setjmp_buffer))
185  throw CLAW_EXCEPTION(jerr.error_string);
186 
187  create_compress_info(cinfo, outfile);
188 
189  try
190  {
191  set_options(cinfo, opt);
192  save_image(cinfo);
193  jpeg_destroy_compress(&cinfo);
194  }
195  catch(...)
196  {
197  jpeg_abort_compress(&cinfo);
198  jpeg_destroy_compress(&cinfo);
199  throw;
200  }
201 }
202 
208 void claw::graphic::jpeg::writer::set_options(jpeg_compress_struct& cinfo,
209  const options& opt) const
210 {
211  cinfo.image_width = m_image.width(); /* image width, in pixels */
212  cinfo.image_height = m_image.height(); /* image height, in pixels */
213  cinfo.input_components = s_rgb_pixel_size; /* # of components per pixel */
214  cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
215 
216  jpeg_set_defaults(&cinfo);
217 
218  if(opt.quality > 100)
219  jpeg_set_quality(&cinfo, 100, TRUE);
220  else
221  jpeg_set_quality(&cinfo, opt.quality, TRUE);
222 
223  if(opt.progressive)
224  jpeg_simple_progression(&cinfo);
225 }
226 
231 void claw::graphic::jpeg::writer::save_image(jpeg_compress_struct& cinfo) const
232 {
233  JSAMPLE* data = new JSAMPLE[m_image.width() * s_rgb_pixel_size];
234 
235  error_manager jerr;
236  jpeg_error_mgr* jerr_saved = cinfo.err;
237 
238  cinfo.err = jpeg_std_error(&jerr.pub);
239  jerr.pub.error_exit = jpeg__error_manager__error_exit;
240 
241  if(setjmp(jerr.setjmp_buffer))
242  {
243  delete[] data;
244  jpeg_abort_compress(&cinfo);
245  throw CLAW_EXCEPTION(jerr.error_string);
246  }
247 
248  jpeg_start_compress(&cinfo, TRUE);
249 
250  while(cinfo.next_scanline < cinfo.image_height)
251  {
252  copy_pixel_line(data, cinfo.next_scanline);
253  jpeg_write_scanlines(&cinfo, &data, 1);
254  }
255 
256  delete[] data;
257  jpeg_finish_compress(&cinfo);
258 
259  cinfo.err = jerr_saved;
260 }
261 
268 void claw::graphic::jpeg::writer::copy_pixel_line(JSAMPLE* data,
269  unsigned int y) const
270 {
271  CLAW_PRECOND(data);
272  CLAW_PRECOND(y < m_image.height());
273 
274  // three bytes for each pixel in the line
275  for(unsigned int x = 0; x != m_image.width(); ++x, data += s_rgb_pixel_size)
276  {
277  data[0] = m_image[y][x].components.red;
278  data[1] = m_image[y][x].components.green;
279  data[2] = m_image[y][x].components.blue;
280  }
281 }
282 
288 void claw::graphic::jpeg::writer::create_compress_info(
289  jpeg_compress_struct& cinfo, destination_manager& outfile) const
290 {
291  jpeg_create_compress(&cinfo);
292 
293  cinfo.dest = &outfile.pub;
294  cinfo.client_data = &outfile;
295 
296  outfile.pub.init_destination
298  outfile.pub.empty_output_buffer
300  outfile.pub.term_destination
302 }
void term()
Write the last pending bytes in the file.
A class for jpeg pictures.
struct jpeg_error_mgr pub
"public" fields, needed by the jpeg library.
Definition: jpeg.hpp:65
void flush()
Write the content of the buffer in the file.
std::string error_string
A comprehensive description of the error.
Definition: jpeg.hpp:71
struct jpeg_destination_mgr pub
"public" fields, needed by the jpeg library.
Definition: jpeg.hpp:202
Destination manager that allow us to write in a std::ostream.
Definition: jpeg.hpp:191
writer(const image &img)
Constructor.
claw__graphic__jpeg__destination_manager__term_destination(j_compress_ptr cinfo)
Write the last pending bytes in the file.
Definition: jpeg_writer.cpp:71
void jpeg__error_manager__error_exit(j_common_ptr cinfo)
Throw an exception when an error occurs in an internal jpeg processing.
jmp_buf setjmp_buffer
For return to caller.
Definition: jpeg.hpp:68
claw__graphic__jpeg__destination_manager__init_destination(j_compress_ptr cinfo)
Initialize the output stream.
Definition: jpeg_writer.cpp:42
destination_manager(std::ostream &os)
Constructor.
Definition: jpeg_writer.cpp:86
Error handler that throw an exception instead of exiting the program.
Definition: jpeg.hpp:62
Parameters of the writing algorithm.
Definition: jpeg.hpp:170
A simple class to use as exception with string message.
claw__graphic__jpeg__destination_manager__empty_output_buffer(j_compress_ptr cinfo)
Write the content of the buffer in the file.
Definition: jpeg_writer.cpp:53
Some assert macros to strengthen you code.
A class to deal with images.
Definition: image.hpp:50
void save(std::ostream &f, const options &opt=options()) const
Save an image in a jpeg file.
Methods for the claw::graphic::jpeg::error_manager class.
#define CLAW_EXCEPTION(m)
Create an exception and add the name of the current function to the message.
Definition: exception.hpp:92
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition: assert.hpp:94