mirror of
https://github.com/vdemydiuk/mtapi.git
synced 2026-08-20 22:28:17 +00:00
Added thirdparty: boost library
This commit is contained in:
+38
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// Copyright 2010 Christian Henning
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_BASE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_BASE_HPP
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
|
||||
#include <csetjmp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4324) //structure was padded due to __declspec(align())
|
||||
#endif
|
||||
|
||||
class jpeg_io_base
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
jpeg_error_mgr _jerr;
|
||||
jmp_buf _mark;
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// Copyright 2009 Christian Henning
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_IS_ALLOWED_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_IS_ALLOWED_HPP
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< jpeg_tag >& info
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
if( info._color_space == JCS_YCbCr )
|
||||
{
|
||||
// We read JCS_YCbCr files as rgb.
|
||||
return ( is_read_supported< typename View::value_type
|
||||
, jpeg_tag
|
||||
>::_color_space == JCS_RGB );
|
||||
}
|
||||
|
||||
return ( is_read_supported< typename View::value_type
|
||||
, jpeg_tag
|
||||
>::_color_space == info._color_space );
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< jpeg_tag >& /* info */
|
||||
, std::false_type // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
+317
@@ -0,0 +1,317 @@
|
||||
//
|
||||
// Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READ_HPP
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/base.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
|
||||
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/conversion_policies.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
|
||||
#include <csetjmp>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4512) //assignment operator could not be generated
|
||||
#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
|
||||
#endif
|
||||
|
||||
///
|
||||
/// JPEG Reader
|
||||
///
|
||||
template< typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
class reader< Device
|
||||
, jpeg_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
: public reader_base< jpeg_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
, public reader_backend< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
{
|
||||
private:
|
||||
|
||||
using this_t = reader<Device, jpeg_tag, ConversionPolicy>;
|
||||
using cc_t = typename ConversionPolicy::color_converter_type;
|
||||
|
||||
public:
|
||||
|
||||
using backend_t = reader_backend<Device, jpeg_tag>;
|
||||
|
||||
public:
|
||||
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
reader( const Device& io_dev
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: reader_base< jpeg_tag
|
||||
, ConversionPolicy
|
||||
>()
|
||||
|
||||
, backend_t( io_dev
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
reader( const Device& io_dev
|
||||
, const typename ConversionPolicy::color_converter_type& cc
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: reader_base< jpeg_tag
|
||||
, ConversionPolicy
|
||||
>( cc )
|
||||
, backend_t( io_dev
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
// Fire exception in case of error.
|
||||
if( setjmp( this->_mark ))
|
||||
{
|
||||
this->raise_error();
|
||||
}
|
||||
|
||||
this->get()->dct_method = this->_settings._dct_method;
|
||||
|
||||
using is_read_and_convert_t = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
>::type;
|
||||
|
||||
io_error_if( !detail::is_allowed< View >( this->_info
|
||||
, is_read_and_convert_t()
|
||||
)
|
||||
, "Image types aren't compatible."
|
||||
);
|
||||
|
||||
if( jpeg_start_decompress( this->get() ) == false )
|
||||
{
|
||||
io_error( "Cannot start decompression." );
|
||||
}
|
||||
|
||||
switch( this->_info._color_space )
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
{
|
||||
this->_scanline_length = this->_info._width;
|
||||
read_rows< gray8_pixel_t >( view );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case JCS_RGB:
|
||||
//!\todo add Y'CbCr? We loose image quality when reading JCS_YCbCr as JCS_RGB
|
||||
case JCS_YCbCr:
|
||||
{
|
||||
this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
|
||||
|
||||
read_rows< rgb8_pixel_t >( view );
|
||||
break;
|
||||
}
|
||||
|
||||
case JCS_CMYK:
|
||||
//!\todo add Y'CbCrK? We loose image quality when reading JCS_YCCK as JCS_CMYK
|
||||
case JCS_YCCK:
|
||||
{
|
||||
this->get()->out_color_space = JCS_CMYK;
|
||||
this->_scanline_length = this->_info._width * num_channels< cmyk8_view_t >::value;
|
||||
|
||||
read_rows< cmyk8_pixel_t >( view );
|
||||
|
||||
break;
|
||||
}
|
||||
default: { io_error( "Unsupported jpeg color space." ); }
|
||||
}
|
||||
|
||||
jpeg_finish_decompress ( this->get() );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template< typename ImagePixel
|
||||
, typename View
|
||||
>
|
||||
void read_rows( const View& view )
|
||||
{
|
||||
using buffer_t = std::vector<ImagePixel>;
|
||||
buffer_t buffer( this->_info._width );
|
||||
|
||||
// In case of an error we'll jump back to here and fire an exception.
|
||||
// @todo Is the buffer above cleaned up when the exception is thrown?
|
||||
// The strategy right now is to allocate necessary memory before
|
||||
// the setjmp.
|
||||
if( setjmp( this->_mark ))
|
||||
{
|
||||
this->raise_error();
|
||||
}
|
||||
|
||||
|
||||
JSAMPLE *row_adr = reinterpret_cast< JSAMPLE* >( &buffer[0] );
|
||||
|
||||
//Skip scanlines if necessary.
|
||||
for( int y = 0; y < this->_settings._top_left.y; ++y )
|
||||
{
|
||||
io_error_if( jpeg_read_scanlines( this->get()
|
||||
, &row_adr
|
||||
, 1
|
||||
) !=1
|
||||
, "jpeg_read_scanlines: fail to read JPEG file"
|
||||
);
|
||||
}
|
||||
|
||||
// Read data.
|
||||
for( int y = 0; y < view.height(); ++y )
|
||||
{
|
||||
io_error_if( jpeg_read_scanlines( this->get()
|
||||
, &row_adr
|
||||
, 1
|
||||
) != 1
|
||||
, "jpeg_read_scanlines: fail to read JPEG file"
|
||||
);
|
||||
|
||||
typename buffer_t::iterator beg = buffer.begin() + this->_settings._top_left.x;
|
||||
typename buffer_t::iterator end = beg + this->_settings._dim.x;
|
||||
|
||||
this->_cc_policy.read( beg
|
||||
, end
|
||||
, view.row_begin( y )
|
||||
);
|
||||
}
|
||||
|
||||
//@todo: There might be a better way to do that.
|
||||
while( this->get()->output_scanline < this->get()->image_height )
|
||||
{
|
||||
io_error_if( jpeg_read_scanlines( this->get()
|
||||
, &row_adr
|
||||
, 1
|
||||
) !=1
|
||||
, "jpeg_read_scanlines: fail to read JPEG file"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct jpeg_type_format_checker
|
||||
{
|
||||
jpeg_type_format_checker( jpeg_color_space::type color_space )
|
||||
: _color_space( color_space )
|
||||
{}
|
||||
|
||||
template< typename Image >
|
||||
bool apply()
|
||||
{
|
||||
return is_read_supported< typename get_pixel_type< typename Image::view_t >::type
|
||||
, jpeg_tag
|
||||
>::_color_space == _color_space;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
jpeg_color_space::type _color_space;
|
||||
};
|
||||
|
||||
struct jpeg_read_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply : public is_read_supported< typename get_pixel_type< View >::type
|
||||
, jpeg_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
///
|
||||
/// JPEG Dynamic Reader
|
||||
///
|
||||
template< typename Device >
|
||||
class dynamic_image_reader< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public reader< Device
|
||||
, jpeg_tag
|
||||
, detail::read_and_no_convert
|
||||
>
|
||||
{
|
||||
using parent_t = reader<Device, jpeg_tag, detail::read_and_no_convert>;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_reader( const Device& io_dev
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: parent_t( io_dev
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename ...Images >
|
||||
void apply( any_image< Images... >& images )
|
||||
{
|
||||
detail::jpeg_type_format_checker format_checker( this->_info._color_space != JCS_YCbCr
|
||||
? this->_info._color_space
|
||||
: JCS_RGB
|
||||
);
|
||||
|
||||
if( !detail::construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
io_error( "No matching image type between those of the given any_image and that of the file" );
|
||||
}
|
||||
else
|
||||
{
|
||||
this->init_image( images
|
||||
, this->_settings
|
||||
);
|
||||
|
||||
detail::dynamic_io_fnobj< detail::jpeg_read_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
variant2::visit( op
|
||||
, view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+320
@@ -0,0 +1,320 @@
|
||||
//
|
||||
// Copyright 2012 Christian Henning
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READER_BACKEND_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READER_BACKEND_HPP
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/base.hpp>
|
||||
|
||||
#include <csetjmp>
|
||||
#include <memory>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4512) //assignment operator could not be generated
|
||||
#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
///
|
||||
/// Wrapper for libjpeg's decompress object. Implements value semantics.
|
||||
///
|
||||
struct jpeg_decompress_wrapper
|
||||
{
|
||||
protected:
|
||||
|
||||
using jpeg_decompress_ptr_t = std::shared_ptr<jpeg_decompress_struct> ;
|
||||
|
||||
protected:
|
||||
|
||||
///
|
||||
/// Default Constructor
|
||||
///
|
||||
jpeg_decompress_wrapper()
|
||||
: _jpeg_decompress_ptr( new jpeg_decompress_struct()
|
||||
, jpeg_decompress_deleter
|
||||
)
|
||||
{}
|
||||
|
||||
jpeg_decompress_struct* get() { return _jpeg_decompress_ptr.get(); }
|
||||
const jpeg_decompress_struct* get() const { return _jpeg_decompress_ptr.get(); }
|
||||
|
||||
private:
|
||||
|
||||
static void jpeg_decompress_deleter( jpeg_decompress_struct* jpeg_decompress_ptr )
|
||||
{
|
||||
if( jpeg_decompress_ptr )
|
||||
{
|
||||
jpeg_destroy_decompress( jpeg_decompress_ptr );
|
||||
|
||||
delete jpeg_decompress_ptr;
|
||||
jpeg_decompress_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
jpeg_decompress_ptr_t _jpeg_decompress_ptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
///
|
||||
/// JPEG Backend
|
||||
///
|
||||
template< typename Device >
|
||||
struct reader_backend< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public jpeg_io_base
|
||||
, public detail::jpeg_decompress_wrapper
|
||||
{
|
||||
public:
|
||||
|
||||
using format_tag_t = jpeg_tag;
|
||||
|
||||
public:
|
||||
//
|
||||
// Constructor
|
||||
//
|
||||
reader_backend( const Device& io_dev
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: _io_dev( io_dev )
|
||||
, _settings( settings )
|
||||
, _info()
|
||||
|
||||
, _scanline_length( 0 )
|
||||
{
|
||||
get()->err = jpeg_std_error( &_jerr );
|
||||
get()->client_data = this;
|
||||
|
||||
// Error exit handler: does not return to caller.
|
||||
_jerr.error_exit = &reader_backend::error_exit;
|
||||
|
||||
if( setjmp( _mark ))
|
||||
{
|
||||
raise_error();
|
||||
}
|
||||
|
||||
_src._jsrc.bytes_in_buffer = 0;
|
||||
_src._jsrc.next_input_byte = buffer_;
|
||||
_src._jsrc.init_source = reinterpret_cast< void(*) ( j_decompress_ptr )>( &reader_backend< Device, jpeg_tag >::init_device );
|
||||
_src._jsrc.fill_input_buffer = reinterpret_cast< boolean(*)( j_decompress_ptr )>( &reader_backend< Device, jpeg_tag >::fill_buffer );
|
||||
_src._jsrc.skip_input_data = reinterpret_cast< void(*) ( j_decompress_ptr
|
||||
, long num_bytes
|
||||
) >( &reader_backend< Device, jpeg_tag >::skip_input_data );
|
||||
_src._jsrc.term_source = reinterpret_cast< void(*) ( j_decompress_ptr ) >( &reader_backend< Device, jpeg_tag >::close_device );
|
||||
_src._jsrc.resync_to_restart = jpeg_resync_to_restart;
|
||||
_src._this = this;
|
||||
|
||||
jpeg_create_decompress( get() );
|
||||
|
||||
get()->src = &_src._jsrc;
|
||||
|
||||
jpeg_read_header( get()
|
||||
, TRUE
|
||||
);
|
||||
|
||||
io_error_if( get()->data_precision != 8
|
||||
, "Image file is not supported."
|
||||
);
|
||||
|
||||
//
|
||||
read_header();
|
||||
|
||||
//
|
||||
if( _settings._dim.x == 0 )
|
||||
{
|
||||
_settings._dim.x = _info._width;
|
||||
}
|
||||
|
||||
if( _settings._dim.y == 0 )
|
||||
{
|
||||
_settings._dim.y = _info._height;
|
||||
}
|
||||
}
|
||||
|
||||
/// Read image header.
|
||||
void read_header()
|
||||
{
|
||||
_info._width = get()->image_width;
|
||||
_info._height = get()->image_height;
|
||||
_info._num_components = get()->num_components;
|
||||
_info._color_space = get()->jpeg_color_space;
|
||||
_info._data_precision = get()->data_precision;
|
||||
|
||||
_info._density_unit = get()->density_unit;
|
||||
_info._x_density = get()->X_density;
|
||||
_info._y_density = get()->Y_density;
|
||||
|
||||
// obtain real world dimensions
|
||||
// taken from https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/read.cpp#cl-62
|
||||
|
||||
jpeg_calc_output_dimensions( get() );
|
||||
|
||||
double units_conversion = 0;
|
||||
if (get()->density_unit == 1) // dots per inch
|
||||
{
|
||||
units_conversion = 25.4; // millimeters in an inch
|
||||
}
|
||||
else if (get()->density_unit == 2) // dots per cm
|
||||
{
|
||||
units_conversion = 10; // millimeters in a centimeter
|
||||
}
|
||||
|
||||
_info._pixel_width_mm = get()->X_density ? (get()->output_width / double(get()->X_density)) * units_conversion : 0;
|
||||
_info._pixel_height_mm = get()->Y_density ? (get()->output_height / double(get()->Y_density)) * units_conversion : 0;
|
||||
}
|
||||
|
||||
/// Return image read settings.
|
||||
const image_read_settings< jpeg_tag >& get_settings()
|
||||
{
|
||||
return _settings;
|
||||
}
|
||||
|
||||
/// Return image header info.
|
||||
const image_read_info< jpeg_tag >& get_info()
|
||||
{
|
||||
return _info;
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (jpeg_image_width::type) img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
|
||||
}
|
||||
|
||||
|
||||
if( _settings._dim.y > 0 )
|
||||
{
|
||||
if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (jpeg_image_height::type) img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
// Taken from jerror.c
|
||||
/*
|
||||
* Error exit handler: must not return to caller.
|
||||
*
|
||||
* Applications may override this if they want to get control back after
|
||||
* an error. Typically one would longjmp somewhere instead of exiting.
|
||||
* The setjmp buffer can be made a private field within an expanded error
|
||||
* handler object. Note that the info needed to generate an error message
|
||||
* is stored in the error object, so you can generate the message now or
|
||||
* later, at your convenience.
|
||||
* You should make sure that the JPEG object is cleaned up (with jpeg_abort
|
||||
* or jpeg_destroy) at some point.
|
||||
*/
|
||||
static void error_exit( j_common_ptr cinfo )
|
||||
{
|
||||
reader_backend< Device, jpeg_tag >* mgr = reinterpret_cast< reader_backend< Device, jpeg_tag >* >( cinfo->client_data );
|
||||
|
||||
longjmp( mgr->_mark, 1 );
|
||||
}
|
||||
|
||||
void raise_error()
|
||||
{
|
||||
// we clean up in the destructor
|
||||
|
||||
io_error( "jpeg is invalid." );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// See jdatasrc.c for default implementation for the following static member functions.
|
||||
|
||||
static void init_device( jpeg_decompress_struct* cinfo )
|
||||
{
|
||||
gil_jpeg_source_mgr* src = reinterpret_cast< gil_jpeg_source_mgr* >( cinfo->src );
|
||||
src->_jsrc.bytes_in_buffer = 0;
|
||||
src->_jsrc.next_input_byte = src->_this->buffer_;
|
||||
}
|
||||
|
||||
static boolean fill_buffer( jpeg_decompress_struct* cinfo )
|
||||
{
|
||||
gil_jpeg_source_mgr* src = reinterpret_cast< gil_jpeg_source_mgr* >( cinfo->src );
|
||||
size_t count = src->_this->_io_dev.read(src->_this->buffer_, sizeof(src->_this->buffer_) );
|
||||
|
||||
if( count <= 0 )
|
||||
{
|
||||
// libjpeg does that: adding an EOF marker
|
||||
src->_this->buffer_[0] = (JOCTET) 0xFF;
|
||||
src->_this->buffer_[1] = (JOCTET) JPEG_EOI;
|
||||
count = 2;
|
||||
}
|
||||
|
||||
src->_jsrc.next_input_byte = src->_this->buffer_;
|
||||
src->_jsrc.bytes_in_buffer = count;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void skip_input_data( jpeg_decompress_struct * cinfo, long num_bytes )
|
||||
{
|
||||
gil_jpeg_source_mgr* src = reinterpret_cast< gil_jpeg_source_mgr* >( cinfo->src );
|
||||
|
||||
if( num_bytes > 0 )
|
||||
{
|
||||
while( num_bytes > long( src->_jsrc.bytes_in_buffer ))
|
||||
{
|
||||
num_bytes -= (long) src->_jsrc.bytes_in_buffer;
|
||||
fill_buffer( cinfo );
|
||||
}
|
||||
|
||||
src->_jsrc.next_input_byte += num_bytes;
|
||||
src->_jsrc.bytes_in_buffer -= num_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
static void close_device( jpeg_decompress_struct* ) {}
|
||||
|
||||
public:
|
||||
|
||||
Device _io_dev;
|
||||
|
||||
image_read_settings< jpeg_tag > _settings;
|
||||
image_read_info< jpeg_tag > _info;
|
||||
|
||||
std::size_t _scanline_length;
|
||||
|
||||
struct gil_jpeg_source_mgr
|
||||
{
|
||||
jpeg_source_mgr _jsrc;
|
||||
reader_backend* _this;
|
||||
};
|
||||
|
||||
gil_jpeg_source_mgr _src;
|
||||
|
||||
// libjpeg default is 4096 - see jdatasrc.c
|
||||
JOCTET buffer_[4096];
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
+152
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SCANLINE_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SCANLINE_READ_HPP
|
||||
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/detail/base.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/reader_backend.hpp>
|
||||
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/conversion_policies.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/scanline_read_iterator.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
|
||||
#include <csetjmp>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
|
||||
#endif
|
||||
|
||||
///
|
||||
/// JPEG Scanline Reader
|
||||
///
|
||||
template< typename Device >
|
||||
class scanline_reader< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public reader_backend< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
|
||||
using tag_t = jpeg_tag;
|
||||
using backend_t = reader_backend<Device, tag_t>;
|
||||
using this_t = scanline_reader<Device, tag_t>;
|
||||
using iterator_t = scanline_read_iterator<this_t>;
|
||||
|
||||
public:
|
||||
scanline_reader( Device& device
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: reader_backend< Device
|
||||
, jpeg_tag
|
||||
>( device
|
||||
, settings
|
||||
)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
void read( byte_t* dst
|
||||
, int
|
||||
)
|
||||
{
|
||||
// Fire exception in case of error.
|
||||
if( setjmp( this->_mark )) { this->raise_error(); }
|
||||
|
||||
// read data
|
||||
read_scanline( dst );
|
||||
}
|
||||
|
||||
/// Skip over a scanline.
|
||||
void skip( byte_t* dst, int )
|
||||
{
|
||||
// Fire exception in case of error.
|
||||
if( setjmp( this->_mark )) { this->raise_error(); }
|
||||
|
||||
// read data
|
||||
read_scanline( dst );
|
||||
}
|
||||
|
||||
iterator_t begin() { return iterator_t( *this ); }
|
||||
iterator_t end() { return iterator_t( *this, this->_info._height ); }
|
||||
|
||||
private:
|
||||
|
||||
void initialize()
|
||||
{
|
||||
this->get()->dct_method = this->_settings._dct_method;
|
||||
|
||||
io_error_if( jpeg_start_decompress( this->get() ) == false
|
||||
, "Cannot start decompression." );
|
||||
|
||||
switch( this->_info._color_space )
|
||||
{
|
||||
case JCS_GRAYSCALE:
|
||||
{
|
||||
this->_scanline_length = this->_info._width;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case JCS_RGB:
|
||||
//!\todo add Y'CbCr? We loose image quality when reading JCS_YCbCr as JCS_RGB
|
||||
case JCS_YCbCr:
|
||||
{
|
||||
this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case JCS_CMYK:
|
||||
//!\todo add Y'CbCrK? We loose image quality when reading JCS_YCCK as JCS_CMYK
|
||||
case JCS_YCCK:
|
||||
{
|
||||
this->get()->out_color_space = JCS_CMYK;
|
||||
this->_scanline_length = this->_info._width * num_channels< cmyk8_view_t >::value;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: { io_error( "Unsupported jpeg color space." ); }
|
||||
}
|
||||
}
|
||||
|
||||
void read_scanline( byte_t* dst )
|
||||
{
|
||||
JSAMPLE *row_adr = reinterpret_cast< JSAMPLE* >( dst );
|
||||
|
||||
// Read data.
|
||||
io_error_if( jpeg_read_scanlines( this->get()
|
||||
, &row_adr
|
||||
, 1
|
||||
) != 1
|
||||
, "jpeg_read_scanlines: fail to read JPEG file"
|
||||
);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SUPPORTED_TYPES_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SUPPORTED_TYPES_HPP
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/gil/color_base.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
// Read support
|
||||
|
||||
template< jpeg_color_space::type ColorSpace >
|
||||
struct jpeg_rw_support_base
|
||||
{
|
||||
static const jpeg_color_space::type _color_space = ColorSpace;
|
||||
};
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct jpeg_read_support : read_support_false
|
||||
, jpeg_rw_support_base< JCS_UNKNOWN > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_read_support<uint8_t
|
||||
, rgb_t
|
||||
> : read_support_true
|
||||
, jpeg_rw_support_base< JCS_RGB > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_read_support<uint8_t
|
||||
, cmyk_t
|
||||
> : read_support_true
|
||||
, jpeg_rw_support_base< JCS_CMYK > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_read_support<uint8_t
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, jpeg_rw_support_base< JCS_GRAYSCALE > {};
|
||||
|
||||
// Write support
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct jpeg_write_support : write_support_false
|
||||
, jpeg_rw_support_base< JCS_UNKNOWN > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_write_support<uint8_t
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, jpeg_rw_support_base< JCS_GRAYSCALE > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_write_support<uint8_t
|
||||
, rgb_t
|
||||
> : write_support_true
|
||||
, jpeg_rw_support_base< JCS_RGB > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_write_support<uint8_t
|
||||
, cmyk_t
|
||||
> : write_support_true
|
||||
, jpeg_rw_support_base< JCS_CMYK > {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel, jpeg_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::jpeg_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
using parent_t = detail::jpeg_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>;
|
||||
|
||||
static const typename jpeg_color_space::type _color_space = parent_t::_color_space;
|
||||
};
|
||||
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, jpeg_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::jpeg_write_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
//
|
||||
// Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/supported_types.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/writer_backend.hpp>
|
||||
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4512) //assignment operator could not be generated
|
||||
#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
struct jpeg_write_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply
|
||||
: public is_write_supported< typename get_pixel_type< View >::type
|
||||
, jpeg_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
} // detail
|
||||
|
||||
///
|
||||
/// JPEG Writer
|
||||
///
|
||||
template< typename Device >
|
||||
class writer< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public writer_backend< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
|
||||
using backend_t = writer_backend<Device, jpeg_tag>;
|
||||
|
||||
public:
|
||||
|
||||
writer( const Device& io_dev
|
||||
, const image_write_info< jpeg_tag >& info
|
||||
)
|
||||
: backend_t( io_dev
|
||||
, info
|
||||
)
|
||||
{}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
write_rows( view );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename View>
|
||||
void write_rows( const View& view )
|
||||
{
|
||||
std::vector< pixel< typename channel_type< View >::type
|
||||
, layout<typename color_space_type< View >::type >
|
||||
>
|
||||
> row_buffer( view.width() );
|
||||
|
||||
// In case of an error we'll jump back to here and fire an exception.
|
||||
// @todo Is the buffer above cleaned up when the exception is thrown?
|
||||
// The strategy right now is to allocate necessary memory before
|
||||
// the setjmp.
|
||||
if( setjmp( this->_mark )) { this->raise_error(); }
|
||||
|
||||
using channel_t = typename channel_type<typename View::value_type>::type;
|
||||
|
||||
this->get()->image_width = JDIMENSION( view.width() );
|
||||
this->get()->image_height = JDIMENSION( view.height() );
|
||||
this->get()->input_components = num_channels<View>::value;
|
||||
this->get()->in_color_space = detail::jpeg_write_support< channel_t
|
||||
, typename color_space_type< View >::type
|
||||
>::_color_space;
|
||||
|
||||
jpeg_set_defaults( this->get() );
|
||||
|
||||
jpeg_set_quality( this->get()
|
||||
, this->_info._quality
|
||||
, TRUE
|
||||
);
|
||||
|
||||
// Needs to be done after jpeg_set_defaults() since it's overridding this value back to slow.
|
||||
this->get()->dct_method = this->_info._dct_method;
|
||||
|
||||
|
||||
// set the pixel dimensions
|
||||
this->get()->density_unit = this->_info._density_unit;
|
||||
this->get()->X_density = this->_info._x_density;
|
||||
this->get()->Y_density = this->_info._y_density;
|
||||
|
||||
// done reading header information
|
||||
|
||||
jpeg_start_compress( this->get()
|
||||
, TRUE
|
||||
);
|
||||
|
||||
JSAMPLE* row_addr = reinterpret_cast< JSAMPLE* >( &row_buffer[0] );
|
||||
|
||||
for( int y =0; y != view.height(); ++ y )
|
||||
{
|
||||
std::copy( view.row_begin( y )
|
||||
, view.row_end ( y )
|
||||
, row_buffer.begin()
|
||||
);
|
||||
|
||||
jpeg_write_scanlines( this->get()
|
||||
, &row_addr
|
||||
, 1
|
||||
);
|
||||
}
|
||||
|
||||
jpeg_finish_compress ( this->get() );
|
||||
}
|
||||
};
|
||||
|
||||
///
|
||||
/// JPEG Dyamic Image Writer
|
||||
///
|
||||
template< typename Device >
|
||||
class dynamic_image_writer< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public writer< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
{
|
||||
using parent_t = writer<Device, jpeg_tag>;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_writer( const Device& io_dev
|
||||
, const image_write_info< jpeg_tag >& info
|
||||
)
|
||||
: parent_t( io_dev
|
||||
, info
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename ...Views >
|
||||
void apply( const any_image_view< Views... >& views )
|
||||
{
|
||||
detail::dynamic_io_fnobj< detail::jpeg_write_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
variant2::visit( op, views );
|
||||
}
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif
|
||||
+194
@@ -0,0 +1,194 @@
|
||||
//
|
||||
// Copyright 2012 Christian Henning
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITER_BACKEND_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITER_BACKEND_HPP
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/base.hpp>
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4512) //assignment operator could not be generated
|
||||
#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
///
|
||||
/// Wrapper for libjpeg's compress object. Implements value semantics.
|
||||
///
|
||||
struct jpeg_compress_wrapper
|
||||
{
|
||||
protected:
|
||||
|
||||
using jpeg_compress_ptr_t = std::shared_ptr<jpeg_compress_struct>;
|
||||
|
||||
protected:
|
||||
|
||||
///
|
||||
/// Default Constructor
|
||||
///
|
||||
jpeg_compress_wrapper()
|
||||
: _jpeg_compress_ptr( new jpeg_compress_struct()
|
||||
, jpeg_compress_deleter
|
||||
)
|
||||
{}
|
||||
|
||||
jpeg_compress_struct* get() { return _jpeg_compress_ptr.get(); }
|
||||
const jpeg_compress_struct* get() const { return _jpeg_compress_ptr.get(); }
|
||||
|
||||
private:
|
||||
|
||||
static void jpeg_compress_deleter( jpeg_compress_struct* jpeg_compress_ptr )
|
||||
{
|
||||
if( jpeg_compress_ptr )
|
||||
{
|
||||
jpeg_destroy_compress( jpeg_compress_ptr );
|
||||
|
||||
delete jpeg_compress_ptr;
|
||||
jpeg_compress_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
jpeg_compress_ptr_t _jpeg_compress_ptr;
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
///
|
||||
/// JPEG Writer Backend
|
||||
///
|
||||
template< typename Device >
|
||||
struct writer_backend< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public jpeg_io_base
|
||||
, public detail::jpeg_compress_wrapper
|
||||
{
|
||||
public:
|
||||
|
||||
using format_tag_t = jpeg_tag;
|
||||
|
||||
public:
|
||||
///
|
||||
/// Constructor
|
||||
///
|
||||
writer_backend( const Device& io_dev
|
||||
, const image_write_info< jpeg_tag >& info
|
||||
)
|
||||
: _io_dev( io_dev )
|
||||
, _info( info )
|
||||
{
|
||||
get()->err = jpeg_std_error( &_jerr );
|
||||
get()->client_data = this;
|
||||
|
||||
// Error exit handler: does not return to caller.
|
||||
_jerr.error_exit = &writer_backend< Device, jpeg_tag >::error_exit;
|
||||
|
||||
// Fire exception in case of error.
|
||||
if( setjmp( _mark )) { raise_error(); }
|
||||
|
||||
_dest._jdest.free_in_buffer = sizeof( buffer );
|
||||
_dest._jdest.next_output_byte = buffer;
|
||||
_dest._jdest.init_destination = reinterpret_cast< void(*) ( j_compress_ptr ) >( &writer_backend< Device, jpeg_tag >::init_device );
|
||||
_dest._jdest.empty_output_buffer = reinterpret_cast< boolean(*)( j_compress_ptr ) >( &writer_backend< Device, jpeg_tag >::empty_buffer );
|
||||
_dest._jdest.term_destination = reinterpret_cast< void(*) ( j_compress_ptr ) >( &writer_backend< Device, jpeg_tag >::close_device );
|
||||
_dest._this = this;
|
||||
|
||||
jpeg_create_compress( get() );
|
||||
get()->dest = &_dest._jdest;
|
||||
}
|
||||
|
||||
~writer_backend()
|
||||
{
|
||||
// JPEG compression object destruction does not signal errors,
|
||||
// unlike jpeg_finish_compress called elsewhere,
|
||||
// so there is no need for the setjmp bookmark here.
|
||||
jpeg_destroy_compress( get() );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
struct gil_jpeg_destination_mgr
|
||||
{
|
||||
jpeg_destination_mgr _jdest;
|
||||
writer_backend< Device
|
||||
, jpeg_tag
|
||||
>* _this;
|
||||
};
|
||||
|
||||
static void init_device( jpeg_compress_struct* cinfo )
|
||||
{
|
||||
gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
|
||||
|
||||
dest->_jdest.free_in_buffer = sizeof( dest->_this->buffer );
|
||||
dest->_jdest.next_output_byte = dest->_this->buffer;
|
||||
}
|
||||
|
||||
static boolean empty_buffer( jpeg_compress_struct* cinfo )
|
||||
{
|
||||
gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
|
||||
|
||||
dest->_this->_io_dev.write( dest->_this->buffer
|
||||
, buffer_size
|
||||
);
|
||||
|
||||
writer_backend<Device,jpeg_tag>::init_device( cinfo );
|
||||
return static_cast<boolean>(TRUE);
|
||||
}
|
||||
|
||||
static void close_device( jpeg_compress_struct* cinfo )
|
||||
{
|
||||
writer_backend< Device
|
||||
, jpeg_tag
|
||||
>::empty_buffer( cinfo );
|
||||
|
||||
gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
|
||||
|
||||
dest->_this->_io_dev.flush();
|
||||
}
|
||||
|
||||
void raise_error()
|
||||
{
|
||||
io_error( "Cannot write jpeg file." );
|
||||
}
|
||||
|
||||
static void error_exit( j_common_ptr cinfo )
|
||||
{
|
||||
writer_backend< Device, jpeg_tag >* mgr = reinterpret_cast< writer_backend< Device, jpeg_tag >* >( cinfo->client_data );
|
||||
|
||||
longjmp( mgr->_mark, 1 );
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Device _io_dev;
|
||||
|
||||
image_write_info< jpeg_tag > _info;
|
||||
|
||||
gil_jpeg_destination_mgr _dest;
|
||||
|
||||
static const unsigned int buffer_size = 1024;
|
||||
JOCTET buffer[buffer_size];
|
||||
};
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user