Added thirdparty: boost library

This commit is contained in:
Viacheslav Demydiuk
2024-01-06 19:55:56 +02:00
parent bf49f439e1
commit bccd1e7051
15683 changed files with 3239840 additions and 0 deletions
+38
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+161
View File
@@ -0,0 +1,161 @@
//
// Copyright 2007-2008 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_OLD_HPP
#define BOOST_GIL_EXTENSION_IO_JPEG_OLD_HPP
#include <boost/gil/extension/io/jpeg.hpp>
namespace boost { namespace gil {
/// \ingroup JPEG_IO
/// \brief Returns the width and height of the JPEG file at the specified location.
/// Throws std::ios_base::failure if the location does not correspond to a valid JPEG file
template<typename String>
inline point_t jpeg_read_dimensions(String const& filename)
{
using backend_t = typename get_reader_backend<String, jpeg_tag>::type;
backend_t backend = read_image_info(filename, jpeg_tag());
return { backend._info._width, backend._info._height };
}
/// \ingroup JPEG_IO
/// \brief Loads the image specified by the given jpeg image file name into the given view.
/// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension.
/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not
/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
template< typename String
, typename View
>
inline
void jpeg_read_view( const String& filename
, const View& view
)
{
read_view( filename
, view
, jpeg_tag()
);
}
/// \ingroup JPEG_IO
/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it.
/// Triggers a compile assert if the image color space or channel depth are not supported by the JPEG library or by the I/O extension.
/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not
/// compatible with the ones specified by Image
template< typename String
, typename Image
>
inline
void jpeg_read_image( const String& filename
, Image& img
)
{
read_image( filename
, img
, jpeg_tag()
);
}
/// \ingroup JPEG_IO
/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view.
/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its dimensions don't match the ones of the view.
template< typename String
, typename View
, typename CC
>
inline
void jpeg_read_and_convert_view( const String& filename
, const View& view
, CC cc
)
{
read_and_convert_view( filename
, view
, cc
, jpeg_tag()
);
}
/// \ingroup JPEG_IO
/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view.
/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its dimensions don't match the ones of the view.
template< typename String
, typename View
>
inline
void jpeg_read_and_convert_view( const String& filename
, const View& view
)
{
read_and_convert_view( filename
, view
, jpeg_tag()
);
}
/// \ingroup JPEG_IO
/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it.
/// Throws std::ios_base::failure if the file is not a valid JPEG file
template< typename String
, typename Image
, typename CC
>
inline
void jpeg_read_and_convert_image( const String& filename
, Image& img
, CC cc
)
{
read_and_convert_image( filename
, img
, cc
, jpeg_tag()
);
}
/// \ingroup JPEG_IO
/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it.
/// Throws std::ios_base::failure if the file is not a valid JPEG file
template< typename String
, typename Image
>
inline
void jpeg_read_and_convert_image( const String filename
, Image& img
)
{
read_and_convert_image( filename
, img
, jpeg_tag()
);
}
/// \ingroup JPEG_IO
/// \brief Saves the view to a jpeg file specified by the given jpeg image file name.
/// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension.
/// Throws std::ios_base::failure if it fails to create the file.
template< typename String
, typename View
>
inline
void jpeg_write_view( const String& filename
, const View& view
, int quality = jpeg_quality::default_value
)
{
write_view( filename
, view
, image_write_info< jpeg_tag >( quality )
);
}
} // namespace gil
} // namespace boost
#endif
+30
View File
@@ -0,0 +1,30 @@
//
// Copyright 2007-2008 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_READ_HPP
#define BOOST_GIL_EXTENSION_IO_JPEG_READ_HPP
#define BOOST_GIL_EXTENSION_IO_JPEG_READ_ENABLED // TODO: Document, explain, review
#include <boost/gil/extension/io/jpeg/tags.hpp>
#include <boost/gil/extension/io/jpeg/detail/read.hpp>
#include <boost/gil/extension/io/jpeg/detail/scanline_read.hpp>
#include <boost/gil/extension/io/jpeg/detail/supported_types.hpp>
#include <boost/gil/io/get_reader.hpp>
#include <boost/gil/io/make_backend.hpp>
#include <boost/gil/io/make_dynamic_image_reader.hpp>
#include <boost/gil/io/make_reader.hpp>
#include <boost/gil/io/make_scanline_reader.hpp>
#include <boost/gil/io/read_and_convert_image.hpp>
#include <boost/gil/io/read_and_convert_view.hpp>
#include <boost/gil/io/read_image.hpp>
#include <boost/gil/io/read_image_info.hpp>
#include <boost/gil/io/read_view.hpp>
#include <boost/gil/io/scanline_read_iterator.hpp>
#endif
+231
View File
@@ -0,0 +1,231 @@
//
// 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_TAGS_HPP
#define BOOST_GIL_EXTENSION_IO_JPEG_TAGS_HPP
// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_C_LIB_COMPILED_AS_CPLUSPLUS
extern "C" {
#else
// DONT_USE_EXTERN_C introduced in v7 of the IJG library.
// By default the v7 IJG headers check for __cplusplus being defined and
// wrap the content in an 'extern "C"' block if it's present.
// When DONT_USE_EXTERN_C is defined, this wrapping is not performed.
#ifndef DONT_USE_EXTERN_C
#define DONT_USE_EXTERN_C 1
#endif
#endif
#include <cstdio> // jpeglib doesn't know about FILE
#include <jerror.h>
#include <jpeglib.h>
#ifndef BOOST_GIL_EXTENSION_IO_JPEG_C_LIB_COMPILED_AS_CPLUSPLUS
}
#endif
#include <boost/gil/io/base.hpp>
namespace boost { namespace gil {
/// Defines jpeg tag.
struct jpeg_tag : format_tag {};
/// see http://en.wikipedia.org/wiki/JPEG for reference
/// Defines type for image width property.
struct jpeg_image_width : property_base< JDIMENSION > {};
/// Defines type for image height property.
struct jpeg_image_height : property_base< JDIMENSION > {};
/// Defines type for number of components property.
struct jpeg_num_components : property_base< int > {};
/// Defines type for color space property.
struct jpeg_color_space : property_base< J_COLOR_SPACE > {};
/// Defines type for jpeg quality property.
struct jpeg_quality : property_base< int >
{
static const type default_value = 100;
};
/// Defines type for data precision property.
struct jpeg_data_precision : property_base< int > {};
/// JFIF code for pixel size units
struct jpeg_density_unit : property_base< UINT8 >
{
static const type default_value = 0;
};
/// pixel density
struct jpeg_pixel_density : property_base< UINT16 >
{
static const type default_value = 0;
};
/// Defines type for dct ( discrete cosine transformation ) method property.
struct jpeg_dct_method : property_base< J_DCT_METHOD >
{
static const type slow = JDCT_ISLOW;
static const type fast = JDCT_IFAST;
static const type floating_pt = JDCT_FLOAT;
static const type fastest = JDCT_FASTEST;
static const type default_value = slow;
};
/// Read information for jpeg images.
///
/// The structure is returned when using read_image_info.
template<>
struct image_read_info< jpeg_tag >
{
image_read_info()
: _width ( 0 )
, _height( 0 )
, _num_components( 0 )
, _color_space( J_COLOR_SPACE( 0 ))
, _data_precision( 0 )
, _density_unit ( 0 )
, _x_density ( 0 )
, _y_density ( 0 )
, _pixel_width_mm ( 0.0 )
, _pixel_height_mm( 0.0 )
{}
/// The image width.
jpeg_image_width::type _width;
/// The image height.
jpeg_image_height::type _height;
/// The number of channels.
jpeg_num_components::type _num_components;
/// The color space.
jpeg_color_space::type _color_space;
/// The width of channel.
/// I believe this number is always 8 in the case libjpeg is built with 8.
/// see: http://www.asmail.be/msg0055405033.html
jpeg_data_precision::type _data_precision;
/// Density conversion unit.
jpeg_density_unit::type _density_unit;
jpeg_pixel_density::type _x_density;
jpeg_pixel_density::type _y_density;
/// Real-world dimensions
double _pixel_width_mm;
double _pixel_height_mm;
};
/// Read settings for jpeg images.
///
/// The structure can be used for all read_xxx functions, except read_image_info.
template<>
struct image_read_settings< jpeg_tag > : public image_read_settings_base
{
/// Default constructor
image_read_settings()
: image_read_settings_base()
, _dct_method( jpeg_dct_method::default_value )
{}
/// Constructor
/// \param top_left Top left coordinate for reading partial image.
/// \param dim Dimensions for reading partial image.
/// \param dct_method Specifies dct method.
image_read_settings( point_t const& top_left
, point_t const& dim
, jpeg_dct_method::type dct_method = jpeg_dct_method::default_value
)
: image_read_settings_base( top_left
, dim
)
, _dct_method( dct_method )
{}
/// The dct ( discrete cosine transformation ) method.
jpeg_dct_method::type _dct_method;
};
/// Write information for jpeg images.
///
/// The structure can be used for write_view() function.
template<>
struct image_write_info< jpeg_tag >
{
/// Constructor
/// \param quality Defines the jpeg quality.
/// \param dct_method Defines the DCT method.
/// \param density_unit Defines the density unit.
/// \param x_density Defines the x density.
/// \param y_density Defines the y density.
image_write_info( const jpeg_quality::type quality = jpeg_quality::default_value
, const jpeg_dct_method::type dct_method = jpeg_dct_method::default_value
, const jpeg_density_unit::type density_unit = jpeg_density_unit::default_value
, const jpeg_pixel_density::type x_density = jpeg_pixel_density::default_value
, const jpeg_pixel_density::type y_density = jpeg_pixel_density::default_value
)
: _quality ( quality )
, _dct_method( dct_method )
, _density_unit( density_unit )
, _x_density ( x_density )
, _y_density ( y_density )
{}
/// The jpeg quality.
jpeg_quality::type _quality;
/// The dct ( discrete cosine transformation ) method.
jpeg_dct_method::type _dct_method;
/// Density conversion unit.
jpeg_density_unit::type _density_unit;
/// Pixel density dimensions.
jpeg_pixel_density::type _x_density;
jpeg_pixel_density::type _y_density;
/// Sets the pixel dimensions.
void set_pixel_dimensions( int image_width // in pixels
, int image_height // in pixels
, double pixel_width // in mm
, double pixel_height // in mm
)
{
_density_unit = 2; // dots per cm
_x_density = round( image_width / ( pixel_width / 10 ));
_y_density = round( image_height / ( pixel_height / 10 ));
}
private:
UINT16 round( double d )
{
return static_cast< UINT16 >( d + 0.5 );
}
};
} // namespace gil
} // namespace boost
#endif
+19
View File
@@ -0,0 +1,19 @@
//
// Copyright 2007-2008 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_WRITE_HPP
#define BOOST_GIL_EXTENSION_IO_JPEG_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/write.hpp>
#include <boost/gil/io/make_writer.hpp>
#include <boost/gil/io/make_dynamic_image_writer.hpp>
#include <boost/gil/io/write_view.hpp>
#endif