jpeg_writer.cpp
Go to the documentation of this file.
/*
CLAW - a C++ Library Absolutely Wonderful
CLAW is a free library without any particular aim but being useful to
anyone.
Copyright (C) 2005-2011 Julien Jorge
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
contact: julien.jorge@gamned.org
*/
#include <claw/jpeg.hpp>
#include <claw/jpeg_error_manager.hpp>
#include <claw/exception.hpp>
#include <claw/assert.hpp>
/*----------------------------------------------------------------------------*/
METHODDEF(void)
claw__graphic__jpeg__destination_manager__init_destination(j_compress_ptr cinfo)
{
// nothing to do
} // claw__graphic__jpeg__destination_manager__init_destination()
/*----------------------------------------------------------------------------*/
METHODDEF(boolean)
claw__graphic__jpeg__destination_manager__empty_output_buffer
(j_compress_ptr cinfo)
{
claw::graphic::jpeg::writer::destination_manager* self =
(claw::graphic::jpeg::writer::destination_manager*)cinfo->client_data;
CLAW_PRECOND( &self->pub == cinfo->dest );
self->flush();
return TRUE;
} // claw__graphic__jpeg__destination_manager__empty_output_buffer()
/*----------------------------------------------------------------------------*/
METHODDEF(void)
claw__graphic__jpeg__destination_manager__term_destination(j_compress_ptr cinfo)
{
claw::graphic::jpeg::writer::destination_manager* self =
(claw::graphic::jpeg::writer::destination_manager*)cinfo->client_data;
CLAW_PRECOND( &self->pub == cinfo->dest );
self->term();
} // claw__graphic__jpeg__destination_manager__term_destination()
/*----------------------------------------------------------------------------*/
claw::graphic::jpeg::writer::destination_manager::destination_manager
( std::ostream& os )
: m_output(os), m_buffer_size(1024)
{
m_buffer = new JOCTET[m_buffer_size];
pub.next_output_byte = m_buffer;
pub.free_in_buffer = m_buffer_size;
} // jpeg::writer::destination_manager::destination_manager()
/*----------------------------------------------------------------------------*/
claw::graphic::jpeg::writer::destination_manager::~destination_manager()
{
delete[] m_buffer;
} // jpeg::writer::destination_manager::~destination_manager()
/*----------------------------------------------------------------------------*/
void claw::graphic::jpeg::writer::destination_manager::flush()
{
m_output.write((char*)m_buffer, m_buffer_size);
pub.next_output_byte = m_buffer;
pub.free_in_buffer = m_buffer_size;
} // jpeg::writer::destination_manager::fill_output_buffer()
/*----------------------------------------------------------------------------*/
void
claw::graphic::jpeg::writer::destination_manager::term()
{
m_output.write((char*)m_buffer, m_buffer_size - pub.free_in_buffer);
} // jpeg::writer::destination_manager::term()
/*----------------------------------------------------------------------------*/
claw::graphic::jpeg::writer::options::options()
: quality(75), progressive(false)
{
} // jpeg::writer::options::options()
/*----------------------------------------------------------------------------*/
claw::graphic::jpeg::writer::options::options
( unsigned char quality_, bool progressive_ )
: quality(quality_), progressive(progressive_)
{
} // jpeg::writer::options::options()
/*----------------------------------------------------------------------------*/
const unsigned int claw::graphic::jpeg::writer::s_rgb_pixel_size = 3;
/*----------------------------------------------------------------------------*/
claw::graphic::jpeg::writer::writer( const image& img )
: m_image( img )
{
} // jpeg::writer::writer()
/*----------------------------------------------------------------------------*/
claw::graphic::jpeg::writer::writer
( const image& img, std::ostream& f, const options& opt )
: m_image( img )
{
save(f, opt);
} // jpeg::writer::writer()
/*----------------------------------------------------------------------------*/
void
claw::graphic::jpeg::writer::save( std::ostream& f, const options& opt ) const
{
CLAW_PRECOND( !!f );
destination_manager outfile(f);
jpeg_compress_struct cinfo;
error_manager jerr;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpeg__error_manager__error_exit;
if ( setjmp(jerr.setjmp_buffer) )
throw CLAW_EXCEPTION(jerr.error_string);
create_compress_info( cinfo, outfile );
try
{
set_options( cinfo, opt );
save_image( cinfo );
jpeg_destroy_compress(&cinfo);
}
catch(...)
{
jpeg_abort_compress(&cinfo);
jpeg_destroy_compress(&cinfo);
throw;
}
} // jpeg::writer::save()
/*----------------------------------------------------------------------------*/
void claw::graphic::jpeg::writer::set_options
( jpeg_compress_struct& cinfo, const options& opt ) const
{
cinfo.image_width = m_image.width(); /* image width, in pixels */
cinfo.image_height = m_image.height(); /* image height, in pixels */
cinfo.input_components = s_rgb_pixel_size; /* # of components per pixel */
cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
jpeg_set_defaults(&cinfo);
if (opt.quality > 100)
jpeg_set_quality(&cinfo, 100, TRUE);
else
jpeg_set_quality(&cinfo, opt.quality, TRUE);
if (opt.progressive)
jpeg_simple_progression(&cinfo);
} // jpeg::writer::set_options()
/*----------------------------------------------------------------------------*/
void
claw::graphic::jpeg::writer::save_image( jpeg_compress_struct& cinfo ) const
{
JSAMPLE* data = new JSAMPLE[ m_image.width() * s_rgb_pixel_size ];
error_manager jerr;
jpeg_error_mgr* jerr_saved = cinfo.err;
cinfo.err = jpeg_std_error(&jerr.pub);
jerr.pub.error_exit = jpeg__error_manager__error_exit;
if ( setjmp(jerr.setjmp_buffer) )
{
delete[] data;
jpeg_abort_compress(&cinfo);
throw CLAW_EXCEPTION(jerr.error_string);
}
jpeg_start_compress( &cinfo, TRUE );
while (cinfo.next_scanline < cinfo.image_height)
{
copy_pixel_line( data, cinfo.next_scanline );
jpeg_write_scanlines( &cinfo, &data, 1 );
}
delete[] data;
jpeg_finish_compress(&cinfo);
cinfo.err = jerr_saved;
} // jpeg::writer::load()
/*----------------------------------------------------------------------------*/
void claw::graphic::jpeg::writer::copy_pixel_line
( JSAMPLE* data, unsigned int y ) const
{
CLAW_PRECOND( data );
CLAW_PRECOND( y < m_image.height() );
// three bytes for each pixel in the line
for (unsigned int x=0; x!=m_image.width(); ++x, data+=s_rgb_pixel_size)
{
data[0] = m_image[y][x].components.red;
data[1] = m_image[y][x].components.green;
data[2] = m_image[y][x].components.blue;
}
} // jpeg::writer::copy_pixel_line()
/*----------------------------------------------------------------------------*/
void claw::graphic::jpeg::writer::create_compress_info
( jpeg_compress_struct& cinfo, destination_manager& outfile ) const
{
jpeg_create_compress(&cinfo);
cinfo.dest = &outfile.pub;
cinfo.client_data = &outfile;
outfile.pub.init_destination =
claw__graphic__jpeg__destination_manager__init_destination;
outfile.pub.empty_output_buffer =
claw__graphic__jpeg__destination_manager__empty_output_buffer;
outfile.pub.term_destination =
claw__graphic__jpeg__destination_manager__term_destination;
} // jpeg::writer::create_compress_info()
claw::graphic::jpeg::writer::options::quality
unsigned char quality
Quality level to use in the saved stream.
Definition: jpeg.hpp:182
claw::graphic::jpeg::writer::destination_manager::term
void term()
Write the last pending bytes in the file.
Definition: jpeg_writer.cpp:125
jpeg.hpp
A class for jpeg pictures.
claw::graphic::jpeg::error_manager::pub
struct jpeg_error_mgr pub
"public" fields, needed by the jpeg library.
Definition: jpeg.hpp:65
claw::graphic::jpeg::writer::destination_manager::~destination_manager
~destination_manager()
Destructor.
Definition: jpeg_writer.cpp:103
claw::graphic::jpeg::writer::destination_manager::flush
void flush()
Write the content of the buffer in the file.
Definition: jpeg_writer.cpp:112
claw::graphic::image::height
unsigned int height() const
Gets image&#39;s height.
Definition: image.cpp:159
claw::graphic::jpeg::error_manager::error_string
std::string error_string
A comprehensive description of the error.
Definition: jpeg.hpp:71
claw::graphic::jpeg::writer::destination_manager::pub
struct jpeg_destination_mgr pub
"public" fields, needed by the jpeg library.
Definition: jpeg.hpp:207
claw::graphic::jpeg::writer::destination_manager
Destination manager that allow us to write in a std::ostream.
Definition: jpeg.hpp:196
claw::graphic::jpeg::writer::writer
writer(const image &img)
Constructor.
Definition: jpeg_writer.cpp:168
claw::graphic::jpeg::writer::options::progressive
bool progressive
Tell if we save a progressive jpeg.
Definition: jpeg.hpp:185
claw__graphic__jpeg__destination_manager__term_destination
claw__graphic__jpeg__destination_manager__term_destination(j_compress_ptr cinfo)
Write the last pending bytes in the file.
Definition: jpeg_writer.cpp:72
claw::graphic::jpeg__error_manager__error_exit
void jpeg__error_manager__error_exit(j_common_ptr cinfo)
Throw an exception when an error occurs in an internal jpeg processing.
Definition: jpeg_error_manager.cpp:39
claw::graphic::jpeg::error_manager::setjmp_buffer
jmp_buf setjmp_buffer
For return to caller.
Definition: jpeg.hpp:68
claw::graphic::jpeg::writer::options::options
options()
Default constructor.
Definition: jpeg_writer.cpp:137
claw__graphic__jpeg__destination_manager__init_destination
claw__graphic__jpeg__destination_manager__init_destination(j_compress_ptr cinfo)
Initialize the output stream.
Definition: jpeg_writer.cpp:42
claw::graphic::jpeg::writer::destination_manager::destination_manager
destination_manager(std::ostream &os)
Constructor.
Definition: jpeg_writer.cpp:91
claw::graphic::image::width
unsigned int width() const
Gets image&#39;s width.
Definition: image.cpp:147
claw::graphic::jpeg::error_manager
Error handler that throw an exception instead of exiting the program.
Definition: jpeg.hpp:62
claw::graphic::jpeg::writer::options
Parameters of the writing algorithm.
Definition: jpeg.hpp:174
exception.hpp
A simple class to use as exception with string message.
claw__graphic__jpeg__destination_manager__empty_output_buffer
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:54
assert.hpp
Some assert macros to strengthen you code.
claw::graphic::image
A class to deal with images.
Definition: image.hpp:49
claw::graphic::jpeg::writer::save
void save(std::ostream &f, const options &opt=options()) const
Save an image in a jpeg file.
Definition: jpeg_writer.cpp:195
jpeg_error_manager.hpp
Methods for the claw::graphic::jpeg::error_manager class.
CLAW_EXCEPTION
#define CLAW_EXCEPTION(m)
Create an exception and add the name of the current function to the message.
Definition: exception.hpp:90
CLAW_PRECOND
#define CLAW_PRECOND(b)
Abort the program if a precondition is not true.
Definition: assert.hpp:98