WIP. Scale cover art option. Seems to work
This commit is contained in:
@@ -16,6 +16,7 @@ lms_SOURCES = \
|
||||
$(top_srcdir)/av/FormatContext.cpp \
|
||||
$(top_srcdir)/av/InputFormatContext.cpp \
|
||||
$(top_srcdir)/av/Stream.cpp \
|
||||
$(top_srcdir)/cover/CoverArt.cpp \
|
||||
$(top_srcdir)/cover/CoverArtGrabber.cpp \
|
||||
$(top_srcdir)/ui/LmsApplication.cpp \
|
||||
$(top_srcdir)/ui/audio/AudioWidget.cpp \
|
||||
|
||||
@@ -3,6 +3,9 @@
|
||||
- Do the feature
|
||||
- Admin account to add/remove users, add path to watch for Audio/Video files
|
||||
|
||||
[Cover]
|
||||
- Scaling: find something more "reliable" than GIL and its customs extensions (adobe work, io_new)
|
||||
|
||||
[Database]
|
||||
- When removing a track, make sure to remove genre/artist/release if last of it
|
||||
- Use Inotify like system to watch modified/added files
|
||||
|
||||
@@ -9,8 +9,6 @@ namespace Av
|
||||
InputFormatContext::InputFormatContext(const boost::filesystem::path& p)
|
||||
: _path(p)
|
||||
{
|
||||
std::cout << "Opening '" << p.string().c_str() << "'" << std::endl;
|
||||
|
||||
AVFormatContext* context = nullptr;
|
||||
|
||||
// The last three parameters specify the file format, buffer size and
|
||||
@@ -103,7 +101,6 @@ InputFormatContext::getPictures(std::vector< std::vector<unsigned char> >& pictu
|
||||
{
|
||||
if (native()->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
|
||||
{
|
||||
std::cout << "Found album art..." << std::endl;
|
||||
AVPacket pkt = native()->streams[i]->attached_pic;
|
||||
|
||||
std::vector<unsigned char> data;
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_ALL_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_ALL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "bmp_read.hpp"
|
||||
#include "bmp_write.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_ALL_HPP
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_IO_OLD_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_IO_OLD_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "bmp_all.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Returns the width and height of the BMP file at the specified location.
|
||||
/// Throws std::ios_base::failure if the location does not correspond to a valid BMP file
|
||||
template< typename String >
|
||||
inline
|
||||
point2< std::ptrdiff_t > bmp_read_dimensions( const String& filename )
|
||||
{
|
||||
image_read_info< bmp_tag > info = read_image_info( filename
|
||||
, bmp_tag()
|
||||
);
|
||||
|
||||
return point2< std::ptrdiff_t >( info._width
|
||||
, info._height
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Loads the image specified by the given bmp image file name into the given view.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the BMP library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid BMP 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 bmp_read_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_view( filename
|
||||
, view
|
||||
, bmp_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given bmp 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 BMP library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid BMP 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 bmp_read_image( const String& filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_image( filename
|
||||
, img
|
||||
, bmp_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Loads and color-converts the image specified by the given bmp image file name into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void bmp_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, cc
|
||||
, bmp_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Loads and color-converts the image specified by the given bmp image file name into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
>
|
||||
inline
|
||||
void bmp_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, bmp_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given bmp image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid BMP file
|
||||
template< typename String
|
||||
, typename Image
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void bmp_read_and_convert_image( const String& filename
|
||||
, Image& img
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, cc
|
||||
, bmp_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given bmp image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid BMP file
|
||||
template< typename String
|
||||
, typename Image
|
||||
>
|
||||
inline
|
||||
void bmp_read_and_convert_image( const String filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, bmp_tag()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup BMP_IO
|
||||
/// \brief Saves the view to a bmp file specified by the given bmp image file name.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the BMP 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 bmp_write_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
write_view( filename
|
||||
, view
|
||||
, bmp_tag()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_IO_OLD_HPP
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "bmp_tags.hpp"
|
||||
#include "formats/bmp/supported_types.hpp"
|
||||
#include "formats/bmp/read.hpp"
|
||||
|
||||
#include "detail/read_image.hpp"
|
||||
#include "detail/read_view.hpp"
|
||||
#include "detail/read_image_info.hpp"
|
||||
#include "detail/read_and_convert_image.hpp"
|
||||
#include "detail/read_and_convert_view.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_READ_HPP
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_TAGS_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_TAGS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "detail/base.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// Defines bmp tag.
|
||||
struct bmp_tag : format_tag {};
|
||||
|
||||
/// See http://en.wikipedia.org/wiki/BMP_file_format#BMP_File_Header for reference.
|
||||
|
||||
/// Defines type for offset value.
|
||||
struct bmp_offset : property_base< uint32_t > {};
|
||||
|
||||
/// Defines type for header sizes.
|
||||
struct bmp_header_size : property_base< uint32_t >
|
||||
{
|
||||
static const type _size = 14; /// Constant size for bmp file header size.
|
||||
static const type _win32_info_size = 40; /// Constant size for win32 bmp info header size.
|
||||
static const type _os2_info_size = 12; /// Constant size for os2 bmp info header size.
|
||||
};
|
||||
|
||||
/// Defines type for image width property.
|
||||
struct bmp_image_width : property_base< int32_t > {};
|
||||
|
||||
/// Defines type for image height property.
|
||||
struct bmp_image_height : property_base< int32_t > {};
|
||||
|
||||
/// Defines type for bits per pixels property.
|
||||
struct bmp_bits_per_pixel : property_base< uint16_t > {};
|
||||
|
||||
/// Defines type for compression property.
|
||||
struct bmp_compression : property_base< uint32_t >
|
||||
{
|
||||
static const type _rgb = 0; /// RGB without compression
|
||||
static const type _rle8 = 1; /// 8 bit index with RLE compression
|
||||
static const type _rle4 = 2; /// 4 bit index with RLE compression
|
||||
static const type _bitfield = 3; /// 16 or 32 bit fields without compression
|
||||
};
|
||||
|
||||
/// Defines type for image size property.
|
||||
struct bmp_image_size : property_base< uint32_t > {};
|
||||
|
||||
/// Defines type for horizontal resolution property.
|
||||
struct bmp_horizontal_resolution : property_base< int32_t > {};
|
||||
|
||||
/// Defines type for vertical resolution property.
|
||||
struct bmp_vertical_resolution : property_base< int32_t > {};
|
||||
|
||||
/// Defines type for number of colors property.
|
||||
struct bmp_num_colors : property_base< uint32_t > {};
|
||||
|
||||
/// Defines type for important number of colors property.
|
||||
struct bmp_num_important_colors : property_base< uint32_t > {};
|
||||
|
||||
static const uint32_t bmp_signature = 0x4D42; /// Constant signature for bmp file format.
|
||||
|
||||
/// Read information for bmp images.
|
||||
///
|
||||
/// The structure is returned when using read_image_info.
|
||||
template<>
|
||||
struct image_read_info< bmp_tag >
|
||||
{
|
||||
/// Default contructor.
|
||||
image_read_info< bmp_tag >()
|
||||
: _valid( false )
|
||||
{}
|
||||
|
||||
/// The offset, i.e. starting address, of the byte where the bitmap data can be found.
|
||||
bmp_offset::type _offset;
|
||||
|
||||
/// The size of this header:
|
||||
/// - 40 bytes for Windows V3 header
|
||||
/// - 12 bytes for OS/2 V1 header
|
||||
bmp_header_size::type _header_size;
|
||||
|
||||
/// The bitmap width in pixels ( signed integer ).
|
||||
bmp_image_width::type _width;
|
||||
|
||||
/// The bitmap height in pixels ( signed integer ).
|
||||
bmp_image_height::type _height;
|
||||
|
||||
/// The number of bits per pixel, which is the color depth of the image.
|
||||
/// Typical values are 1, 4, 8, 16, 24 and 32.
|
||||
bmp_bits_per_pixel::type _bits_per_pixel;
|
||||
|
||||
/// The compression method being used. See above for a list of possible values.
|
||||
bmp_compression::type _compression;
|
||||
|
||||
/// The image size. This is the size of the raw bitmap data (see below),
|
||||
/// and should not be confused with the file size.
|
||||
bmp_image_size::type _image_size;
|
||||
|
||||
/// The horizontal resolution of the image. (pixel per meter, signed integer)
|
||||
bmp_horizontal_resolution::type _horizontal_resolution;
|
||||
|
||||
/// The vertical resolution of the image. (pixel per meter, signed integer)
|
||||
bmp_vertical_resolution::type _vertical_resolution;
|
||||
|
||||
/// The number of colors in the color palette, or 0 to default to 2^n - 1.
|
||||
bmp_num_colors::type _num_colors;
|
||||
|
||||
/// The number of important colors used, or 0 when every color is important;
|
||||
/// generally ignored.
|
||||
bmp_num_important_colors::type _num_important_colors;
|
||||
|
||||
/// Used internaly to identify is the header has been read.
|
||||
bool _valid;
|
||||
};
|
||||
|
||||
/// Read settings for bmp images.
|
||||
///
|
||||
/// The structure can be used for all read_xxx functions, except read_image_info.
|
||||
template<>
|
||||
struct image_read_settings< bmp_tag > : public image_read_settings_base
|
||||
{
|
||||
/// Default constructor
|
||||
image_read_settings()
|
||||
: image_read_settings_base()
|
||||
{}
|
||||
|
||||
/// Constructor
|
||||
/// \param top_left Top left coordinate for reading partial image.
|
||||
/// \param dim Dimensions for reading partial image.
|
||||
image_read_settings( const point_t& top_left
|
||||
, const point_t& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Write information for bmp images.
|
||||
///
|
||||
/// The structure can be used for write_view() function.
|
||||
template<>
|
||||
struct image_write_info< bmp_tag >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_TAGS_HPP
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "bmp_tags.hpp"
|
||||
#include "formats/bmp/supported_types.hpp"
|
||||
#include "formats/bmp/write.hpp"
|
||||
|
||||
#include "detail/write_view.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_WRITE_HPP
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_DETAIL_BASE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_BASE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <ostream>
|
||||
#include <istream>
|
||||
#include <vector>
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
#include <boost/gil/utilities.hpp>
|
||||
#include <boost/gil/color_convert.hpp>
|
||||
#include <boost/gil/bit_aligned_pixel_reference.hpp>
|
||||
#include <boost/gil/bit_aligned_pixel_iterator.hpp>
|
||||
|
||||
#include <boost/gil/extension/toolbox/gil_extensions.hpp>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
#include "io_error.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
struct format_tag {};
|
||||
|
||||
template< typename Property >
|
||||
struct property_base
|
||||
{
|
||||
typedef Property type;
|
||||
};
|
||||
|
||||
template<typename FormatTag> struct is_format_tag : is_base_and_derived< format_tag
|
||||
, FormatTag
|
||||
> {};
|
||||
|
||||
struct image_read_settings_base
|
||||
{
|
||||
protected:
|
||||
|
||||
image_read_settings_base()
|
||||
: _top_left( 0, 0 )
|
||||
, _dim ( 0, 0 )
|
||||
{}
|
||||
|
||||
image_read_settings_base( const point_t& top_left
|
||||
, const point_t& dim
|
||||
)
|
||||
: _top_left( top_left )
|
||||
, _dim ( dim )
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
point_t _top_left;
|
||||
point_t _dim;
|
||||
};
|
||||
|
||||
/**
|
||||
* Boolean meta function, mpl::true_ if the pixel type \a PixelType is supported
|
||||
* by the image format identified with \a FormatTag.
|
||||
* \todo the name is_supported is to generic, pick something more IO realted.
|
||||
*/
|
||||
// Depending on image type the parameter Pixel can be a reference type
|
||||
// for bit_aligned images or a pixel for byte images.
|
||||
template< typename Pixel, typename FormatTag > struct is_read_supported {};
|
||||
template< typename Pixel, typename FormatTag > struct is_write_supported {};
|
||||
|
||||
|
||||
namespace detail {
|
||||
|
||||
template< typename Property >
|
||||
struct property_base
|
||||
{
|
||||
typedef Property type;
|
||||
};
|
||||
|
||||
struct read_support_true { BOOST_STATIC_CONSTANT( bool, is_supported = true ); };
|
||||
struct read_support_false { BOOST_STATIC_CONSTANT( bool, is_supported = false ); };
|
||||
struct write_support_true { BOOST_STATIC_CONSTANT( bool, is_supported = true ); };
|
||||
struct write_support_false{ BOOST_STATIC_CONSTANT( bool, is_supported = false ); };
|
||||
|
||||
class no_log {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template<typename FormatTag> struct image_read_info;
|
||||
template<typename FormatTag> struct image_read_settings;
|
||||
template<typename FormatTag, typename Log = typename detail::no_log > struct image_write_info;
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_BASE_HPP
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_DETAIL_BIT_OPERATIONS_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_BIT_OPERATIONS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
// 1110 1100 -> 0011 0111
|
||||
template< typename Buffer
|
||||
, typename IsBitAligned
|
||||
>
|
||||
struct mirror_bits
|
||||
{
|
||||
mirror_bits( bool ) {}
|
||||
|
||||
void operator() ( Buffer& ) {}
|
||||
};
|
||||
|
||||
|
||||
// The functor will generate a lookup table since the
|
||||
// mirror operation is quite costly.
|
||||
template< typename Buffer >
|
||||
struct mirror_bits< Buffer
|
||||
, mpl::true_
|
||||
>
|
||||
{
|
||||
mirror_bits( bool apply_operation = true )
|
||||
: _apply_operation( apply_operation )
|
||||
{
|
||||
if( _apply_operation == true )
|
||||
{
|
||||
byte_t i = 0;
|
||||
do
|
||||
{
|
||||
_lookup[i] = mirror( i );
|
||||
}
|
||||
while( i++ != 255 );
|
||||
}
|
||||
}
|
||||
|
||||
void operator() ( Buffer& buf )
|
||||
{
|
||||
if( _apply_operation == true )
|
||||
{
|
||||
for_each( buf.begin()
|
||||
, buf.end()
|
||||
, boost::bind( &mirror_bits< Buffer
|
||||
, mpl::true_
|
||||
>::lookup
|
||||
, *this
|
||||
, _1
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void lookup( byte_t& c )
|
||||
{
|
||||
c = _lookup[ c ];
|
||||
}
|
||||
|
||||
static byte_t mirror( byte_t c )
|
||||
{
|
||||
byte_t result = 0;
|
||||
for( int i = 0; i < 8; ++i )
|
||||
{
|
||||
result = result << 1;
|
||||
result |= ( c & 1 );
|
||||
c = c >> 1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
bool _apply_operation;
|
||||
|
||||
array< byte_t, 256 > _lookup;
|
||||
};
|
||||
|
||||
|
||||
// 0011 1111 -> 1100 0000
|
||||
template< typename Buffer
|
||||
, typename IsBitAligned
|
||||
>
|
||||
struct negate_bits
|
||||
{
|
||||
void operator() ( Buffer& ) {}
|
||||
};
|
||||
|
||||
template< typename Buffer >
|
||||
struct negate_bits< Buffer, mpl::true_ >
|
||||
{
|
||||
void operator() ( Buffer& buf )
|
||||
{
|
||||
for_each( buf.begin()
|
||||
, buf.end()
|
||||
, negate_bits< Buffer, mpl::true_ >::negate
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void negate( byte_t& b )
|
||||
{
|
||||
b = ~b;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 11101100 -> 11001110
|
||||
template< typename Buffer
|
||||
, typename IsBitAligned
|
||||
>
|
||||
struct swap_half_bytes
|
||||
{
|
||||
void operator() ( Buffer& ) {}
|
||||
};
|
||||
|
||||
template< typename Buffer >
|
||||
struct swap_half_bytes< Buffer
|
||||
, mpl::true_
|
||||
>
|
||||
{
|
||||
void operator() ( Buffer& buf )
|
||||
{
|
||||
for_each( buf.begin()
|
||||
, buf.end()
|
||||
, swap_half_bytes< Buffer, mpl::true_ >::swap
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void swap( byte_t& c )
|
||||
{
|
||||
c = (( c << 4 ) & 0xF0 ) | (( c >> 4 ) & 0x0F );
|
||||
}
|
||||
};
|
||||
|
||||
template< typename Buffer >
|
||||
struct do_nothing
|
||||
{
|
||||
do_nothing() {}
|
||||
|
||||
void operator() ( Buffer& ) {}
|
||||
};
|
||||
|
||||
/// Count consecutive zeros on the right
|
||||
template< typename T >
|
||||
inline
|
||||
unsigned int trailing_zeros( T x )
|
||||
throw()
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
x = ~x & (x - 1);
|
||||
|
||||
while( x )
|
||||
{
|
||||
n = n + 1;
|
||||
x = x >> 1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
/// Counts ones in a bit-set
|
||||
template< typename T >
|
||||
inline
|
||||
unsigned int count_ones( T x )
|
||||
throw()
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
while( x )
|
||||
{
|
||||
// clear the least significant bit set
|
||||
x &= x - 1;
|
||||
++n;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_BIT_OPERATIONS_HPP
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
Copyright 2007-2008 Andreas Pokorny, Christian Henning
|
||||
Use, modification and distribution are subject to 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_DETAIL_CONVERSION_POLICIES_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_CONVERSION_POLICIES_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Andreas Pokorny, Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <boost/gil/image_view_factory.hpp>
|
||||
|
||||
namespace boost{namespace gil{ namespace detail {
|
||||
|
||||
struct read_and_no_convert
|
||||
{
|
||||
public:
|
||||
typedef void* color_converter_type;
|
||||
|
||||
template< typename InIterator
|
||||
, typename OutIterator
|
||||
>
|
||||
void read( const InIterator& /* begin */
|
||||
, const InIterator& /* end */
|
||||
, OutIterator /* out */
|
||||
, typename disable_if< typename pixels_are_compatible< typename std::iterator_traits<InIterator>::value_type
|
||||
, typename std::iterator_traits<OutIterator>::value_type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
io_error( "Data cannot be copied because the pixels are incompatible." );
|
||||
}
|
||||
|
||||
template< typename InIterator
|
||||
, typename OutIterator
|
||||
>
|
||||
void read( const InIterator& begin
|
||||
, const InIterator& end
|
||||
, OutIterator out
|
||||
, typename enable_if< typename pixels_are_compatible< typename std::iterator_traits<InIterator>::value_type
|
||||
, typename std::iterator_traits<OutIterator>::value_type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
std::copy( begin
|
||||
, end
|
||||
, out
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
template<typename CC>
|
||||
struct read_and_convert
|
||||
{
|
||||
public:
|
||||
typedef CC color_converter_type;
|
||||
CC _cc;
|
||||
|
||||
read_and_convert( color_converter_type const& cc )
|
||||
: _cc(cc) {}
|
||||
|
||||
template< typename InIterator
|
||||
, typename OutIterator
|
||||
>
|
||||
void read( const InIterator& begin
|
||||
, const InIterator& end
|
||||
, OutIterator out
|
||||
)
|
||||
{
|
||||
typedef color_convert_deref_fn< typename std::iterator_traits<InIterator>::reference
|
||||
, typename std::iterator_traits<OutIterator>::value_type //reference?
|
||||
, CC
|
||||
> deref_t;
|
||||
|
||||
std::transform( begin
|
||||
, end
|
||||
, out
|
||||
, deref_t( _cc )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_CONVERSION_POLICIES_HPP
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
|
||||
Use, modification and distribution are subject to 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).
|
||||
|
||||
See http://opensource.adobe.com/gil for most recent version including documentation.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP_INCLUDED
|
||||
#define BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP_INCLUDED
|
||||
|
||||
/// \file
|
||||
/// \brief Generic io functions for dealing with dynamic images
|
||||
//
|
||||
/// \author Hailin Jin and Lubomir Bourdev \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n Last updated May 30, 2006
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/gil/gil_config.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_error.hpp>
|
||||
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// need this for various meta functions.
|
||||
struct any_image_pixel_t {};
|
||||
struct any_image_channel_t {};
|
||||
struct any_image_color_space_t {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <long N>
|
||||
struct construct_matched_t {
|
||||
template <typename Images,typename Pred>
|
||||
static bool apply(any_image<Images>& im,Pred pred) {
|
||||
if (pred.template apply<typename mpl::at_c<Images,N-1>::type>()) {
|
||||
typename mpl::at_c<Images,N-1>::type x;
|
||||
im.move_in(x);
|
||||
return true;
|
||||
} else return construct_matched_t<N-1>::apply(im,pred);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct construct_matched_t<0> {
|
||||
template <typename Images,typename Pred>
|
||||
static bool apply(any_image<Images>&,Pred) {return false;}
|
||||
};
|
||||
|
||||
// A function object that can be passed to apply_operation.
|
||||
// Given a predicate IsSupported taking a view type and returning an MPL boolean,
|
||||
// calls the apply method of OpClass with the view if the given view IsSupported, or throws an exception otherwise
|
||||
template <typename IsSupported, typename OpClass>
|
||||
class dynamic_io_fnobj {
|
||||
OpClass* _op;
|
||||
|
||||
template <typename View>
|
||||
void apply(const View& view,mpl::true_ ) {_op->apply(view);}
|
||||
|
||||
template <typename View, typename Info >
|
||||
void apply( const View& view
|
||||
, const Info& info
|
||||
, const mpl::true_
|
||||
)
|
||||
{
|
||||
_op->apply( view, info );
|
||||
}
|
||||
|
||||
template <typename View>
|
||||
void apply(const View& /* view */ ,mpl::false_) {io_error("dynamic_io: unsupported view type for the given file format");}
|
||||
|
||||
template <typename View, typename Info >
|
||||
void apply( const View& /* view */
|
||||
, const Info& /* info */
|
||||
, const mpl::false_
|
||||
)
|
||||
{
|
||||
io_error( "dynamic_io: unsupported view type for the given file format" );
|
||||
}
|
||||
|
||||
public:
|
||||
dynamic_io_fnobj(OpClass* op) : _op(op) {}
|
||||
|
||||
typedef void result_type;
|
||||
|
||||
template <typename View>
|
||||
void operator()(const View& view) {apply(view,typename IsSupported::template apply<View>::type());}
|
||||
|
||||
template< typename View, typename Info >
|
||||
void operator()(const View& view, const Info& info )
|
||||
{
|
||||
apply( view
|
||||
, info
|
||||
, typename IsSupported::template apply< View >::type()
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Within the any_image, constructs an image with the given dimensions
|
||||
/// and a type that satisfies the given predicate
|
||||
template <typename Images,typename Pred>
|
||||
inline bool construct_matched(any_image<Images>& im,Pred pred) {
|
||||
return detail::construct_matched_t<mpl::size<Images>::value>::apply(im,pred);
|
||||
}
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP_INCLUDED
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny
|
||||
Use, modification and distribution are subject to 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_IO_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_IO_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*!
|
||||
* \page iobackend Adding a new io backend
|
||||
* \section Overview of backend requirements
|
||||
* To add support for a new IO backend the following is required:
|
||||
* - a format tag, to identify the image format, derived from boost::gil::format_tag
|
||||
* - boolean meta function is_supported<PixelType,FormatTag> must be implemented for
|
||||
* the new format tag
|
||||
* - explicit specialisation of image_read_info<FormatTag> must be provided, containing
|
||||
* runtime information available before/at reading the image
|
||||
* - explicit specialisation of image_write_info<FormatTag> must be provided, containing
|
||||
* runtime encoding parameters for writing an image
|
||||
* - An image reader must be specialized:
|
||||
* \code
|
||||
* template<typename IODevice, typename ConversionPolicy>
|
||||
* struct boost::gil::detail::reader<IODevice,FormatTag,ConversionPolicy>
|
||||
* {
|
||||
* reader( IODevice & device )
|
||||
* reader( IODevice & device, typename ConversionPolicy::color_converter_type const& cc )
|
||||
* image_read_info<FormatTag> get_info();
|
||||
* template<typename Image>
|
||||
* void read_image( Image &, point_t const& top_left );
|
||||
* template<typename View>
|
||||
* void read_view( View &, point_t const& top_left );
|
||||
* };
|
||||
* \endcode
|
||||
* - An image writer must be specialized:
|
||||
* \code
|
||||
* \template <typename IODevice>
|
||||
* struct boost::gil::detail::writer<IODevice,FormatTag>
|
||||
* {
|
||||
* writer( IODevice & device )
|
||||
* template<typename View>
|
||||
* void apply( View const&, point_t const& top_left );
|
||||
* template<typename View>
|
||||
* void apply( View const&, point_t const& top_left, image_write_info<FormatTag> const& );
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
* Or instead of the items above implement overloads of read_view, read_and_convert_view, read_image,
|
||||
* read_and_convert_image, write_view and read_image_info.
|
||||
*
|
||||
* \section ConversionPolicy Interface of the ConversionPolicy
|
||||
* There are two different conversion policies in use, when reading images:
|
||||
* read_and_convert<ColorConverter> and read_and_no_convert. ColorConverter
|
||||
* can be a user defined color converter.
|
||||
*
|
||||
* \code
|
||||
* struct ConversionPolicy
|
||||
* {
|
||||
* template<typename InputIterator,typename OutputIterator>
|
||||
* void read( InputIterator in_begin, InputIterator in_end,
|
||||
* OutputIterator out_end );
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
* Methods like read_view and read_image are supposed to bail out with an
|
||||
* exception instead of converting the image
|
||||
*
|
||||
* \section IODevice Concept of IO Device
|
||||
* A Device is simply an object used to read and write data to and from a stream.
|
||||
* The IODevice was added as a template paramter to be able to replace the file_name
|
||||
* access functionality. This is only an interim solution, as soon as boost provides
|
||||
* a good IO library, interfaces/constraints provided by that library could be used.
|
||||
*
|
||||
* \code
|
||||
* concept IODevice
|
||||
* {
|
||||
* void IODevice::read( unsigned char* data, int count );
|
||||
* void IODevice::write( unsigned char* data, int count );
|
||||
* void IODevice::seek(long count, int whence);
|
||||
* void IODevice::flush();
|
||||
* };
|
||||
* \endcode
|
||||
*
|
||||
* For the time being a boolean meta function must be specialized:
|
||||
* \code
|
||||
* namespace boost{namespace gil{namespace detail{
|
||||
* template<typename Device>
|
||||
* struct detail::is_input_device;
|
||||
* }}}
|
||||
* \endcode
|
||||
*
|
||||
*/
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_IO_HPP
|
||||
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
Copyright 2007-2008 Andreas Pokorny, Christian Henning
|
||||
Use, modification and distribution are subject to 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_DETAIL_IO_DEVICE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_IO_DEVICE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Andreas Pokorny, Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
#include "base.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template < typename T > struct buff_item
|
||||
{
|
||||
static const unsigned int size = sizeof( T );
|
||||
};
|
||||
|
||||
template <> struct buff_item< void >
|
||||
{
|
||||
static const unsigned int size = 1;
|
||||
};
|
||||
|
||||
|
||||
/*!
|
||||
* Implements the IODevice concept c.f. to \ref IODevice required by Image libraries like
|
||||
* libjpeg and libpng.
|
||||
*
|
||||
* \todo switch to a sane interface as soon as there is
|
||||
* something good in boost. I.E. the IOChains library
|
||||
* would fit very well here.
|
||||
*
|
||||
* This implementation is based on FILE*.
|
||||
*/
|
||||
template< typename FormatTag >
|
||||
class file_stream_device
|
||||
{
|
||||
public:
|
||||
|
||||
typedef FormatTag _tag_t;
|
||||
|
||||
public:
|
||||
struct read_tag {};
|
||||
struct write_tag {};
|
||||
|
||||
file_stream_device( std::string const& file_name, read_tag )
|
||||
: file(0),_close(true)
|
||||
{
|
||||
io_error_if( ( file = fopen( file_name.c_str(), "rb" )) == NULL
|
||||
, "file_stream_device: failed to open file" );
|
||||
}
|
||||
|
||||
file_stream_device( std::string const& file_name, write_tag )
|
||||
: file(0),_close(true)
|
||||
{
|
||||
io_error_if( ( file = fopen( file_name.c_str(), "wb" )) == NULL
|
||||
, "file_stream_device: failed to open file" );
|
||||
}
|
||||
|
||||
file_stream_device( FILE * filep)
|
||||
: file(filep),_close(false)
|
||||
{
|
||||
}
|
||||
|
||||
~file_stream_device()
|
||||
{
|
||||
if(_close)
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
int getc_unchecked()
|
||||
{
|
||||
return std::getc( file );
|
||||
}
|
||||
|
||||
char getc()
|
||||
{
|
||||
int ch;
|
||||
|
||||
if(( ch = std::getc( file )) == EOF )
|
||||
io_error( "file_stream_device: unexpected EOF" );
|
||||
|
||||
return ( char ) ch;
|
||||
}
|
||||
|
||||
std::size_t read( byte_t* data
|
||||
, std::size_t count )
|
||||
{
|
||||
return fread( data, 1, static_cast<int>( count ), file );
|
||||
}
|
||||
|
||||
/// Reads array
|
||||
template< typename T
|
||||
, int N
|
||||
>
|
||||
size_t read( T (&buf)[N] )
|
||||
{
|
||||
return read( buf, N );
|
||||
}
|
||||
|
||||
/// Reads byte
|
||||
uint8_t read_int8() throw()
|
||||
{
|
||||
byte_t m[1];
|
||||
|
||||
read( m );
|
||||
return m[0];
|
||||
}
|
||||
|
||||
/// Reads 16 bit little endian integer
|
||||
uint16_t read_int16() throw()
|
||||
{
|
||||
byte_t m[2];
|
||||
|
||||
read( m );
|
||||
return (m[1] << 8) | m[0];
|
||||
}
|
||||
|
||||
/// Reads 32 bit little endian integer
|
||||
uint32_t read_int32() throw()
|
||||
{
|
||||
byte_t m[4];
|
||||
|
||||
read( m );
|
||||
return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
|
||||
}
|
||||
|
||||
/// Writes number of elements from a buffer
|
||||
template < typename T >
|
||||
size_t write(const T *buf, size_t cnt) throw()
|
||||
{
|
||||
return fwrite( buf, buff_item<T>::size, cnt, file );
|
||||
}
|
||||
|
||||
/// Writes array
|
||||
template < typename T
|
||||
, size_t N
|
||||
>
|
||||
size_t write( const T (&buf)[N] ) throw()
|
||||
{
|
||||
return write( buf, N );
|
||||
}
|
||||
|
||||
/// Writes byte
|
||||
void write_int8( uint8_t x ) throw()
|
||||
{
|
||||
byte_t m[1] = { x };
|
||||
write(m);
|
||||
}
|
||||
|
||||
/// Writes 16 bit little endian integer
|
||||
void write_int16( uint16_t x ) throw()
|
||||
{
|
||||
byte_t m[2];
|
||||
|
||||
m[0] = byte_t( x >> 0 );
|
||||
m[1] = byte_t( x >> 8 );
|
||||
|
||||
write( m );
|
||||
}
|
||||
|
||||
/// Writes 32 bit little endian integer
|
||||
void write_int32( uint32_t x ) throw()
|
||||
{
|
||||
byte_t m[4];
|
||||
|
||||
m[0] = byte_t( x >> 0 );
|
||||
m[1] = byte_t( x >> 8 );
|
||||
m[2] = byte_t( x >> 16 );
|
||||
m[3] = byte_t( x >> 24 );
|
||||
|
||||
write( m );
|
||||
}
|
||||
|
||||
|
||||
//!\todo replace with std::ios::seekdir?
|
||||
void seek( long count, int whence = SEEK_SET )
|
||||
{
|
||||
fseek(file, count, whence );
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
fflush( file );
|
||||
}
|
||||
|
||||
/// Prints formatted ASCII text
|
||||
void print_line( const std::string& line )
|
||||
{
|
||||
fwrite( line.c_str(), sizeof( char ), line.size(), file );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
file_stream_device( file_stream_device const& );
|
||||
file_stream_device& operator=( file_stream_device const& );
|
||||
|
||||
//@todo: why not fstream?
|
||||
FILE* file;
|
||||
|
||||
bool _close;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Input stream device
|
||||
*/
|
||||
template< typename FormatTag >
|
||||
class istream_device
|
||||
{
|
||||
public:
|
||||
istream_device( std::istream& in )
|
||||
: _in( in ) {}
|
||||
|
||||
int getc_unchecked()
|
||||
{
|
||||
return _in.get();
|
||||
}
|
||||
|
||||
char getc()
|
||||
{
|
||||
int ch;
|
||||
|
||||
if(( ch = _in.get() ) == EOF )
|
||||
io_error( "file_stream_device: unexpected EOF" );
|
||||
|
||||
return ( char ) ch;
|
||||
}
|
||||
|
||||
std::size_t read( byte_t* data
|
||||
, std::size_t count )
|
||||
{
|
||||
std::streamsize cr = 0;
|
||||
|
||||
do
|
||||
{
|
||||
_in.peek();
|
||||
std::streamsize c = _in.readsome( reinterpret_cast< char* >( data )
|
||||
, static_cast< std::streamsize >( count ));
|
||||
|
||||
count -= static_cast< std::size_t >( c );
|
||||
data += c;
|
||||
cr += c;
|
||||
|
||||
} while( count && _in );
|
||||
|
||||
return static_cast< std::size_t >( cr );
|
||||
}
|
||||
|
||||
/// Reads array
|
||||
template< typename T
|
||||
, int N
|
||||
>
|
||||
size_t read( T (&buf)[N] )
|
||||
{
|
||||
return read( buf, N );
|
||||
}
|
||||
|
||||
/// Reads byte
|
||||
uint8_t read_int8() throw()
|
||||
{
|
||||
byte_t m[1];
|
||||
|
||||
read( m );
|
||||
return m[0];
|
||||
}
|
||||
|
||||
/// Reads 16 bit little endian integer
|
||||
uint16_t read_int16() throw()
|
||||
{
|
||||
byte_t m[2];
|
||||
|
||||
read( m );
|
||||
return (m[1] << 8) | m[0];
|
||||
}
|
||||
|
||||
/// Reads 32 bit little endian integer
|
||||
uint32_t read_int32() throw()
|
||||
{
|
||||
byte_t m[4];
|
||||
|
||||
read( m );
|
||||
return (m[3] << 24) | (m[2] << 16) | (m[1] << 8) | m[0];
|
||||
}
|
||||
|
||||
void seek( long count, int whence = SEEK_SET )
|
||||
{
|
||||
_in.seekg( count
|
||||
, whence == SEEK_SET ? std::ios::beg
|
||||
:( whence == SEEK_CUR ? std::ios::cur
|
||||
: std::ios::end )
|
||||
);
|
||||
}
|
||||
|
||||
void write( const byte_t* data
|
||||
, std::size_t count )
|
||||
{
|
||||
io_error( "Bad io error." );
|
||||
}
|
||||
|
||||
void flush() {}
|
||||
|
||||
private:
|
||||
|
||||
std::istream& _in;
|
||||
};
|
||||
|
||||
/**
|
||||
* Output stream device
|
||||
*/
|
||||
template< typename FormatTag >
|
||||
class ostream_device
|
||||
{
|
||||
public:
|
||||
ostream_device( std::ostream & out )
|
||||
: _out( out )
|
||||
{
|
||||
}
|
||||
|
||||
size_t read( byte_t* data
|
||||
, std::size_t count )
|
||||
{
|
||||
io_error( "Bad io error." );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void seek( long count, int whence )
|
||||
{
|
||||
_out.seekp( count
|
||||
, whence == SEEK_SET
|
||||
? std::ios::beg
|
||||
: ( whence == SEEK_CUR
|
||||
?std::ios::cur
|
||||
:std::ios::end )
|
||||
);
|
||||
}
|
||||
|
||||
void write( const byte_t* data
|
||||
, std::size_t count )
|
||||
{
|
||||
_out.write( reinterpret_cast<char const*>( data )
|
||||
, static_cast<std::streamsize>( count )
|
||||
);
|
||||
}
|
||||
|
||||
/// Writes array
|
||||
template < typename T
|
||||
, size_t N
|
||||
>
|
||||
void write( const T (&buf)[N] ) throw()
|
||||
{
|
||||
write( buf, N );
|
||||
}
|
||||
|
||||
/// Writes byte
|
||||
void write_int8( uint8_t x ) throw()
|
||||
{
|
||||
byte_t m[1] = { x };
|
||||
write(m);
|
||||
}
|
||||
|
||||
/// Writes 16 bit little endian integer
|
||||
void write_int16( uint16_t x ) throw()
|
||||
{
|
||||
byte_t m[2];
|
||||
|
||||
m[0] = byte_t( x >> 0 );
|
||||
m[1] = byte_t( x >> 8 );
|
||||
|
||||
write( m );
|
||||
}
|
||||
|
||||
/// Writes 32 bit little endian integer
|
||||
void write_int32( uint32_t x ) throw()
|
||||
{
|
||||
byte_t m[4];
|
||||
|
||||
m[0] = byte_t( x >> 0 );
|
||||
m[1] = byte_t( x >> 8 );
|
||||
m[2] = byte_t( x >> 16 );
|
||||
m[3] = byte_t( x >> 24 );
|
||||
|
||||
write( m );
|
||||
}
|
||||
|
||||
void flush()
|
||||
{
|
||||
_out << std::flush;
|
||||
}
|
||||
|
||||
/// Prints formatted ASCII text
|
||||
void print_line( const std::string& line )
|
||||
{
|
||||
_out << line;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
|
||||
std::ostream& _out;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Metafunction to detect input devices.
|
||||
* Should be replaced by an external facility in the future.
|
||||
*/
|
||||
template< typename IODevice > struct is_input_device : mpl::false_{};
|
||||
template< typename FormatTag > struct is_input_device< file_stream_device< FormatTag > > : mpl::true_{};
|
||||
template< typename FormatTag > struct is_input_device< istream_device< FormatTag > > : mpl::true_{};
|
||||
|
||||
template< typename FormatTag
|
||||
, typename T
|
||||
, typename D = void
|
||||
>
|
||||
struct is_adaptable_input_device : mpl::false_{};
|
||||
|
||||
template< typename FormatTag
|
||||
, typename T
|
||||
>
|
||||
struct is_adaptable_input_device< FormatTag
|
||||
, T
|
||||
, typename enable_if< mpl::or_< is_base_and_derived< std::istream, T >
|
||||
, is_same < std::istream, T >
|
||||
>
|
||||
>::type
|
||||
> : mpl::true_
|
||||
{
|
||||
typedef istream_device< FormatTag > device_type;
|
||||
};
|
||||
|
||||
template< typename FormatTag >
|
||||
struct is_adaptable_input_device< FormatTag
|
||||
, FILE*
|
||||
, void
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
typedef file_stream_device< FormatTag > device_type;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Metafunction to detect output devices.
|
||||
* Should be replaced by an external facility in the future.
|
||||
*/
|
||||
template<typename IODevice> struct is_output_device : mpl::false_{};
|
||||
|
||||
template< typename FormatTag > struct is_output_device< file_stream_device< FormatTag > > : mpl::true_{};
|
||||
template< typename FormatTag > struct is_output_device< ostream_device < FormatTag > > : mpl::true_{};
|
||||
|
||||
template< typename FormatTag
|
||||
, typename IODevice
|
||||
, typename D = void
|
||||
>
|
||||
struct is_adaptable_output_device : mpl::false_ {};
|
||||
|
||||
template< typename FormatTag
|
||||
, typename T
|
||||
> struct is_adaptable_output_device< FormatTag
|
||||
, T
|
||||
, typename enable_if< mpl::or_< is_base_and_derived< std::ostream, T >
|
||||
, is_same < std::ostream, T >
|
||||
>
|
||||
>::type
|
||||
> : mpl::true_
|
||||
{
|
||||
typedef ostream_device< FormatTag > device_type;
|
||||
};
|
||||
|
||||
template<typename FormatTag> struct is_adaptable_output_device<FormatTag,FILE*,void>
|
||||
: mpl::true_
|
||||
{
|
||||
typedef file_stream_device< FormatTag > device_type;
|
||||
};
|
||||
|
||||
template< typename Device, typename FormatTag, typename ConversionPolicy > class reader;
|
||||
template< typename Device, typename FormatTag, typename Log = no_log > class writer;
|
||||
|
||||
template< typename Device, typename FormatTag > class dynamic_image_reader;
|
||||
template< typename Device, typename FormatTag, typename Log = no_log > class dynamic_image_writer;
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_IO_DEVICE_HPP
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_DETAIL_IO_ERROR_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_IO_ERROR_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2010 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
inline
|
||||
void io_error( const std::string& descr )
|
||||
{
|
||||
throw std::ios_base::failure( descr );
|
||||
}
|
||||
|
||||
inline
|
||||
void io_error_if( bool expr, const std::string& descr )
|
||||
{
|
||||
if( expr )
|
||||
io_error( descr );
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_IO_ERROR_HPP
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
Copyright 2007-2008 Andreas Pokorny, Christian Henning
|
||||
Use, modification and distribution are subject to 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_DETAIL_PATH_SPEC_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_PATH_SPEC_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Andreas Pokorny, Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cstdlib>
|
||||
#include <malloc.h>
|
||||
|
||||
#ifdef BOOST_GIL_IO_ADD_FS_PATH_SUPPORT
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#endif // BOOST_GIL_IO_ADD_FS_PATH_SUPPORT
|
||||
namespace boost{ namespace gil{ namespace detail{
|
||||
|
||||
template<typename P> struct is_supported_path_spec : mpl::false_ {};
|
||||
template<> struct is_supported_path_spec< std::string > : mpl::true_ {};
|
||||
template<> struct is_supported_path_spec< std::wstring > : mpl::true_ {};
|
||||
template<> struct is_supported_path_spec< const char* > : mpl::true_ {};
|
||||
template<> struct is_supported_path_spec< char* > : mpl::true_ {};
|
||||
|
||||
template<int i> struct is_supported_path_spec<const char [i]> : mpl::true_ {};
|
||||
template<int i> struct is_supported_path_spec<char [i]> : mpl::true_ {};
|
||||
|
||||
#ifdef BOOST_GIL_IO_ADD_FS_PATH_SUPPORT
|
||||
template<typename String, typename Traits>
|
||||
struct is_supported_path_spec<filesystem::basic_path<String,Traits> > : mpl::true_
|
||||
{};
|
||||
#endif // BOOST_GIL_IO_ADD_FS_PATH_SUPPORT
|
||||
|
||||
inline std::string convert_to_string( std::string const& obj)
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
inline std::string convert_to_string( std::wstring const& s )
|
||||
{
|
||||
std::size_t len = wcslen( s.c_str() );
|
||||
char* c = reinterpret_cast<char*>( alloca( len ));
|
||||
wcstombs( c, s.c_str(), len );
|
||||
|
||||
return std::string( c, c + len );
|
||||
}
|
||||
|
||||
inline std::string convert_to_string( const char* str )
|
||||
{
|
||||
return std::string( str );
|
||||
}
|
||||
|
||||
inline std::string convert_to_string( char* str )
|
||||
{
|
||||
return std::string( str );
|
||||
}
|
||||
|
||||
#ifdef BOOST_GIL_IO_ADD_FS_PATH_SUPPORT
|
||||
template<typename String, typename T>
|
||||
inline std::string convert_to_string( filesystem::basic_path<String,T> const& path )
|
||||
{
|
||||
return convert_to_string( path.string() );
|
||||
}
|
||||
#endif // BOOST_GIL_IO_ADD_FS_PATH_SUPPORT
|
||||
|
||||
}}}
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_PATH_SPEC_HPP
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_READ_AND_CONVERT_IMAGE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_READ_AND_CONVERT_IMAGE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "io_device.hpp"
|
||||
#include "path_spec.hpp"
|
||||
#include "conversion_policies.hpp"
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// \ingroup IO
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \param cc Color converter function object.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename Image
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( Device& file
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, const ColorConverter& cc
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_input_device< Device >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef detail::read_and_convert< ColorConverter > reader_color_convert;
|
||||
|
||||
detail::reader< Device
|
||||
, FormatTag
|
||||
, reader_color_convert
|
||||
> reader( file
|
||||
, cc
|
||||
, settings
|
||||
);
|
||||
|
||||
reader.init_image( img
|
||||
, reader.get_info()
|
||||
);
|
||||
|
||||
reader.apply( view( img ));
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \param cc Color converter function object.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename Image
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( Device& file
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, const ColorConverter& cc
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
device_type dev( file );
|
||||
|
||||
read_and_convert_image( dev
|
||||
, img
|
||||
, settings
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \param cc Color converter function object.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Image
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( const String& file_name
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, const ColorConverter& cc
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::read_tag()
|
||||
);
|
||||
|
||||
read_and_convert_image( device
|
||||
, img
|
||||
, settings
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param cc Color converter function object.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Image
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( const String& file_name
|
||||
, Image& img
|
||||
, const ColorConverter& cc
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_image( file_name
|
||||
, img
|
||||
, image_read_settings< FormatTag >()
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction or is_adaptable_input_device.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param cc Color converter function object.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Image
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( Device& device
|
||||
, Image& img
|
||||
, const ColorConverter& cc
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< mpl::or_< detail::is_input_device< Device >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_image( device
|
||||
, img
|
||||
, image_read_settings< FormatTag >()
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated. Default color converter is used.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( const String& file_name
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_image( file_name
|
||||
, img
|
||||
, settings
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated. Default color converter is used.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction or is_adaptable_input_device.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( Device& device
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< mpl::or_< detail::is_input_device< Device >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_image( device
|
||||
, img
|
||||
, settings
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated. Default color converter is used.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( const String& file_name
|
||||
, Image& img
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_image( file_name
|
||||
, img
|
||||
, image_read_settings< FormatTag >()
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image. Image memory is allocated. Default color converter is used.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param img The image in which the data is read into.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_image( Device& device
|
||||
, Image& img
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< mpl::or_< detail::is_input_device< Device >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_image( device
|
||||
, img
|
||||
, image_read_settings< FormatTag >()
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_READ_AND_CONVERT_IMAGE_HPP
|
||||
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_READ_AND_CONVERT_VIEW_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_READ_AND_CONVERT_VIEW_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "io_device.hpp"
|
||||
#include "path_spec.hpp"
|
||||
#include "conversion_policies.hpp"
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// \ingroup IO
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \param cc Color converter function object.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename View
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( Device& file
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, const ColorConverter& cc
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_input_device< Device >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef detail::read_and_convert< ColorConverter > reader_color_convert;
|
||||
|
||||
detail::reader< Device
|
||||
, FormatTag
|
||||
, reader_color_convert
|
||||
> reader( file
|
||||
, cc
|
||||
, settings
|
||||
);
|
||||
|
||||
reader.init_view( view
|
||||
, reader.get_info()
|
||||
);
|
||||
|
||||
reader.apply( view );
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \param cc Color converter function object.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename View
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( Device& file
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, const ColorConverter& cc
|
||||
, typename enable_if< mpl::and_< detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
|
||||
device_type dev( file );
|
||||
|
||||
read_and_convert_view( dev
|
||||
, view
|
||||
, settings
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \param cc Color converter function object.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename View
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( const String& file_name
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, const ColorConverter& cc
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::read_tag()
|
||||
);
|
||||
|
||||
read_and_convert_view( device
|
||||
, view
|
||||
, settings
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param cc Color converter function object.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename View
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( const String& file_name
|
||||
, const View& view
|
||||
, const ColorConverter& cc
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_view( file_name
|
||||
, view
|
||||
, image_read_settings< FormatTag >()
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction or is_adaptable_input_device.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param cc Color converter function object.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename View
|
||||
, typename ColorConverter
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( Device& device
|
||||
, const View& view
|
||||
, const ColorConverter& cc
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< mpl::or_< detail::is_input_device< Device >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_view( device
|
||||
, view
|
||||
, image_read_settings< FormatTag >()
|
||||
, cc
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( const String& file_name
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_view( file_name
|
||||
, view
|
||||
, settings
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction or is_adaptable_input_device.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( Device& device
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< mpl::or_< detail::is_input_device< Device >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_view( device
|
||||
, view
|
||||
, settings
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( const String& file_name
|
||||
, const View& view
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_view( file_name
|
||||
, view
|
||||
, image_read_settings< FormatTag >()
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads and color-converts an image view. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction or is_adaptable_input_device.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_and_convert_view( Device& device
|
||||
, const View& view
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< mpl::or_< detail::is_input_device< Device >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_and_convert_view( device
|
||||
, view
|
||||
, image_read_settings< FormatTag >()
|
||||
, default_color_converter()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_READ_AND_CONVERT_VIEW_HPP
|
||||
@@ -0,0 +1,437 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_READ_IMAGE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_READ_IMAGE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <boost/gil/extension/toolbox/dynamic_images.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "io_device.hpp"
|
||||
#include "path_spec.hpp"
|
||||
#include "conversion_policies.hpp"
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// \ingroup IO
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param img The image in which the data is read into. Must satisfy is_read_supported metafunction.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< detail::is_input_device< Device >
|
||||
, is_format_tag < FormatTag >
|
||||
, is_read_supported < typename get_pixel_type< typename Image::view_t >::type
|
||||
, FormatTag
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::reader< Device
|
||||
, FormatTag
|
||||
, detail::read_and_no_convert
|
||||
> reader( file
|
||||
, settings
|
||||
);
|
||||
|
||||
reader.init_image( img
|
||||
, reader.get_info()
|
||||
);
|
||||
|
||||
reader.apply( view( img ));
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param img The image in which the data is read into. Must satisfy is_read_supported metafunction.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
, is_read_supported< typename get_pixel_type< typename Image::view_t >::type
|
||||
, FormatTag
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
|
||||
device_type dev(file);
|
||||
detail::reader< device_type
|
||||
, FormatTag
|
||||
, detail::read_and_no_convert
|
||||
> reader( dev
|
||||
, settings
|
||||
);
|
||||
|
||||
reader.init_image( img
|
||||
, reader.get_info()
|
||||
);
|
||||
|
||||
reader.apply( view( img ));
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param img The image in which the data is read into. Must satisfy is_read_supported metafunction.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( const String& file_name
|
||||
, Image& img
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< detail::is_supported_path_spec< String >
|
||||
, is_format_tag< FormatTag >
|
||||
, is_read_supported< typename get_pixel_type< typename Image::view_t >::type
|
||||
, FormatTag
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::file_stream_device<FormatTag>::read_tag read_tag;
|
||||
|
||||
detail::file_stream_device<FormatTag> device( detail::convert_to_string( file_name )
|
||||
, read_tag()
|
||||
);
|
||||
|
||||
read_image( device
|
||||
, img
|
||||
, settings
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param img The image in which the data is read into. Must satisfy is_read_supported metafunction.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, Image& img
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< detail::is_input_device< Device >
|
||||
, is_format_tag < FormatTag >
|
||||
, is_read_supported < typename get_pixel_type< typename Image::view_t >::type
|
||||
, FormatTag
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_image( file
|
||||
, img
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param img The image in which the data is read into. Must satisfy is_read_supported metafunction.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, Image& img
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
, is_read_supported< typename get_pixel_type< typename Image::view_t >::type
|
||||
, FormatTag
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag, Device >::device_type device_type;
|
||||
device_type dev( file );
|
||||
|
||||
read_image( dev
|
||||
, img
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param img The image in which the data is read into. Must satisfy is_read_supported metafunction.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Image
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( const String& file_name
|
||||
, Image& img
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< detail::is_supported_path_spec< String >
|
||||
, is_format_tag< FormatTag >
|
||||
, is_read_supported< typename get_pixel_type< typename Image::view_t >::type
|
||||
, FormatTag
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::read_tag()
|
||||
);
|
||||
|
||||
read_image( device
|
||||
, img
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
///////////////////////////// dynamic images
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param images Dynamic image ( mpl::vector ). See boost::gil::dynamic_image extension.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
template < typename Device
|
||||
, typename Images
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, any_image< Images >& images
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< detail::is_input_device< Device >
|
||||
, is_format_tag < FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::dynamic_image_reader< Device
|
||||
, FormatTag
|
||||
> dyn_reader( file
|
||||
, settings
|
||||
);
|
||||
|
||||
dyn_reader.init_image( images
|
||||
, dyn_reader.get_info()
|
||||
);
|
||||
|
||||
dyn_reader.apply( images );
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param images Dynamic image ( mpl::vector ). See boost::gil::dynamic_image extension.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
|
||||
template < typename Device
|
||||
, typename Images
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, any_image< Images >& images
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
device_type dev( file );
|
||||
|
||||
detail::reader< device_type
|
||||
, FormatTag
|
||||
, detail::read_and_no_convert
|
||||
> reader( dev
|
||||
, settings
|
||||
);
|
||||
|
||||
reader.init_image( images
|
||||
, reader.get_info
|
||||
);
|
||||
|
||||
reader.apply( view( images ));
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param images Dynamic image ( mpl::vector ). See boost::gil::dynamic_image extension.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Images
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( const String& file_name
|
||||
, any_image< Images >& images
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< detail::is_supported_path_spec< String >
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::file_stream_device< FormatTag >::read_tag read_tag;
|
||||
|
||||
detail::file_stream_device<FormatTag> device( detail::convert_to_string( file_name )
|
||||
, read_tag()
|
||||
);
|
||||
|
||||
read_image( device
|
||||
, images
|
||||
, settings
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param images Dynamic image ( mpl::vector ). See boost::gil::dynamic_image extension.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Images
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, any_image< Images >& images
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< detail::is_input_device< Device >
|
||||
, is_format_tag < FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_image( file
|
||||
, images
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param images Dynamic image ( mpl::vector ). See boost::gil::dynamic_image extension.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename Images
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( Device& file
|
||||
, any_image< Images >& images
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
device_type dev( file );
|
||||
|
||||
read_image( dev
|
||||
, images
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image without conversion. Image memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param images Dynamic image ( mpl::vector ). See boost::gil::dynamic_image extension.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename Images
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_image( const String& file_name
|
||||
, any_image< Images >& images
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< detail::is_supported_path_spec< String >
|
||||
, is_format_tag< FormatTag >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::read_tag()
|
||||
);
|
||||
|
||||
read_image( device
|
||||
, images
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_READ_IMAGE_HPP
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_IMAGE_READ_INFO_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_IMAGE_READ_INFO_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "io_device.hpp"
|
||||
#include "path_spec.hpp"
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// \ingroup IO
|
||||
|
||||
/// \brief Returns the image info. Image info is file format specific.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \return image_read_info object dependent on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
image_read_info< FormatTag >
|
||||
read_image_info( Device& file
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_input_device< Device >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
return detail::reader< Device
|
||||
, FormatTag
|
||||
, detail::read_and_no_convert
|
||||
>( file
|
||||
, settings
|
||||
).get_info();
|
||||
}
|
||||
|
||||
/// \brief Returns the image info. Image info is file format specific.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \return image_read_info object dependent on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
image_read_info< FormatTag >
|
||||
read_image_info( Device& file
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_input_device< Device >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
return read_image_info( file
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// \brief Returns the image info. Image info is file format specific.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \return image_read_info object dependent on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
image_read_info<FormatTag>
|
||||
read_image_info( Device& file
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
|
||||
device_type dev( file );
|
||||
|
||||
return detail::reader< device_type
|
||||
, FormatTag
|
||||
, detail::read_and_no_convert
|
||||
>( dev
|
||||
, settings
|
||||
).get_info();
|
||||
}
|
||||
|
||||
/// \brief Returns the image info. Image info is file format specific.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \return image_read_info object dependent on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
image_read_info< FormatTag >
|
||||
read_image_info( Device& file
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
|
||||
device_type dev( file );
|
||||
|
||||
return read_image_info( dev
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Returns the image info. Image info is file format specific.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \return image_read_info object dependent on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename String
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
image_read_info< FormatTag >
|
||||
read_image_info( const String& file_name
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > reader( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::read_tag()
|
||||
);
|
||||
|
||||
return read_image_info( reader
|
||||
, settings
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Returns the image info. Image info is file format specific.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \return image_read_info object dependent on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename String
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
image_read_info< FormatTag >
|
||||
read_image_info( const String& file_name
|
||||
, const FormatTag&
|
||||
, typename enable_if< mpl::and_< is_format_tag< FormatTag >
|
||||
, detail::is_supported_path_spec< String >
|
||||
>
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > reader( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::read_tag()
|
||||
);
|
||||
|
||||
return read_image_info( reader
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_IMAGE_READ_INFO_HPP
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_READ_VIEW_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_READ_VIEW_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "io_device.hpp"
|
||||
#include "path_spec.hpp"
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// \ingroup IO
|
||||
|
||||
/// \brief Reads an image view without conversion. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_view( Device& file
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_input_device< Device >::type
|
||||
, typename is_format_tag < FormatTag >::type
|
||||
, typename is_read_supported < typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::reader< Device
|
||||
, FormatTag
|
||||
, detail::read_and_no_convert
|
||||
> reader( file
|
||||
, settings
|
||||
);
|
||||
|
||||
reader.init_view( view
|
||||
, reader.get_info()
|
||||
);
|
||||
|
||||
reader.apply( view );
|
||||
}
|
||||
|
||||
/// \brief Reads an image view without conversion. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_adaptable_input_device metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_view( Device& file
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::type
|
||||
, typename is_format_tag<FormatTag>::type
|
||||
, typename is_read_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::device_type device_type;
|
||||
|
||||
device_type dev( file );
|
||||
|
||||
detail::reader< device_type
|
||||
, FormatTag
|
||||
, detail::read_and_no_convert
|
||||
> reader( dev
|
||||
, settings
|
||||
);
|
||||
|
||||
reader.init_view( view
|
||||
, reader.get_info()
|
||||
);
|
||||
|
||||
reader.apply( view );
|
||||
}
|
||||
|
||||
/// \brief Reads an image view without conversion. No memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param settings Specifies read settings depending on the image format.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_view( const String& file_name
|
||||
, const View& view
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_supported_path_spec< String >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_read_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device<FormatTag> device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::read_tag()
|
||||
);
|
||||
|
||||
read_view( device
|
||||
, view
|
||||
, settings
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image view without conversion. No memory is allocated.
|
||||
/// \param file_name File name. Must satisfy is_supported_path_spec metafunction.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template < typename String
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_view( const String& file_name
|
||||
, const View& view
|
||||
, const FormatTag&
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_supported_path_spec< String >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_read_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_view( file_name
|
||||
, view
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
/// \brief Reads an image view without conversion. No memory is allocated.
|
||||
/// \param file It's a device. Must satisfy is_input_device metafunction or is_adaptable_input_device.
|
||||
/// \param view The image view in which the data is read into.
|
||||
/// \param tag Defines the image format. Must satisfy is_format_tag metafunction.
|
||||
/// \throw std::ios_base::failure
|
||||
template< typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void read_view( Device& device
|
||||
, const View& view
|
||||
, const FormatTag&
|
||||
, typename enable_if< typename mpl::and_< typename is_format_tag< FormatTag >::type
|
||||
, typename mpl::or_< typename detail::is_input_device< Device >::type
|
||||
, typename detail::is_adaptable_input_device< FormatTag
|
||||
, Device
|
||||
>::type
|
||||
>::type
|
||||
, typename is_read_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
read_view( device
|
||||
, view
|
||||
, image_read_settings< FormatTag >()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_READ_VIEW_HPP
|
||||
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_DETAIL_READER_BASE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_READER_BASE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "base.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
/// Reader Base Class
|
||||
///
|
||||
/// It provides some basic functionality which is shared for all readers.
|
||||
/// For instance, it recreates images when necessary. It checks whether
|
||||
/// user supplied coordinates are valid.
|
||||
///
|
||||
/// @tparam FormatTag A format tag, like jpeg_tag.
|
||||
/// @tparam ConversionPolicy Conversion policy, see coversion_policies.hpp.
|
||||
template< typename FormatTag
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
struct reader_base
|
||||
{
|
||||
public:
|
||||
|
||||
/// Initializes an image. But also does some check ups.
|
||||
///
|
||||
/// @tparam Image Image which implements boost::gil's ImageConcept.
|
||||
///
|
||||
/// @param img The image.
|
||||
/// @param info The image read info.
|
||||
template< typename Image >
|
||||
void init_image( Image& img
|
||||
, const image_read_info< FormatTag >& info
|
||||
)
|
||||
{
|
||||
_info = info;
|
||||
|
||||
setup( _settings._dim );
|
||||
|
||||
img.recreate( _settings._dim.x
|
||||
, _settings._dim.y
|
||||
);
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void init_view( const View& view
|
||||
, const image_read_info< FormatTag >& info
|
||||
)
|
||||
{
|
||||
_info = info;
|
||||
|
||||
setup( view.dimensions() );
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
reader_base( const image_read_settings< FormatTag >& settings )
|
||||
: _settings( settings )
|
||||
{}
|
||||
reader_base( const typename ConversionPolicy::color_converter_type& cc
|
||||
, const image_read_settings< FormatTag >& settings
|
||||
)
|
||||
: _settings( settings )
|
||||
, _cc_policy( cc )
|
||||
{}
|
||||
|
||||
private:
|
||||
|
||||
void setup( const point_t& dim )
|
||||
{
|
||||
check_coordinates( dim );
|
||||
|
||||
if( dim == point_t( 0, 0 ))
|
||||
{
|
||||
_settings._dim.x = _info._width;
|
||||
_settings._dim.y = _info._height;
|
||||
}
|
||||
else
|
||||
{
|
||||
_settings._dim = dim;
|
||||
}
|
||||
}
|
||||
|
||||
void check_coordinates( const point_t& dim )
|
||||
{
|
||||
typedef point_t::value_type int_t;
|
||||
|
||||
int_t width = static_cast< int_t >( _info._width );
|
||||
int_t height = static_cast< int_t >( _info._height );
|
||||
|
||||
io_error_if( ( _settings._top_left.x < 0
|
||||
|| _settings._top_left.y < 0
|
||||
|| dim.x < 0
|
||||
|| dim.y < 0
|
||||
)
|
||||
, "User provided view has incorrect size." );
|
||||
|
||||
|
||||
io_error_if( ( ( width ) < _settings._top_left.x
|
||||
&& ( width ) <= dim.x
|
||||
&& ( height ) < _settings._top_left.y
|
||||
&& ( height ) <= dim.y )
|
||||
, "User provided view has incorrect size." );
|
||||
|
||||
io_error_if( ( ( _settings._top_left.x + dim.x ) > width
|
||||
|| ( _settings._top_left.y + dim.y ) > height
|
||||
)
|
||||
, "User provided view has incorrect size." );
|
||||
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
image_read_settings< FormatTag > _settings;
|
||||
image_read_info< FormatTag > _info;
|
||||
|
||||
ConversionPolicy _cc_policy;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_READER_BASE_HPP
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_DETAIL_READ_HELPER_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_READ_HELPER_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Helper for having one read implementation used for
|
||||
/// bit_aligned and byte images.
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/gil/extension/toolbox/gil_extensions.hpp>
|
||||
|
||||
#include "typedefs.hpp"
|
||||
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename Pixel
|
||||
, typename DummyT = void
|
||||
>
|
||||
struct row_buffer_helper
|
||||
{
|
||||
typedef Pixel element_t;
|
||||
typedef std::vector< element_t > buffer_t;
|
||||
typedef typename buffer_t::iterator iterator_t;
|
||||
|
||||
row_buffer_helper( std::size_t width
|
||||
, bool
|
||||
)
|
||||
: _row_buffer( width )
|
||||
{}
|
||||
|
||||
element_t* data() { return &_row_buffer[0]; }
|
||||
|
||||
iterator_t begin() { return _row_buffer.begin(); }
|
||||
iterator_t end() { return _row_buffer.end(); }
|
||||
|
||||
buffer_t& buffer() { return _row_buffer; }
|
||||
|
||||
private:
|
||||
|
||||
buffer_t _row_buffer;
|
||||
};
|
||||
|
||||
template<typename Pixel >
|
||||
struct row_buffer_helper< Pixel
|
||||
, typename enable_if< typename mpl::and_< typename is_bit_aligned< Pixel >::type
|
||||
, typename is_homogeneous< Pixel >::type
|
||||
>::type
|
||||
>::type
|
||||
>
|
||||
{
|
||||
typedef byte_t element_t;
|
||||
typedef std::vector< element_t > buffer_t;
|
||||
typedef Pixel pixel_type;
|
||||
typedef bit_aligned_pixel_iterator<pixel_type> iterator_t;
|
||||
|
||||
row_buffer_helper( std::size_t width
|
||||
, bool in_bytes
|
||||
)
|
||||
: _c( ( width
|
||||
* num_channels< pixel_type >::type::value
|
||||
* channel_type< pixel_type >::type::num_bits
|
||||
)
|
||||
>> 3
|
||||
)
|
||||
|
||||
, _r( width
|
||||
* num_channels< pixel_type >::type::value
|
||||
* channel_type< pixel_type >::type::num_bits
|
||||
- ( _c << 3 )
|
||||
)
|
||||
{
|
||||
if( in_bytes )
|
||||
{
|
||||
_row_buffer.resize( width );
|
||||
}
|
||||
else
|
||||
{
|
||||
// add one byte if there are remaining bits
|
||||
_row_buffer.resize( _c + ( _r!=0 ));
|
||||
}
|
||||
}
|
||||
|
||||
element_t* data() { return &_row_buffer[0]; }
|
||||
|
||||
iterator_t begin() { return iterator_t( &_row_buffer.front(),0 ); }
|
||||
iterator_t end() { return _r == 0 ? iterator_t( &_row_buffer.back() + 1, 0 )
|
||||
: iterator_t( &_row_buffer.back() , (int) _r );
|
||||
}
|
||||
|
||||
buffer_t& buffer() { return _row_buffer; }
|
||||
|
||||
private:
|
||||
|
||||
// For instance 25 pixels of rgb2 type would be:
|
||||
// overall 25 pixels * 3 channels * 2 bits/channel = 150 bits
|
||||
// c = 18 bytes
|
||||
// r = 6 bits
|
||||
|
||||
std::size_t _c; // number of full bytes
|
||||
std::size_t _r; // number of remaining bits
|
||||
|
||||
buffer_t _row_buffer;
|
||||
};
|
||||
|
||||
template< typename View
|
||||
, typename D = void
|
||||
>
|
||||
struct row_buffer_helper_view : row_buffer_helper< typename View::value_type >
|
||||
{
|
||||
row_buffer_helper_view( std::size_t width
|
||||
, bool in_bytes
|
||||
)
|
||||
: row_buffer_helper< typename View::value_type >( width
|
||||
, in_bytes
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
|
||||
template< typename View >
|
||||
struct row_buffer_helper_view< View
|
||||
, typename enable_if< typename is_bit_aligned< typename View::value_type
|
||||
>::type
|
||||
>::type
|
||||
> : row_buffer_helper< typename View::reference >
|
||||
{
|
||||
row_buffer_helper_view( std::size_t width
|
||||
, bool in_bytes
|
||||
)
|
||||
: row_buffer_helper< typename View::reference >( width
|
||||
, in_bytes
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_READ_HELPER_HPP
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BASE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BASE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/type_traits/is_base_of.hpp>
|
||||
|
||||
#include <boost/gil/image.hpp>
|
||||
#include <boost/gil/utilities.hpp>
|
||||
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
#include <boost/gil/extension/toolbox/gray_alpha.hpp>
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
struct double_zero { static double apply() { return 0.0; } };
|
||||
struct double_one { static double apply() { return 1.0; } };
|
||||
|
||||
typedef scoped_channel_value< double, double_zero, double_one > bits64f;
|
||||
|
||||
typedef unsigned char byte_t;
|
||||
typedef std::vector< byte_t > byte_vector_t;
|
||||
|
||||
typedef point2< std::ptrdiff_t > point_t;
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<> struct is_floating_point< gil::bits32f > : mpl::true_ {};
|
||||
template<> struct is_floating_point< gil::bits64f > : mpl::true_ {};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
///@todo We should use boost::preprocessor here.
|
||||
|
||||
typedef bit_aligned_image1_type< 1, gray_layout_t >::type gray1_image_t;
|
||||
typedef bit_aligned_image1_type< 2, gray_layout_t >::type gray2_image_t;
|
||||
typedef bit_aligned_image1_type< 4, gray_layout_t >::type gray4_image_t;
|
||||
|
||||
typedef pixel< double, gray_layout_t > gray64f_pixel_t;
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
typedef pixel< double, gray_alpha_layout_t > gray_alpha64f_pixel_t;
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
typedef pixel< double, rgb_layout_t > rgb64f_pixel_t;
|
||||
typedef pixel< double, rgba_layout_t > rgba64f_pixel_t;
|
||||
|
||||
typedef image< gray64f_pixel_t , false > gray64f_image_t;
|
||||
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
typedef image< gray_alpha32f_pixel_t, false > gray_alpha32f_image_t;
|
||||
typedef image< gray_alpha32f_pixel_t, true > gray_alpha32f_planar_image_t;
|
||||
typedef image< gray_alpha64f_pixel_t, false > gray_alpha64f_image_t;
|
||||
typedef image< gray_alpha64f_pixel_t, true > gray_alpha64f_planar_image_t;
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
typedef image< rgb64f_pixel_t , false > rgb64f_image_t;
|
||||
typedef image< rgb64f_pixel_t , true > rgb64f_planar_image_t;
|
||||
typedef image< rgba64f_pixel_t , false > rgba64f_image_t;
|
||||
typedef image< rgba64f_pixel_t , true > rgba64f_planar_image_t;
|
||||
|
||||
} // namespace details
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BASE_HPP
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_WRITE_VIEW_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_WRITE_VIEW_HPP
|
||||
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/type_traits/is_base_and_derived.hpp>
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "io_device.hpp"
|
||||
#include "path_spec.hpp"
|
||||
#include "conversion_policies.hpp"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// \ingroup IO
|
||||
template< typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const View& view
|
||||
, const FormatTag&
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_output_device< Device >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_write_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::writer< Device
|
||||
, FormatTag
|
||||
> writer( device );
|
||||
|
||||
writer.apply( view );
|
||||
}
|
||||
|
||||
template< typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const View& view
|
||||
, const FormatTag& tag
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_write_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::device_type dev_t;
|
||||
dev_t dev( device );
|
||||
|
||||
write_view( dev
|
||||
, view
|
||||
, tag
|
||||
);
|
||||
}
|
||||
|
||||
template< typename String
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void write_view( const String& file_name
|
||||
, const View& view
|
||||
, const FormatTag& tag
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_supported_path_spec< String >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_write_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device<FormatTag> device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device<FormatTag>::write_tag()
|
||||
);
|
||||
|
||||
write_view( device
|
||||
, view
|
||||
, tag
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup IO
|
||||
template< typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
, typename Log
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const View& view
|
||||
, const image_write_info<FormatTag, Log>& info
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_output_device< Device >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_write_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::writer< Device
|
||||
, FormatTag
|
||||
, Log
|
||||
> writer( device );
|
||||
|
||||
writer.apply( view
|
||||
, info );
|
||||
}
|
||||
|
||||
template< typename Device
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
, typename Log
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const View& view
|
||||
, const image_write_info< FormatTag, Log >& info
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_write_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::device_type dev( device );
|
||||
|
||||
write_view( dev
|
||||
, view
|
||||
, info
|
||||
);
|
||||
}
|
||||
|
||||
template< typename String
|
||||
, typename View
|
||||
, typename FormatTag
|
||||
, typename Log
|
||||
>
|
||||
inline
|
||||
void write_view( const String& file_name
|
||||
, const View& view
|
||||
, const image_write_info< FormatTag, Log >& info
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_supported_path_spec< String >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
, typename is_write_supported< typename get_pixel_type< View >::type
|
||||
, FormatTag
|
||||
>::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::write_tag()
|
||||
);
|
||||
|
||||
write_view( device
|
||||
, view
|
||||
, info
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////// dynamic_image
|
||||
|
||||
// without image_write_info
|
||||
template< typename Device
|
||||
, typename Views
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const any_image_view< Views >& view
|
||||
, const FormatTag&
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_output_device< Device >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::dynamic_image_writer< Device
|
||||
, FormatTag
|
||||
> dyn_writer( device );
|
||||
|
||||
dyn_writer.apply( view );
|
||||
}
|
||||
|
||||
template< typename Device
|
||||
, typename Views
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const any_image_view< Views >& views
|
||||
, const FormatTag& tag
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typedef typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::device_type dev_t;
|
||||
dev_t dev( device );
|
||||
|
||||
write_view( dev
|
||||
, views
|
||||
, tag
|
||||
);
|
||||
}
|
||||
|
||||
template< typename String
|
||||
, typename Views
|
||||
, typename FormatTag
|
||||
>
|
||||
inline
|
||||
void write_view( const String& file_name
|
||||
, const any_image_view< Views >& views
|
||||
, const FormatTag& tag
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_supported_path_spec< String >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device<FormatTag> device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device<FormatTag>::write_tag()
|
||||
);
|
||||
|
||||
write_view( device
|
||||
, views
|
||||
, tag
|
||||
);
|
||||
}
|
||||
|
||||
// with image_write_info
|
||||
/// \ingroup IO
|
||||
template< typename Device
|
||||
, typename Views
|
||||
, typename FormatTag
|
||||
, typename Log
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const any_image_view< Views >& views
|
||||
, const image_write_info< FormatTag
|
||||
, Log
|
||||
>& info
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_output_device< Device >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::dynamic_image_writer< Device
|
||||
, FormatTag
|
||||
, Log
|
||||
> dyn_writer( device );
|
||||
|
||||
dyn_writer.apply( views
|
||||
, info
|
||||
);
|
||||
}
|
||||
|
||||
template< typename Device
|
||||
, typename Views
|
||||
, typename FormatTag
|
||||
, typename Log
|
||||
>
|
||||
inline
|
||||
void write_view( Device& device
|
||||
, const any_image_view< Views >& views
|
||||
, const image_write_info< FormatTag
|
||||
, Log
|
||||
>& info
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
typename detail::is_adaptable_output_device< FormatTag
|
||||
, Device
|
||||
>::device_type dev( device );
|
||||
|
||||
write_view( dev
|
||||
, views
|
||||
, info
|
||||
);
|
||||
}
|
||||
|
||||
template< typename String
|
||||
, typename Views
|
||||
, typename FormatTag
|
||||
, typename Log
|
||||
>
|
||||
inline
|
||||
void write_view( const String& file_name
|
||||
, const any_image_view< Views >& views
|
||||
, const image_write_info< FormatTag
|
||||
, Log
|
||||
>& info
|
||||
, typename enable_if< typename mpl::and_< typename detail::is_supported_path_spec< String >::type
|
||||
, typename is_format_tag< FormatTag >::type
|
||||
>::type
|
||||
>::type* /* ptr */ = 0
|
||||
)
|
||||
{
|
||||
detail::file_stream_device< FormatTag > device( detail::convert_to_string( file_name )
|
||||
, typename detail::file_stream_device< FormatTag >::write_tag()
|
||||
);
|
||||
|
||||
write_view( device
|
||||
, views
|
||||
, info
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_WRITE_VIEW_HPP
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
Copyright 2009 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_IO_IS_ALLOWED_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_IO_IS_ALLOWED_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< bmp_tag >& info
|
||||
, mpl::true_ // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
bmp_bits_per_pixel::type src_bits_per_pixel = 0;
|
||||
|
||||
switch( info._bits_per_pixel )
|
||||
{
|
||||
case 1:
|
||||
case 4:
|
||||
case 8:
|
||||
{
|
||||
if( info._header_size == bmp_header_size::_win32_info_size
|
||||
&& info._compression != bmp_compression::_rle8
|
||||
&& info._compression != bmp_compression::_rle4
|
||||
)
|
||||
{
|
||||
src_bits_per_pixel = 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_bits_per_pixel = 24;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
src_bits_per_pixel = 24;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 24:
|
||||
case 32:
|
||||
{
|
||||
src_bits_per_pixel = info._bits_per_pixel;
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
io_error( "Pixel size not supported." );
|
||||
}
|
||||
}
|
||||
|
||||
typedef typename channel_traits< typename element_type< typename View::value_type >::type >::value_type channel_t;
|
||||
bmp_bits_per_pixel::type dst_bits_per_pixel = detail::unsigned_integral_num_bits< channel_t >::value
|
||||
* num_channels< View >::value;
|
||||
|
||||
return ( dst_bits_per_pixel == src_bits_per_pixel );
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< bmp_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_IO_IS_ALLOWED_HPP
|
||||
@@ -0,0 +1,865 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_IO_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_IO_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <vector>
|
||||
#include <boost/gil/extension/io_new/bmp_tags.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/bit_operations.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/conversion_policies.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/row_buffer_helper.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/reader_base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/typedefs.hpp>
|
||||
|
||||
#include "is_allowed.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
/// Color channel mask
|
||||
struct bit_field
|
||||
{
|
||||
unsigned int mask; // Bit mask at corresponding position
|
||||
unsigned int width; // Bit width of the mask
|
||||
unsigned int shift; // Bit position from right to left
|
||||
};
|
||||
|
||||
/// BMP color masks
|
||||
struct color_mask
|
||||
{
|
||||
bit_field red; // Red bits
|
||||
bit_field green; // Green bits
|
||||
bit_field blue; // Blue bits
|
||||
};
|
||||
|
||||
|
||||
template< typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
class reader< Device
|
||||
, bmp_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
: public reader_base< bmp_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef typename ConversionPolicy::color_converter_type cc_t;
|
||||
|
||||
public:
|
||||
|
||||
reader( Device& device
|
||||
, const image_read_settings< bmp_tag >& settings
|
||||
)
|
||||
: reader_base< bmp_tag
|
||||
, ConversionPolicy >( settings )
|
||||
, _io_dev( device )
|
||||
{}
|
||||
|
||||
reader( Device& device
|
||||
, const cc_t& cc
|
||||
, const image_read_settings< bmp_tag >& settings
|
||||
)
|
||||
: reader_base< bmp_tag
|
||||
, ConversionPolicy
|
||||
>( cc
|
||||
, settings
|
||||
)
|
||||
, _io_dev( device )
|
||||
{}
|
||||
|
||||
image_read_info< bmp_tag > get_info()
|
||||
{
|
||||
// read file header
|
||||
|
||||
// the magic number used to identify the BMP file:
|
||||
// 0x42 0x4D (ASCII code points for B and M)
|
||||
if( _io_dev.read_int16() == 0x424D )
|
||||
{
|
||||
io_error( "Wrong magic number for bmp file." );
|
||||
}
|
||||
|
||||
// the size of the BMP file in bytes
|
||||
_io_dev.read_int32();
|
||||
|
||||
// reserved; actual value depends on the application that creates the image
|
||||
_io_dev.read_int16();
|
||||
// reserved; actual value depends on the application that creates the image
|
||||
_io_dev.read_int16();
|
||||
|
||||
_info._offset = _io_dev.read_int32();
|
||||
|
||||
|
||||
// bitmap information
|
||||
|
||||
// the size of this header ( 40 bytes )
|
||||
_info._header_size = _io_dev.read_int32();
|
||||
|
||||
if( _info._header_size == bmp_header_size::_win32_info_size )
|
||||
{
|
||||
_info._width = _io_dev.read_int32();
|
||||
_info._height = _io_dev.read_int32();
|
||||
|
||||
// the number of color planes being used. Must be set to 1.
|
||||
_io_dev.read_int16();
|
||||
|
||||
_info._bits_per_pixel = _io_dev.read_int16();
|
||||
|
||||
_info._compression = _io_dev.read_int32();
|
||||
|
||||
_info._image_size = _io_dev.read_int32();
|
||||
|
||||
_info._horizontal_resolution = _io_dev.read_int32();
|
||||
_info._vertical_resolution = _io_dev.read_int32();
|
||||
|
||||
_info._num_colors = _io_dev.read_int32();
|
||||
_info._num_important_colors = _io_dev.read_int32();
|
||||
|
||||
}
|
||||
else if( _info._header_size == bmp_header_size::_os2_info_size )
|
||||
{
|
||||
_info._width = static_cast< bmp_image_width::type >( _io_dev.read_int16() );
|
||||
_info._height = static_cast< bmp_image_height::type >( _io_dev.read_int16() );
|
||||
|
||||
// the number of color planes being used. Must be set to 1.
|
||||
_io_dev.read_int16();
|
||||
|
||||
_info._bits_per_pixel = _io_dev.read_int16();
|
||||
|
||||
_info._compression = bmp_compression::_rgb;
|
||||
|
||||
// not used
|
||||
_info._image_size = 0;
|
||||
_info._horizontal_resolution = 0;
|
||||
_info._vertical_resolution = 0;
|
||||
_info._num_colors = 0;
|
||||
_info._num_important_colors = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
io_error( "Invalid BMP info header." );
|
||||
}
|
||||
|
||||
_info._valid = true;
|
||||
|
||||
return _info;
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void apply( const View& dst_view )
|
||||
{
|
||||
if( !_info._valid )
|
||||
{
|
||||
get_info();
|
||||
}
|
||||
|
||||
typedef typename is_same< ConversionPolicy
|
||||
, read_and_no_convert
|
||||
>::type is_read_and_convert_t;
|
||||
|
||||
io_error_if( !is_allowed< View >( this->_info
|
||||
, is_read_and_convert_t()
|
||||
)
|
||||
, "Image types aren't compatible."
|
||||
);
|
||||
|
||||
// the row pitch must be multiple 4 bytes
|
||||
int pitch;
|
||||
|
||||
if( _info._bits_per_pixel < 8 )
|
||||
{
|
||||
pitch = (( this->_info._width * this->_info._bits_per_pixel ) + 7 ) >> 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
pitch = _info._width * (( this->_info._bits_per_pixel + 7 ) >> 3);
|
||||
}
|
||||
|
||||
pitch = (pitch + 3) & ~3;
|
||||
|
||||
|
||||
std::ptrdiff_t ybeg = 0;
|
||||
std::ptrdiff_t yend = this->_settings._dim.y;
|
||||
std::ptrdiff_t yinc = 1;
|
||||
|
||||
// offset to first scanline
|
||||
std::ptrdiff_t offset = 0;
|
||||
|
||||
if( _info._height > 0 )
|
||||
{
|
||||
// the image is upside down
|
||||
ybeg = this->_settings._dim.y - 1;
|
||||
yend = -1;
|
||||
yinc = -1;
|
||||
|
||||
offset = _info._offset
|
||||
+ ( this->_info._height
|
||||
- this->_settings._top_left.y
|
||||
- this->_settings._dim.y
|
||||
) * pitch;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
offset = _info._offset
|
||||
+ this->_settings._top_left.y * pitch;
|
||||
}
|
||||
|
||||
switch( _info._bits_per_pixel )
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
read_palette_image< gray1_image_t::view_t
|
||||
, mirror_bits< byte_vector_t
|
||||
, mpl::true_
|
||||
>
|
||||
> ( dst_view
|
||||
, pitch
|
||||
, ybeg
|
||||
, yend
|
||||
, yinc
|
||||
, offset
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
switch ( _info._compression )
|
||||
{
|
||||
case bmp_compression::_rle4:
|
||||
{
|
||||
read_palette_image_rle( dst_view
|
||||
, ybeg
|
||||
, yend
|
||||
, yinc
|
||||
, offset
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case bmp_compression::_rgb:
|
||||
{
|
||||
read_palette_image< gray4_image_t::view_t
|
||||
, swap_half_bytes< byte_vector_t
|
||||
, mpl::true_
|
||||
>
|
||||
> ( dst_view
|
||||
, pitch
|
||||
, ybeg
|
||||
, yend
|
||||
, yinc
|
||||
, offset
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
io_error( "Unsupported compression mode in BMP file." );
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 8:
|
||||
{
|
||||
switch ( _info._compression )
|
||||
{
|
||||
case bmp_compression::_rle8:
|
||||
{
|
||||
read_palette_image_rle( dst_view
|
||||
, ybeg
|
||||
, yend
|
||||
, yinc
|
||||
, offset
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
case bmp_compression::_rgb:
|
||||
{
|
||||
read_palette_image< gray8_image_t::view_t
|
||||
, do_nothing< std::vector< gray8_pixel_t > >
|
||||
> ( dst_view
|
||||
, pitch
|
||||
, ybeg
|
||||
, yend
|
||||
, yinc
|
||||
, offset
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
io_error( "Unsupported compression mode in BMP file." );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 15: case 16:
|
||||
{
|
||||
read_data_15( dst_view
|
||||
, pitch
|
||||
, ybeg
|
||||
, yend
|
||||
, yinc
|
||||
, offset
|
||||
);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 24: { read_data< bgr8_view_t >( dst_view, pitch, ybeg, yend, yinc, offset ); break; }
|
||||
case 32: { read_data< bgra8_view_t >( dst_view, pitch, ybeg, yend, yinc, offset ); break; }
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void read_palette( std::vector< rgba8_pixel_t >& palette )
|
||||
{
|
||||
int entries = _info._num_colors;
|
||||
|
||||
if( entries == 0 )
|
||||
{
|
||||
entries = 1 << _info._bits_per_pixel;
|
||||
}
|
||||
|
||||
palette.resize( entries );
|
||||
|
||||
for( int i = 0; i < entries; ++i )
|
||||
{
|
||||
get_color( palette[i], blue_t() ) = _io_dev.read_int8();
|
||||
get_color( palette[i], green_t() ) = _io_dev.read_int8();
|
||||
get_color( palette[i], red_t() ) = _io_dev.read_int8();
|
||||
|
||||
// there are 4 entries when windows header
|
||||
// but 3 for os2 header
|
||||
if( _info._header_size == bmp_header_size::_win32_info_size )
|
||||
{
|
||||
_io_dev.read_int8();
|
||||
}
|
||||
|
||||
} // for
|
||||
}
|
||||
|
||||
template< typename View_Src
|
||||
, typename Byte_Manipulator
|
||||
, typename View_Dst
|
||||
>
|
||||
void read_palette_image( const View_Dst& view
|
||||
, int pitch
|
||||
, std::ptrdiff_t ybeg
|
||||
, std::ptrdiff_t yend
|
||||
, std::ptrdiff_t yinc
|
||||
, std::ptrdiff_t offset
|
||||
)
|
||||
{
|
||||
std::vector< rgba8_pixel_t > pal;
|
||||
read_palette( pal );
|
||||
|
||||
// jump to first scanline
|
||||
_io_dev.seek( static_cast< long >( offset ));
|
||||
|
||||
typedef row_buffer_helper_view< View_Src > rh_t;
|
||||
typedef typename rh_t::iterator_t it_t;
|
||||
|
||||
rh_t rh( pitch, true );
|
||||
|
||||
// we have to swap bits
|
||||
Byte_Manipulator byte_manipulator;
|
||||
|
||||
for( std::ptrdiff_t y = ybeg; y != yend; y += yinc )
|
||||
{
|
||||
// @todo: For now we're reading the whole scanline which is
|
||||
// slightly inefficient. Later versions should try to read
|
||||
// only the bytes which are necessary.
|
||||
_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
|
||||
, pitch
|
||||
);
|
||||
|
||||
byte_manipulator( rh.buffer() );
|
||||
|
||||
typename View_Dst::x_iterator dst_it = view.row_begin( y );
|
||||
|
||||
it_t it = rh.begin() + this->_settings._top_left.x;
|
||||
it_t end = it + this->_settings._dim.x;
|
||||
|
||||
for( ; it != end; ++it, ++dst_it )
|
||||
{
|
||||
unsigned char c = get_color( *it, gray_color_t() );
|
||||
*dst_it = pal[ c ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void read_data_15( const View& view
|
||||
, int pitch
|
||||
, std::ptrdiff_t ybeg
|
||||
, std::ptrdiff_t yend
|
||||
, std::ptrdiff_t yinc
|
||||
, std::ptrdiff_t offset
|
||||
)
|
||||
{
|
||||
byte_vector_t row( pitch );
|
||||
|
||||
// read the color masks
|
||||
color_mask mask = { {0} };
|
||||
if( _info._compression == bmp_compression::_bitfield )
|
||||
{
|
||||
mask.red.mask = _io_dev.read_int32();
|
||||
mask.green.mask = _io_dev.read_int32();
|
||||
mask.blue.mask = _io_dev.read_int32();
|
||||
|
||||
mask.red.width = count_ones( mask.red.mask );
|
||||
mask.green.width = count_ones( mask.green.mask );
|
||||
mask.blue.width = count_ones( mask.blue.mask );
|
||||
|
||||
mask.red.shift = trailing_zeros( mask.red.mask );
|
||||
mask.green.shift = trailing_zeros( mask.green.mask );
|
||||
mask.blue.shift = trailing_zeros( mask.blue.mask );
|
||||
}
|
||||
else if( _info._compression == bmp_compression::_rgb )
|
||||
{
|
||||
switch( _info._bits_per_pixel )
|
||||
{
|
||||
case 15:
|
||||
case 16:
|
||||
{
|
||||
mask.red.mask = 0x007C00; mask.red.width = 5; mask.red.shift = 10;
|
||||
mask.green.mask = 0x0003E0; mask.green.width = 5; mask.green.shift = 5;
|
||||
mask.blue.mask = 0x00001F; mask.blue.width = 5; mask.blue.shift = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
case 24:
|
||||
case 32:
|
||||
{
|
||||
mask.red.mask = 0xFF0000; mask.red.width = 8; mask.red.shift = 16;
|
||||
mask.green.mask = 0x00FF00; mask.green.width = 8; mask.green.shift = 8;
|
||||
mask.blue.mask = 0x0000FF; mask.blue.width = 8; mask.blue.shift = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
io_error( "bmp_reader::apply(): unsupported BMP compression" );
|
||||
}
|
||||
|
||||
// jump to first scanline
|
||||
_io_dev.seek( static_cast< long >( offset ));
|
||||
|
||||
typedef rgb8_image_t image_t;
|
||||
typedef image_t::view_t::x_iterator it_t;
|
||||
|
||||
for( std::ptrdiff_t y = ybeg; y != yend; y += yinc )
|
||||
{
|
||||
// @todo: For now we're reading the whole scanline which is
|
||||
// slightly inefficient. Later versions should try to read
|
||||
// only the bytes which are necessary.
|
||||
_io_dev.read( &row.front(), row.size() );
|
||||
|
||||
image_t img_row( _info._width, 1 );
|
||||
image_t::view_t v = gil::view( img_row );
|
||||
it_t it = v.row_begin( 0 );
|
||||
|
||||
it_t beg = v.row_begin( 0 ) + this->_settings._top_left.x;
|
||||
it_t end = beg + this->_settings._dim.x;
|
||||
|
||||
byte_t* src = &row.front();
|
||||
for( int32_t i = 0 ; i < _info._width; ++i, src += 2 )
|
||||
{
|
||||
int p = ( src[1] << 8 ) | src[0];
|
||||
|
||||
int r = ((p & mask.red.mask) >> mask.red.shift) << (8 - mask.red.width);
|
||||
int g = ((p & mask.green.mask) >> mask.green.shift) << (8 - mask.green.width);
|
||||
int b = ((p & mask.blue.mask) >> mask.blue.shift) << (8 - mask.blue.width);
|
||||
|
||||
get_color( it[i], red_t() ) = static_cast< byte_t >( r );
|
||||
get_color( it[i], green_t() ) = static_cast< byte_t >( g );
|
||||
get_color( it[i], blue_t() ) = static_cast< byte_t >( b );
|
||||
}
|
||||
|
||||
this->_cc_policy.read( beg
|
||||
, end
|
||||
, view.row_begin( y )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 8-8-8 BGR
|
||||
// 8-8-8-8 BGRA
|
||||
template< typename View_Src
|
||||
, typename View_Dst
|
||||
>
|
||||
void read_data( const View_Dst& view
|
||||
, int pitch
|
||||
, std::ptrdiff_t ybeg
|
||||
, std::ptrdiff_t yend
|
||||
, std::ptrdiff_t yinc
|
||||
, std::ptrdiff_t offset
|
||||
)
|
||||
{
|
||||
byte_vector_t row( pitch );
|
||||
|
||||
// jump to first scanline
|
||||
_io_dev.seek( static_cast< long >( offset ));
|
||||
|
||||
View_Src v = interleaved_view( _info._width
|
||||
, 1
|
||||
, (typename View_Src::value_type*) &row.front()
|
||||
, _info._width * num_channels< View_Src >::value
|
||||
);
|
||||
|
||||
typename View_Src::x_iterator beg = v.row_begin( 0 ) + this->_settings._top_left.x;
|
||||
typename View_Src::x_iterator end = beg + this->_settings._dim.x;
|
||||
|
||||
for( std::ptrdiff_t y = ybeg; y != yend; y += yinc )
|
||||
{
|
||||
// @todo: For now we're reading the whole scanline which is
|
||||
// slightly inefficient. Later versions should try to read
|
||||
// only the bytes which are necessary.
|
||||
_io_dev.read( &row.front(), row.size() );
|
||||
|
||||
this->_cc_policy.read( beg
|
||||
, end
|
||||
, view.row_begin( y )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template< typename Buffer
|
||||
, typename View
|
||||
>
|
||||
void copy_row_if_needed( const Buffer& buf
|
||||
, const View& view
|
||||
, std::ptrdiff_t y
|
||||
)
|
||||
{
|
||||
if( y >= this->_settings._top_left.y
|
||||
&& y < this->_settings._dim.y
|
||||
)
|
||||
{
|
||||
typename Buffer::const_iterator beg = buf.begin() + this->_settings._top_left.x;
|
||||
typename Buffer::const_iterator end = beg + this->_settings._dim.x;
|
||||
|
||||
std::copy( beg
|
||||
, end
|
||||
, view.row_begin( y )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View_Dst >
|
||||
void read_palette_image_rle( const View_Dst& view
|
||||
, std::ptrdiff_t ybeg
|
||||
, std::ptrdiff_t yend
|
||||
, std::ptrdiff_t yinc
|
||||
, std::ptrdiff_t offset
|
||||
)
|
||||
{
|
||||
assert( _info._compression == bmp_compression::_rle4
|
||||
|| _info._compression == bmp_compression::_rle8
|
||||
);
|
||||
|
||||
std::vector< rgba8_pixel_t > pal;
|
||||
read_palette( pal );
|
||||
|
||||
// jump to start of rle4 data
|
||||
_io_dev.seek( static_cast< long >( offset ));
|
||||
|
||||
// we need to know the stream position for padding purposes
|
||||
std::size_t stream_pos = offset;
|
||||
|
||||
typedef std::vector< rgba8_pixel_t > Buf_type;
|
||||
Buf_type buf( this->_settings._dim.x );
|
||||
Buf_type::iterator dst_it = buf.begin();
|
||||
Buf_type::iterator dst_end = buf.end();
|
||||
|
||||
std::ptrdiff_t y = ybeg;
|
||||
bool finished = false;
|
||||
|
||||
while ( !finished )
|
||||
{
|
||||
std::ptrdiff_t count = _io_dev.read_int8();
|
||||
std::ptrdiff_t second = _io_dev.read_int8();
|
||||
stream_pos += 2;
|
||||
|
||||
if ( count )
|
||||
{
|
||||
// encoded mode
|
||||
|
||||
// clamp to boundary
|
||||
if( count > dst_end - dst_it )
|
||||
{
|
||||
count = dst_end - dst_it;
|
||||
}
|
||||
|
||||
if( _info._compression == bmp_compression::_rle4 )
|
||||
{
|
||||
std::ptrdiff_t cs[2] = { second >> 4, second & 0x0f };
|
||||
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
*dst_it++ = pal[ cs[i & 1] ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
*dst_it++ = pal[ second ];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( second )
|
||||
{
|
||||
case 0: // end of row
|
||||
{
|
||||
copy_row_if_needed( buf, view, y );
|
||||
|
||||
y += yinc;
|
||||
if( y == yend )
|
||||
{
|
||||
finished = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
dst_it = buf.begin();
|
||||
dst_end = buf.end();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 1: // end of bitmap
|
||||
{
|
||||
copy_row_if_needed( buf, view, y );
|
||||
finished = true;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: // offset coordinates
|
||||
{
|
||||
std::ptrdiff_t dx = _io_dev.read_int8();
|
||||
std::ptrdiff_t dy = _io_dev.read_int8() * yinc;
|
||||
stream_pos += 2;
|
||||
|
||||
if( dy )
|
||||
{
|
||||
copy_row_if_needed( buf, view, y );
|
||||
}
|
||||
|
||||
std::ptrdiff_t x = dst_it - buf.begin();
|
||||
x += dx;
|
||||
|
||||
if( x > _info._width )
|
||||
{
|
||||
io_error( "Mangled BMP file." );
|
||||
}
|
||||
|
||||
y += dy;
|
||||
if( yinc > 0 ? y > yend : y < yend )
|
||||
{
|
||||
io_error( "Mangled BMP file." );
|
||||
}
|
||||
|
||||
dst_it = buf.begin() + x;
|
||||
dst_end = buf.end();
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: // absolute mode
|
||||
{
|
||||
count = second;
|
||||
|
||||
// clamp to boundary
|
||||
if( count > dst_end - dst_it )
|
||||
{
|
||||
count = dst_end - dst_it;
|
||||
}
|
||||
|
||||
if ( _info._compression == bmp_compression::_rle4 )
|
||||
{
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
uint8_t packed_indices = _io_dev.read_int8();
|
||||
++stream_pos;
|
||||
|
||||
*dst_it++ = pal[ packed_indices >> 4 ];
|
||||
if( ++i == second )
|
||||
break;
|
||||
|
||||
*dst_it++ = pal[ packed_indices & 0x0f ];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int i = 0; i < count; ++i )
|
||||
{
|
||||
uint8_t c = _io_dev.read_int8();
|
||||
++stream_pos;
|
||||
*dst_it++ = pal[ c ];
|
||||
}
|
||||
}
|
||||
|
||||
// pad to word boundary
|
||||
if( ( stream_pos - offset ) & 1 )
|
||||
{
|
||||
_io_dev.seek( 1, SEEK_CUR );
|
||||
++stream_pos;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
Device& _io_dev;
|
||||
image_read_info< bmp_tag > _info;
|
||||
};
|
||||
|
||||
/////////////////////////////////// dynamic image
|
||||
|
||||
class bmp_type_format_checker
|
||||
{
|
||||
public:
|
||||
|
||||
bmp_type_format_checker( const bmp_bits_per_pixel::type& bpp )
|
||||
: _bpp( bpp )
|
||||
{}
|
||||
|
||||
template< typename Image >
|
||||
bool apply()
|
||||
{
|
||||
if( _bpp < 32 )
|
||||
{
|
||||
return pixels_are_compatible< typename Image::value_type, rgb8_pixel_t >::value
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pixels_are_compatible< typename Image::value_type, rgba8_pixel_t >::value
|
||||
? true
|
||||
: false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const bmp_bits_per_pixel::type& _bpp;
|
||||
};
|
||||
|
||||
struct bmp_read_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply : public is_read_supported< typename get_pixel_type< View >::type
|
||||
, bmp_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device
|
||||
>
|
||||
class dynamic_image_reader< Device
|
||||
, bmp_tag
|
||||
>
|
||||
: public reader< Device
|
||||
, bmp_tag
|
||||
, detail::read_and_no_convert
|
||||
>
|
||||
{
|
||||
typedef reader< Device
|
||||
, bmp_tag
|
||||
, detail::read_and_no_convert
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_reader( Device& device
|
||||
, const image_read_settings< bmp_tag >& settings
|
||||
)
|
||||
: parent_t( device
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
{
|
||||
if( !this->_info._valid )
|
||||
{
|
||||
parent_t::get_info();
|
||||
}
|
||||
|
||||
bmp_type_format_checker format_checker( this->_info._bits_per_pixel );
|
||||
|
||||
if( !construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
io_error( "No matching image type between those of the given any_image and that of the file" );
|
||||
}
|
||||
else
|
||||
{
|
||||
init_image( images
|
||||
, this->_info
|
||||
);
|
||||
|
||||
dynamic_io_fnobj< bmp_read_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_IO_READ_HPP
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_SUPPORTED_TYPES_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_SUPPORTED_TYPES_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/gil/color_base.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
// Read support
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct bmp_read_support : read_support_false
|
||||
{
|
||||
static const bmp_bits_per_pixel::type bpp = 0;
|
||||
};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct bmp_read_support< packed_dynamic_channel_reference< BitField
|
||||
, 1
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
{
|
||||
static const bmp_bits_per_pixel::type bpp = 1;
|
||||
};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct bmp_read_support< packed_dynamic_channel_reference< BitField
|
||||
, 4
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
{
|
||||
static const bmp_bits_per_pixel::type bpp = 4;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct bmp_read_support< bits8
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
{
|
||||
static const bmp_bits_per_pixel::type bpp = 8;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<>
|
||||
struct bmp_read_support< bits8
|
||||
, rgb_t
|
||||
> : read_support_true
|
||||
{
|
||||
static const bmp_bits_per_pixel::type bpp = 24;
|
||||
};
|
||||
|
||||
|
||||
template<>
|
||||
struct bmp_read_support< bits8
|
||||
, rgba_t
|
||||
> : read_support_true
|
||||
{
|
||||
static const bmp_bits_per_pixel::type bpp = 32;
|
||||
};
|
||||
|
||||
|
||||
// Write support
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct bmp_write_support : write_support_false
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct bmp_write_support< bits8
|
||||
, rgb_t
|
||||
> : write_support_true {};
|
||||
|
||||
template<>
|
||||
struct bmp_write_support< bits8
|
||||
, rgba_t
|
||||
> : write_support_true {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_read_supported< Pixel
|
||||
, bmp_tag
|
||||
>
|
||||
: mpl::bool_< detail::bmp_read_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
typedef detail::bmp_read_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
> parent_t;
|
||||
|
||||
static const typename bmp_bits_per_pixel::type bpp = parent_t::bpp;
|
||||
};
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_write_supported< Pixel
|
||||
, bmp_tag
|
||||
>
|
||||
: mpl::bool_< detail::bmp_write_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
> {};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_SUPPORTED_TYPES_HPP
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_BMP_IO_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_BMP_IO_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/bmp_tags.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template < int N > struct get_bgr_cs {};
|
||||
template <> struct get_bgr_cs< 1 > { typedef gray8_view_t type; };
|
||||
template <> struct get_bgr_cs< 3 > { typedef bgr8_view_t type; };
|
||||
template <> struct get_bgr_cs< 4 > { typedef bgra8_view_t type; };
|
||||
|
||||
template< typename Device >
|
||||
class writer< Device
|
||||
, bmp_tag
|
||||
>
|
||||
{
|
||||
public:
|
||||
|
||||
writer( Device& file )
|
||||
: _out( file )
|
||||
{
|
||||
}
|
||||
|
||||
~writer()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
write( view );
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view
|
||||
, const image_write_info< bmp_tag >& /* info */
|
||||
)
|
||||
{
|
||||
// Add code here, once image_write_info< bmp_tag > isn't empty anymore.
|
||||
|
||||
write( view );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template< typename View >
|
||||
void write( const View& view )
|
||||
{
|
||||
typedef typename channel_type<
|
||||
typename get_pixel_type< View >::type >::type channel_t;
|
||||
|
||||
typedef typename color_space_type< View >::type color_space_t;
|
||||
|
||||
// check if supported
|
||||
/*
|
||||
/// todo
|
||||
if( bmp_read_write_support_private<channel_t, color_space_t>::channel != 8)
|
||||
{
|
||||
io_error("Input view type is incompatible with the image type");
|
||||
}
|
||||
*/
|
||||
|
||||
// compute the file size
|
||||
int bpp = num_channels< View >::value * 8;
|
||||
int entries = 0;
|
||||
|
||||
/*
|
||||
/// @todo: Not supported for now. bit_aligned_images refer to indexed images
|
||||
/// in this context.
|
||||
if( bpp <= 8 )
|
||||
{
|
||||
entries = 1 << bpp;
|
||||
}
|
||||
*/
|
||||
|
||||
std::size_t spn = ( view.width() * num_channels< View >::value + 3 ) & ~3;
|
||||
std::size_t ofs = bmp_header_size::_size
|
||||
+ bmp_header_size::_win32_info_size
|
||||
+ entries * 4;
|
||||
|
||||
std::size_t siz = ofs + spn * view.height();
|
||||
|
||||
// write the BMP file header
|
||||
_out.write_int16( bmp_signature );
|
||||
_out.write_int32( (uint32_t) siz );
|
||||
_out.write_int16( 0 );
|
||||
_out.write_int16( 0 );
|
||||
_out.write_int32( (uint32_t) ofs );
|
||||
|
||||
// writes Windows information header
|
||||
_out.write_int32( bmp_header_size::_win32_info_size );
|
||||
_out.write_int32( static_cast< uint32_t >( view.width() ));
|
||||
_out.write_int32( static_cast< uint32_t >( view.height() ));
|
||||
_out.write_int16( 1 );
|
||||
_out.write_int16( static_cast< uint16_t >( bpp ));
|
||||
_out.write_int32( bmp_compression::_rgb );
|
||||
_out.write_int32( 0 );
|
||||
_out.write_int32( 0 );
|
||||
_out.write_int32( 0 );
|
||||
_out.write_int32( entries );
|
||||
_out.write_int32( 0 );
|
||||
|
||||
write_image< View
|
||||
, typename get_bgr_cs< num_channels< View >::value >::type
|
||||
>( view, spn );
|
||||
}
|
||||
|
||||
|
||||
template< typename View
|
||||
, typename BMP_View
|
||||
>
|
||||
void write_image( const View& view
|
||||
, const std::size_t spn
|
||||
)
|
||||
{
|
||||
byte_vector_t buffer( spn );
|
||||
std::fill( buffer.begin(), buffer.end(), 0 );
|
||||
|
||||
|
||||
BMP_View row = interleaved_view( view.width()
|
||||
, 1
|
||||
, (typename BMP_View::value_type*) &buffer.front()
|
||||
, spn
|
||||
);
|
||||
|
||||
for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
|
||||
{
|
||||
copy_pixels( subimage_view( view
|
||||
, 0
|
||||
, (int) y
|
||||
, (int) view.width()
|
||||
, 1
|
||||
)
|
||||
, row
|
||||
);
|
||||
|
||||
_out.write( &buffer.front(), spn );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Device& _out;
|
||||
};
|
||||
|
||||
|
||||
struct bmp_write_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply
|
||||
: public is_write_supported< typename get_pixel_type< View >::type
|
||||
, bmp_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device >
|
||||
class dynamic_image_writer< Device
|
||||
, bmp_tag
|
||||
>
|
||||
: public writer< Device
|
||||
, bmp_tag
|
||||
>
|
||||
{
|
||||
typedef writer< Device
|
||||
, bmp_tag
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_writer( Device& file )
|
||||
: parent_t( file )
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
{
|
||||
dynamic_io_fnobj< bmp_write_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( views, op );
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_BMP_IO_WRITE_HPP
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
Copyright 2010 Christian Henning
|
||||
Use, modification and distribution are subject to 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_DETAIL_JPEG_IO_BASE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_JPEG_IO_BASE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2010 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
#include <boost/gil/extension/io_new/jpeg_tags.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
class jpeg_io_base
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
jpeg_error_mgr _jerr;
|
||||
jmp_buf _mark;
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_JPEG_IO_BASE_HPP
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright 2009 Christian Henning
|
||||
Use, modification and distribution are subject to 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_IO_IS_ALLOWED_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_IO_IS_ALLOWED_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< jpeg_tag >& info
|
||||
, mpl::true_ // 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 */
|
||||
, mpl::false_ // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_IO_IS_ALLOWED_HPP
|
||||
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_IO_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_IO_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <csetjmp>
|
||||
#include <vector>
|
||||
#include <boost/gil/extension/io_new/jpeg_tags.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/conversion_policies.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/reader_base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/typedefs.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "is_allowed.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template<typename Device>
|
||||
struct jpeg_decompress_mgr : public jpeg_io_base
|
||||
{
|
||||
jpeg_decompress_mgr( Device& file )
|
||||
: in(file)
|
||||
{
|
||||
_cinfo.err = jpeg_std_error( &_jerr );
|
||||
_cinfo.client_data = this;
|
||||
|
||||
// Error exit handler: does not return to caller.
|
||||
_jerr.error_exit = &jpeg_decompress_mgr::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 )>( &jpeg_decompress_mgr< Device >::init_device );
|
||||
_src._jsrc.fill_input_buffer = reinterpret_cast< boolean(*)( j_decompress_ptr )>( &jpeg_decompress_mgr< Device >::fill_buffer );
|
||||
_src._jsrc.skip_input_data = reinterpret_cast< void(*) ( j_decompress_ptr
|
||||
, long num_bytes
|
||||
) >( &jpeg_decompress_mgr< Device >::skip_input_data );
|
||||
_src._jsrc.term_source = reinterpret_cast< void(*) ( j_decompress_ptr ) >( &jpeg_decompress_mgr< Device >::close_device );
|
||||
_src._jsrc.resync_to_restart = jpeg_resync_to_restart;
|
||||
_src._this = this;
|
||||
|
||||
jpeg_create_decompress( &_cinfo );
|
||||
|
||||
_cinfo.src = &_src._jsrc;
|
||||
|
||||
jpeg_read_header( &_cinfo
|
||||
, TRUE );
|
||||
|
||||
io_error_if( _cinfo.data_precision != 8
|
||||
, "Image file is not supported."
|
||||
);
|
||||
}
|
||||
|
||||
~jpeg_decompress_mgr()
|
||||
{
|
||||
jpeg_destroy_decompress( &_cinfo );
|
||||
}
|
||||
|
||||
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 )
|
||||
{
|
||||
jpeg_decompress_mgr< Device >* mgr = reinterpret_cast< jpeg_decompress_mgr< Device >* >( 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->in.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* ) {}
|
||||
|
||||
protected:
|
||||
jpeg_decompress_struct _cinfo;
|
||||
|
||||
|
||||
private:
|
||||
Device ∈
|
||||
|
||||
struct gil_jpeg_source_mgr
|
||||
{
|
||||
jpeg_source_mgr _jsrc;
|
||||
jpeg_decompress_mgr* _this;
|
||||
};
|
||||
|
||||
gil_jpeg_source_mgr _src;
|
||||
|
||||
// libjpeg default is 4096 - see jdatasrc.c
|
||||
JOCTET buffer[4096];
|
||||
};
|
||||
|
||||
template< typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
class reader< Device
|
||||
, jpeg_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
: public jpeg_decompress_mgr< Device >
|
||||
, public reader_base< jpeg_tag
|
||||
, ConversionPolicy >
|
||||
{
|
||||
public:
|
||||
reader( Device& device
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: jpeg_decompress_mgr<Device>( device )
|
||||
, reader_base< jpeg_tag
|
||||
, ConversionPolicy >( settings )
|
||||
{}
|
||||
|
||||
reader( Device& device
|
||||
, const typename ConversionPolicy::color_converter_type& cc
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: jpeg_decompress_mgr< Device >( device )
|
||||
, reader_base< jpeg_tag
|
||||
, ConversionPolicy >( cc
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
image_read_info< jpeg_tag > get_info()
|
||||
{
|
||||
image_read_info<jpeg_tag> ret;
|
||||
ret._width = this->_cinfo.image_width;
|
||||
ret._height = this->_cinfo.image_height;
|
||||
ret._num_components = this->_cinfo.num_components;
|
||||
ret._color_space = this->_cinfo.jpeg_color_space;
|
||||
ret._data_precision = this->_cinfo.data_precision;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
// Fire exception in case of error.
|
||||
if( setjmp( this->_mark )) { this->raise_error(); }
|
||||
|
||||
jpeg_decompress_struct& cinfo = this->_cinfo;
|
||||
cinfo.dct_method = this->_settings._dct_method;
|
||||
|
||||
typedef typename is_same< ConversionPolicy
|
||||
, read_and_no_convert
|
||||
>::type is_read_and_convert_t;
|
||||
|
||||
io_error_if( !is_allowed< View >( this->_info
|
||||
, is_read_and_convert_t()
|
||||
)
|
||||
, "Image types aren't compatible."
|
||||
);
|
||||
|
||||
if( jpeg_start_decompress( &this->_cinfo ) == false )
|
||||
{
|
||||
io_error( "Cannot start decompression." );
|
||||
}
|
||||
|
||||
switch( this->_info._color_space )
|
||||
{
|
||||
case JCS_GRAYSCALE: { read_rows< gray8_pixel_t >( view ); break; }
|
||||
case JCS_RGB: { read_rows< rgb8_pixel_t >( view ); break; }
|
||||
|
||||
//!\todo add Y'CbCr? We loose image quality when reading JCS_YCbCr as JCS_RGB
|
||||
case JCS_YCbCr: { read_rows< rgb8_pixel_t >( view ); break; }
|
||||
|
||||
case JCS_CMYK: { read_rows< cmyk8_pixel_t >( view ); break; }
|
||||
|
||||
//!\todo add Y'CbCrK? We loose image quality when reading JCS_YCCK as JCS_CMYK
|
||||
case JCS_YCCK:
|
||||
{
|
||||
this->_cinfo.out_color_space = JCS_CMYK;
|
||||
read_rows< cmyk8_pixel_t >( view );
|
||||
|
||||
break;
|
||||
}
|
||||
default: { io_error( "Unsupported jpeg color space." ); }
|
||||
}
|
||||
|
||||
jpeg_finish_decompress ( &this->_cinfo );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template< typename ImagePixel
|
||||
, typename View
|
||||
>
|
||||
void read_rows( const View& view )
|
||||
{
|
||||
typedef std::vector<ImagePixel> buffer_t;
|
||||
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->_cinfo
|
||||
, &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->_cinfo
|
||||
, &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->_cinfo.output_scanline < this->_cinfo.image_height )
|
||||
{
|
||||
io_error_if( jpeg_read_scanlines( &this->_cinfo
|
||||
, &row_adr
|
||||
, 1
|
||||
) !=1
|
||||
, "jpeg_read_scanlines: fail to read JPEG file"
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
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
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device
|
||||
>
|
||||
class dynamic_image_reader< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public reader< Device
|
||||
, jpeg_tag
|
||||
, detail::read_and_no_convert
|
||||
>
|
||||
{
|
||||
typedef reader< Device
|
||||
, jpeg_tag
|
||||
, detail::read_and_no_convert
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_reader( Device& device
|
||||
, const image_read_settings< jpeg_tag >& settings
|
||||
)
|
||||
: parent_t( device
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
{
|
||||
jpeg_type_format_checker format_checker( this->_info._color_space != JCS_YCbCr
|
||||
? this->_info._color_space
|
||||
: JCS_RGB
|
||||
);
|
||||
|
||||
if( !construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
io_error( "No matching image type between those of the given any_image and that of the file" );
|
||||
}
|
||||
else
|
||||
{
|
||||
init_image( images
|
||||
, this->_info
|
||||
);
|
||||
|
||||
dynamic_io_fnobj< jpeg_read_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_IO_READ_HPP
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_SUPPORTED_TYPES_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_SUPPORTED_TYPES_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/gil/color_base.hpp>
|
||||
|
||||
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< bits8
|
||||
, rgb_t
|
||||
> : read_support_true
|
||||
, jpeg_rw_support_base< JCS_RGB > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_read_support< bits8
|
||||
, cmyk_t
|
||||
> : read_support_true
|
||||
, jpeg_rw_support_base< JCS_CMYK > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_read_support< bits8
|
||||
, 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< bits8
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, jpeg_rw_support_base< JCS_GRAYSCALE > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_write_support< bits8
|
||||
, rgb_t
|
||||
> : write_support_true
|
||||
, jpeg_rw_support_base< JCS_RGB > {};
|
||||
|
||||
template<>
|
||||
struct jpeg_write_support< bits8
|
||||
, cmyk_t
|
||||
> : write_support_true
|
||||
, jpeg_rw_support_base< JCS_CMYK > {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_read_supported< Pixel
|
||||
, jpeg_tag
|
||||
>
|
||||
: mpl::bool_< detail::jpeg_read_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
typedef detail::jpeg_read_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
> parent_t;
|
||||
|
||||
static const typename jpeg_color_space::type _color_space = parent_t::_color_space;
|
||||
};
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_write_supported< Pixel
|
||||
, jpeg_tag
|
||||
>
|
||||
: mpl::bool_< detail::jpeg_write_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
>
|
||||
{};
|
||||
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_SUPPORTED_TYPES_HPP
|
||||
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_IO_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_IO_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/jpeg_tags.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "supported_types.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename Device >
|
||||
class writer< Device
|
||||
, jpeg_tag
|
||||
> : public jpeg_io_base
|
||||
{
|
||||
public:
|
||||
|
||||
writer( Device& file )
|
||||
: out( file )
|
||||
{
|
||||
_cinfo.err = jpeg_std_error( &_jerr );
|
||||
_cinfo.client_data = this;
|
||||
|
||||
// Error exit handler: does not return to caller.
|
||||
_jerr.error_exit = &writer< 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< Device, jpeg_tag >::init_device );
|
||||
_dest._jdest.empty_output_buffer = reinterpret_cast< boolean(*)( j_compress_ptr ) >( &writer< Device, jpeg_tag >::empty_buffer );
|
||||
_dest._jdest.term_destination = reinterpret_cast< void(*) ( j_compress_ptr ) >( &writer< Device, jpeg_tag >::close_device );
|
||||
_dest._this = this;
|
||||
|
||||
jpeg_create_compress( &_cinfo );
|
||||
_cinfo.dest = &_dest._jdest;
|
||||
|
||||
}
|
||||
|
||||
~writer()
|
||||
{
|
||||
jpeg_finish_compress ( &_cinfo );
|
||||
jpeg_destroy_compress( &_cinfo );
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
write_rows( view
|
||||
, jpeg_quality::default_value
|
||||
, jpeg_dct_method::default_value
|
||||
);
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void apply( const View& view
|
||||
, const image_write_info< jpeg_tag >& info )
|
||||
{
|
||||
write_rows( view
|
||||
, info._quality
|
||||
, info._dct_method
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename View>
|
||||
void write_rows( const View& view
|
||||
, const jpeg_quality::type quality
|
||||
, const jpeg_dct_method::type dct_method
|
||||
)
|
||||
{
|
||||
std::vector< typename View::value_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( _mark )) { raise_error(); }
|
||||
|
||||
typedef typename channel_type< typename View::value_type >::type channel_t;
|
||||
|
||||
_cinfo.image_width = JDIMENSION( view.width() );
|
||||
_cinfo.image_height = JDIMENSION( view.height() );
|
||||
_cinfo.input_components = num_channels<View>::value;
|
||||
_cinfo.in_color_space = detail::jpeg_write_support< channel_t
|
||||
, typename color_space_type< View >::type
|
||||
>::_color_space;
|
||||
|
||||
jpeg_set_defaults( &_cinfo );
|
||||
jpeg_set_quality ( &_cinfo
|
||||
, quality
|
||||
, TRUE
|
||||
);
|
||||
|
||||
// Needs to be done after jpeg_set_defaults() since it's overridding this value back to slow.
|
||||
_cinfo.dct_method = dct_method;
|
||||
|
||||
jpeg_start_compress( &_cinfo
|
||||
, 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->_cinfo
|
||||
, &row_addr
|
||||
, 1
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
struct gil_jpeg_destination_mgr
|
||||
{
|
||||
jpeg_destination_mgr _jdest;
|
||||
writer<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->out.write( dest->_this->buffer
|
||||
, buffer_size
|
||||
);
|
||||
|
||||
writer<Device,jpeg_tag>::init_device( cinfo );
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void close_device( jpeg_compress_struct* cinfo )
|
||||
{
|
||||
writer<Device,jpeg_tag>::empty_buffer( cinfo );
|
||||
|
||||
gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
|
||||
|
||||
dest->_this->out.flush();
|
||||
}
|
||||
|
||||
void raise_error()
|
||||
{
|
||||
io_error( "Cannot write jpeg file." );
|
||||
}
|
||||
|
||||
static void error_exit( j_common_ptr cinfo )
|
||||
{
|
||||
writer< Device, jpeg_tag >* mgr = reinterpret_cast< writer< Device, jpeg_tag >* >( cinfo->client_data );
|
||||
|
||||
longjmp( mgr->_mark, 1 );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Device &out;
|
||||
|
||||
jpeg_compress_struct _cinfo;
|
||||
|
||||
gil_jpeg_destination_mgr _dest;
|
||||
|
||||
static const unsigned int buffer_size = 1024;
|
||||
JOCTET buffer[buffer_size];
|
||||
};
|
||||
|
||||
struct jpeg_write_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply
|
||||
: public is_write_supported< typename get_pixel_type< View >::type
|
||||
, jpeg_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
// unary application
|
||||
template <typename Types, typename Tag, typename Bits, typename Op>
|
||||
typename Op::result_type GIL_FORCEINLINE apply_operation_basec( const Bits& bits
|
||||
, std::size_t index
|
||||
, const image_write_info< Tag >& info
|
||||
, Op op
|
||||
)
|
||||
{
|
||||
return detail::apply_operation_fwd_fn<mpl::size<Types>::value>().template applyc<Types>( bits
|
||||
, index
|
||||
, op
|
||||
);
|
||||
}
|
||||
|
||||
// unary application
|
||||
template< typename Types
|
||||
, typename Info
|
||||
, typename Bits
|
||||
, typename Op
|
||||
>
|
||||
typename Op::result_type GIL_FORCEINLINE apply_operation_base( Bits& bits
|
||||
, std::size_t index
|
||||
, const Info& info
|
||||
, Op op
|
||||
)
|
||||
{
|
||||
return detail::apply_operation_fwd_fn< mpl::size< Types >::value>().template apply< Types
|
||||
>( bits
|
||||
, index
|
||||
, info
|
||||
, op
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// \ingroup Variant
|
||||
/// \brief Invokes a generic constant operation (represented as a binary function object) on two variants
|
||||
template< typename Types1
|
||||
, typename Info
|
||||
, typename BinaryOp
|
||||
>
|
||||
GIL_FORCEINLINE
|
||||
typename BinaryOp::result_type apply_operation( const variant< Types1 >& arg1
|
||||
, const Info& info
|
||||
, BinaryOp op
|
||||
)
|
||||
{
|
||||
typename variant< Types1 >::base_t bits = arg1.bits();
|
||||
|
||||
return apply_operation_base< Types1
|
||||
, image_write_info< jpeg_tag >
|
||||
>( bits
|
||||
, arg1.index()
|
||||
, info
|
||||
, op
|
||||
);
|
||||
}
|
||||
|
||||
template< typename Device >
|
||||
class dynamic_image_writer< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
: public writer< Device
|
||||
, jpeg_tag
|
||||
>
|
||||
{
|
||||
typedef writer< Device
|
||||
, jpeg_tag
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_writer( Device& file )
|
||||
: parent_t( file )
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
{
|
||||
dynamic_io_fnobj< jpeg_write_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( views, op );
|
||||
}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view < Views >& views
|
||||
, const image_write_info< jpeg_tag >& info
|
||||
)
|
||||
{
|
||||
dynamic_io_fnobj< jpeg_write_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( views, info, op );
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_IO_WRITE_HPP
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_DETAIL_PNG_IO_BASE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_PNG_IO_BASE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/gil/extension/io_new/png_tags.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/reader_base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/typedefs.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template<typename Device>
|
||||
class png_io_base
|
||||
{
|
||||
public:
|
||||
png_io_base( Device & io_dev )
|
||||
: _io_dev(io_dev)
|
||||
{}
|
||||
|
||||
protected:
|
||||
Device & _io_dev;
|
||||
|
||||
void check() const
|
||||
{
|
||||
byte_t buf[PNG_BYTES_TO_CHECK];
|
||||
|
||||
io_error_if(_io_dev.read(buf, PNG_BYTES_TO_CHECK) != PNG_BYTES_TO_CHECK,
|
||||
"png_check_validity: failed to read image");
|
||||
|
||||
io_error_if(png_sig_cmp(png_bytep(buf), png_size_t(0), PNG_BYTES_TO_CHECK)!=0,
|
||||
"png_check_validity: invalid png image");
|
||||
}
|
||||
|
||||
static void read_data( png_structp png_ptr
|
||||
, png_bytep data
|
||||
, png_size_t length
|
||||
)
|
||||
{
|
||||
static_cast<Device*>(png_get_io_ptr(png_ptr) )->read( data
|
||||
, length );
|
||||
}
|
||||
|
||||
static void write_data( png_structp png_ptr
|
||||
, png_bytep data
|
||||
, png_size_t length
|
||||
)
|
||||
{
|
||||
static_cast<Device*>( png_get_io_ptr( png_ptr ))->write( data
|
||||
, length );
|
||||
}
|
||||
|
||||
static void flush( png_structp png_ptr )
|
||||
{
|
||||
static_cast<Device*>(png_get_io_ptr(png_ptr) )->flush();
|
||||
}
|
||||
|
||||
|
||||
static int read_user_chunk_callback( png_struct* /* png_ptr */
|
||||
, png_unknown_chunkp /* chunk */
|
||||
)
|
||||
{
|
||||
// @todo
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void read_row_callback( png_structp /* png_ptr */
|
||||
, png_uint_32 /* row_number */
|
||||
, int /* pass */
|
||||
)
|
||||
{
|
||||
// @todo
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_PNG_IO_BASE_HPP
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_PNG_IO_IS_ALLOWED_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNG_IO_IS_ALLOWED_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< png_tag >& info
|
||||
, mpl::true_ // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
typedef typename get_pixel_type< View >::type pixel_t;
|
||||
|
||||
typedef typename channel_traits<
|
||||
typename element_type< pixel_t >::type >::value_type channel_t;
|
||||
|
||||
const png_num_channels::type dst_num_channels = num_channels< pixel_t >::value;
|
||||
const png_bitdepth::type dst_bit_depth = detail::unsigned_integral_num_bits< channel_t >::value;
|
||||
|
||||
return dst_num_channels == info._num_channels
|
||||
&& dst_bit_depth == info._bit_depth;
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< png_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNG_IO_IS_ALLOWED_HPP
|
||||
@@ -0,0 +1,923 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_DETAIL_PNG_IO_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_PNG_IO_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/gil/extension/io_new/png_tags.hpp>
|
||||
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/reader_base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/conversion_policies.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/typedefs.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/row_buffer_helper.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "is_allowed.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
class reader< Device
|
||||
, png_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
: public png_io_base< Device >
|
||||
, public reader_base< png_tag
|
||||
, ConversionPolicy >
|
||||
{
|
||||
public:
|
||||
|
||||
reader( Device& io_dev
|
||||
, const image_read_settings< png_tag >& settings
|
||||
)
|
||||
: png_io_base< Device >( io_dev )
|
||||
, reader_base< png_tag
|
||||
, ConversionPolicy >( settings )
|
||||
, _png_ptr ( NULL )
|
||||
, _info_ptr( NULL )
|
||||
{
|
||||
this->check();
|
||||
init_reader();
|
||||
}
|
||||
|
||||
reader( Device& io_dev
|
||||
, const typename ConversionPolicy::color_converter_type& cc
|
||||
, const image_read_settings< png_tag >& settings
|
||||
)
|
||||
: png_io_base< Device >( io_dev )
|
||||
, reader_base< png_tag
|
||||
, ConversionPolicy >( cc
|
||||
, settings
|
||||
)
|
||||
, _png_ptr ( 0 )
|
||||
, _info_ptr( 0 )
|
||||
{
|
||||
this->check();
|
||||
init_reader();
|
||||
}
|
||||
|
||||
~reader()
|
||||
{
|
||||
png_destroy_read_struct( &_png_ptr
|
||||
, &_info_ptr
|
||||
, NULL
|
||||
);
|
||||
}
|
||||
|
||||
image_read_info<png_tag> get_info() const
|
||||
{
|
||||
image_read_info< png_tag > ret;
|
||||
|
||||
// get PNG_IHDR chunk information from png_info structure
|
||||
png_get_IHDR( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._width
|
||||
, &ret._height
|
||||
, &ret._bit_depth
|
||||
, &ret._color_type
|
||||
, &ret._interlace_method
|
||||
, &ret._compression_method
|
||||
, &ret._filter_method
|
||||
);
|
||||
|
||||
// get number of color channels in image
|
||||
ret._num_channels = png_get_channels( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
// Get CIE chromacities and referenced white point for given image
|
||||
if( this->_settings._read_cie_chromacities )
|
||||
{
|
||||
ret._valid_cie_colors = png_get_cHRM( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._white_x, &ret._white_y
|
||||
, &ret._red_x, &ret._red_y
|
||||
, &ret._green_x, &ret._green_y
|
||||
, &ret._blue_x, &ret._blue_y
|
||||
);
|
||||
}
|
||||
|
||||
// get the gamma value for given image
|
||||
if( this->_settings._read_file_gamma )
|
||||
{
|
||||
ret._valid_file_gamma = png_get_gAMA( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._file_gamma
|
||||
);
|
||||
if( ret._valid_file_gamma == false )
|
||||
{
|
||||
ret._file_gamma = 1.0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
// Get CIE chromacities and referenced white point for given image
|
||||
if( this->_settings._read_cie_chromacities )
|
||||
{
|
||||
ret._valid_cie_colors = png_get_cHRM_fixed( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._white_x, &ret._white_y
|
||||
, &ret._red_x, &ret._red_y
|
||||
, &ret._green_x, &ret._green_y
|
||||
, &ret._blue_x, &ret._blue_y
|
||||
);
|
||||
}
|
||||
|
||||
// get the gamma value for given image
|
||||
if( this->_settings._read_file_gamma )
|
||||
{
|
||||
ret._valid_file_gamma = png_get_gAMA_fixed( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._file_gamma
|
||||
);
|
||||
|
||||
if( ret._valid_file_gamma == false )
|
||||
{
|
||||
ret._file_gamma = 1;
|
||||
}
|
||||
}
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
// get the embedded ICC profile data for given image
|
||||
if( this->_settings._read_icc_profile )
|
||||
{
|
||||
png_charp icc_name = png_charp( NULL );
|
||||
png_charp profile = png_charp( NULL );
|
||||
|
||||
ret._valid_icc_profile = png_get_iCCP( _png_ptr
|
||||
, _info_ptr
|
||||
, &icc_name
|
||||
, &ret._iccp_compression_type
|
||||
, &profile
|
||||
, &ret._profile_length
|
||||
);
|
||||
if( icc_name )
|
||||
{
|
||||
ret._icc_name.append( icc_name
|
||||
, std::strlen( icc_name )
|
||||
);
|
||||
}
|
||||
|
||||
if( ret._profile_length > 0 )
|
||||
{
|
||||
ret._profile.append( profile
|
||||
, ret._profile_length
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// get the rendering intent for given image
|
||||
if( this->_settings._read_intent )
|
||||
{
|
||||
ret._valid_intent = png_get_sRGB( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._intent
|
||||
);
|
||||
}
|
||||
|
||||
// get image palette information from png_info structure
|
||||
if( this->_settings._read_palette )
|
||||
{
|
||||
png_colorp palette = png_colorp( NULL );
|
||||
|
||||
ret._valid_palette = png_get_PLTE( _png_ptr
|
||||
, _info_ptr
|
||||
, &palette
|
||||
, &ret._num_palette
|
||||
);
|
||||
|
||||
if( ret._num_palette > 0 )
|
||||
{
|
||||
ret._palette.resize( ret._num_palette );
|
||||
std::copy( palette
|
||||
, palette + ret._num_palette
|
||||
, &ret._palette.front()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// get background color for given image
|
||||
if( this->_settings._read_background )
|
||||
{
|
||||
png_color_16p background = png_color_16p( NULL );
|
||||
|
||||
ret._valid_background = png_get_bKGD( _png_ptr
|
||||
, _info_ptr
|
||||
, &background
|
||||
);
|
||||
if( background )
|
||||
{
|
||||
ret._background = *background;
|
||||
}
|
||||
}
|
||||
|
||||
// get the histogram for given image
|
||||
if( this->_settings._read_histogram )
|
||||
{
|
||||
png_uint_16p histogram = png_uint_16p( NULL );
|
||||
|
||||
ret._valid_histogram = png_get_hIST( _png_ptr
|
||||
, _info_ptr
|
||||
, &histogram
|
||||
);
|
||||
|
||||
if( histogram )
|
||||
{
|
||||
// the number of values is set by the number of colors inside
|
||||
// the palette.
|
||||
if( this->_settings._read_palette == false )
|
||||
{
|
||||
png_colorp palette = png_colorp( NULL );
|
||||
png_get_PLTE( _png_ptr
|
||||
, _info_ptr
|
||||
, &palette
|
||||
, &ret._num_palette
|
||||
);
|
||||
}
|
||||
|
||||
std::copy( histogram
|
||||
, histogram + ret._num_palette
|
||||
, &ret._histogram.front()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// get screen offsets for the given image
|
||||
if( this->_settings._read_screen_offsets )
|
||||
{
|
||||
ret._valid_offset = png_get_oFFs( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._offset_x
|
||||
, &ret._offset_y
|
||||
, &ret._off_unit_type
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// get pixel calibration settings
|
||||
if( this->_settings._read_pixel_calibration )
|
||||
{
|
||||
png_charp purpose = png_charp ( NULL );
|
||||
png_charp units = png_charp ( NULL );
|
||||
png_charpp params = png_charpp( NULL );
|
||||
|
||||
ret._valid_pixel_calibration = png_get_pCAL( _png_ptr
|
||||
, _info_ptr
|
||||
, &purpose
|
||||
, &ret._X0
|
||||
, &ret._X1
|
||||
, &ret._cal_type
|
||||
, &ret._num_params
|
||||
, &units
|
||||
, ¶ms
|
||||
);
|
||||
if( purpose )
|
||||
{
|
||||
ret._purpose.append( purpose
|
||||
, std::strlen( purpose )
|
||||
);
|
||||
}
|
||||
|
||||
if( units )
|
||||
{
|
||||
ret._units.append( units
|
||||
, std::strlen( units )
|
||||
);
|
||||
}
|
||||
|
||||
if( ret._num_params > 0 )
|
||||
{
|
||||
ret._params.resize( ret._num_params );
|
||||
|
||||
for( png_CAL_nparam::type i = 0
|
||||
; i < ret._num_params
|
||||
; ++i
|
||||
)
|
||||
{
|
||||
ret._params[i].append( params[i]
|
||||
, std::strlen( params[i] )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get the physical resolution for given image
|
||||
if( this->_settings._read_physical_resolution )
|
||||
{
|
||||
ret._valid_resolution = png_get_pHYs( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._res_x
|
||||
, &ret._res_y
|
||||
, &ret._phy_unit_type
|
||||
);
|
||||
}
|
||||
|
||||
// get number of significant bits for each color channel
|
||||
if( this->_settings._read_number_of_significant_bits )
|
||||
{
|
||||
png_color_8p sig_bits = png_color_8p( NULL );
|
||||
|
||||
ret._valid_significant_bits = png_get_sBIT( _png_ptr
|
||||
, _info_ptr
|
||||
, &sig_bits
|
||||
);
|
||||
|
||||
// @todo Is there one or more colors?
|
||||
if( sig_bits )
|
||||
{
|
||||
ret._sig_bits = *sig_bits;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
// get physical scale settings
|
||||
if( this->_settings._read_scale_factors )
|
||||
{
|
||||
ret._valid_scale_factors = png_get_sCAL( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._scale_unit
|
||||
, &ret._scale_width
|
||||
, &ret._scale_height
|
||||
);
|
||||
}
|
||||
#else
|
||||
#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
|
||||
if( this->_settings._read_scale_factors )
|
||||
{
|
||||
png_charp scale_width, scale_height;
|
||||
|
||||
if( ret._valid_scale_factors = png_get_sCAL_s( _png_ptr
|
||||
, _info_ptr
|
||||
, &ret._scale_unit
|
||||
, &scale_width
|
||||
, &scale_height
|
||||
)
|
||||
)
|
||||
{
|
||||
if( scale_width )
|
||||
{
|
||||
ret._scale_width.append( scale_width
|
||||
, std::strlen( scale_width )
|
||||
);
|
||||
}
|
||||
|
||||
if( scale_height )
|
||||
{
|
||||
ret._scale_height.append( scale_height
|
||||
, std::strlen( scale_height )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
// get comments information from png_info structure
|
||||
if( this->_settings._read_comments )
|
||||
{
|
||||
png_textp text = png_textp( NULL );
|
||||
|
||||
ret._valid_text = png_get_text( _png_ptr
|
||||
, _info_ptr
|
||||
, &text
|
||||
, &ret._num_text
|
||||
);
|
||||
|
||||
if( ret._num_text > 0 )
|
||||
{
|
||||
ret._text.resize( ret._num_text );
|
||||
|
||||
for( png_num_text::type i = 0
|
||||
; i < ret._num_text
|
||||
; ++i
|
||||
)
|
||||
{
|
||||
ret._text[i]._compression = text[i].compression;
|
||||
ret._text[i]._key.append( text[i].key
|
||||
, std::strlen( text[i].key )
|
||||
);
|
||||
|
||||
ret._text[i]._text.append( text[i].text
|
||||
, std::strlen( text[i].text )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get last modification time for the image
|
||||
if( this->_settings._read_last_modification_time )
|
||||
{
|
||||
png_timep mod_time = png_timep( NULL );
|
||||
ret._valid_modification_time = png_get_tIME( _png_ptr
|
||||
, _info_ptr
|
||||
, &mod_time
|
||||
);
|
||||
ret._mod_time = *mod_time;
|
||||
}
|
||||
|
||||
// get transparency data for images
|
||||
if( this->_settings._read_transparency_data )
|
||||
{
|
||||
png_bytep trans = png_bytep ( NULL );
|
||||
png_color_16p trans_values = png_color_16p( NULL );
|
||||
|
||||
ret._valid_transparency_factors = png_get_tRNS( _png_ptr
|
||||
, _info_ptr
|
||||
, &trans
|
||||
, &ret._num_trans
|
||||
, &trans_values
|
||||
);
|
||||
|
||||
if( trans )
|
||||
{
|
||||
//@todo What to do, here? How do I know the length of the "trans" array?
|
||||
}
|
||||
|
||||
if( ret._num_trans )
|
||||
{
|
||||
ret._trans_values.resize( ret._num_trans );
|
||||
std::copy( trans_values
|
||||
, trans_values + ret._num_trans
|
||||
, &ret._trans_values.front()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// @todo One day!
|
||||
/*
|
||||
if( false )
|
||||
{
|
||||
png_unknown_chunkp unknowns = png_unknown_chunkp( NULL );
|
||||
int num_unknowns = static_cast< int >( png_get_unknown_chunks( _png_ptr
|
||||
, _info_ptr
|
||||
, &unknowns
|
||||
)
|
||||
);
|
||||
}
|
||||
*/
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void apply( const View& view )
|
||||
{
|
||||
// The info structures are filled at this point.
|
||||
|
||||
// Now it's time for some transformations.
|
||||
|
||||
if( little_endian() )
|
||||
{
|
||||
if( this->_info._bit_depth == 16 )
|
||||
{
|
||||
// Swap bytes of 16 bit files to least significant byte first.
|
||||
png_set_swap( _png_ptr );
|
||||
}
|
||||
|
||||
if( this->_info._bit_depth < 8 )
|
||||
{
|
||||
// swap bits of 1, 2, 4 bit packed pixel formats
|
||||
png_set_packswap( _png_ptr );
|
||||
}
|
||||
}
|
||||
|
||||
if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE )
|
||||
{
|
||||
png_set_palette_to_rgb( _png_ptr );
|
||||
}
|
||||
|
||||
if( this->_info._num_trans > 0 )
|
||||
{
|
||||
png_set_tRNS_to_alpha( _png_ptr );
|
||||
}
|
||||
|
||||
// Tell libpng to handle the gamma conversion for you. The final call
|
||||
// is a good guess for PC generated images, but it should be configurable
|
||||
// by the user at run time by the user. It is strongly suggested that
|
||||
// your application support gamma correction.
|
||||
if( this->_settings._apply_screen_gamma )
|
||||
{
|
||||
// png_set_gamma will change the image data!
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
png_set_gamma( _png_ptr
|
||||
, this->_settings._screen_gamma
|
||||
, this->_info._file_gamma
|
||||
);
|
||||
#else
|
||||
png_set_gamma( _png_ptr
|
||||
, this->_settings._screen_gamma
|
||||
, this->_info._file_gamma
|
||||
);
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
}
|
||||
|
||||
// Turn on interlace handling. REQUIRED if you are not using
|
||||
// png_read_image(). To see how to handle interlacing passes,
|
||||
// see the png_read_row() method below:
|
||||
_number_passes = png_set_interlace_handling( _png_ptr );
|
||||
|
||||
|
||||
// The above transformation might have changed the bit_depth and color type.
|
||||
png_read_update_info( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
|
||||
this->_info._bit_depth = png_get_bit_depth( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
|
||||
this->_info._num_channels = png_get_channels( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
|
||||
this->_info._color_type = png_get_color_type( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
|
||||
switch( this->_info._color_type )
|
||||
{
|
||||
case PNG_COLOR_TYPE_GRAY:
|
||||
{
|
||||
switch( this->_info._bit_depth )
|
||||
{
|
||||
case 1: read_rows< gray1_image_t::view_t::reference >( view ); break;
|
||||
case 2: read_rows< gray2_image_t::view_t::reference >( view ); break;
|
||||
case 4: read_rows< gray4_image_t::view_t::reference >( view ); break;
|
||||
case 8: read_rows< gray8_pixel_t >( view ); break;
|
||||
case 16: read_rows< gray16_pixel_t >( view ); break;
|
||||
default: io_error( "png_reader::read_data(): unknown combination of color type and bit depth" );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PNG_COLOR_TYPE_GA:
|
||||
{
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
switch( this->_info._bit_depth )
|
||||
{
|
||||
case 8: read_rows< gray_alpha8_pixel_t > ( view ); break;
|
||||
case 16: read_rows< gray_alpha16_pixel_t >( view ); break;
|
||||
default: io_error( "png_reader::read_data(): unknown combination of color type and bit depth" );
|
||||
}
|
||||
#else
|
||||
io_error( "gray_alpha isn't enabled. Use ENABLE_GRAY_ALPHA when building application." );
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
|
||||
break;
|
||||
}
|
||||
case PNG_COLOR_TYPE_RGB:
|
||||
{
|
||||
switch( this->_info._bit_depth )
|
||||
{
|
||||
case 8: read_rows< rgb8_pixel_t > ( view ); break;
|
||||
case 16: read_rows< rgb16_pixel_t >( view ); break;
|
||||
default: io_error( "png_reader::read_data(): unknown combination of color type and bit depth" );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case PNG_COLOR_TYPE_RGBA:
|
||||
{
|
||||
switch( this->_info._bit_depth )
|
||||
{
|
||||
case 8: read_rows< rgba8_pixel_t > ( view ); break;
|
||||
case 16: read_rows< rgba16_pixel_t >( view ); break;
|
||||
default: io_error( "png_reader_color_convert::read_data(): unknown combination of color type and bit depth" );
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: io_error( "png_reader_color_convert::read_data(): unknown color type" );
|
||||
}
|
||||
|
||||
// read rest of file, and get additional chunks in info_ptr
|
||||
png_read_end( _png_ptr
|
||||
, NULL
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
template< typename ImagePixel
|
||||
, typename View
|
||||
>
|
||||
void read_rows( const View& view )
|
||||
{
|
||||
typedef row_buffer_helper_view< ImagePixel > row_buffer_helper_t;
|
||||
|
||||
typedef typename row_buffer_helper_t::buffer_t buffer_t;
|
||||
typedef typename row_buffer_helper_t::iterator_t it_t;
|
||||
|
||||
typedef typename is_same< ConversionPolicy
|
||||
, read_and_no_convert
|
||||
>::type is_read_and_convert_t;
|
||||
|
||||
io_error_if( !is_allowed< View >( this->_info
|
||||
, is_read_and_convert_t()
|
||||
)
|
||||
, "Image types aren't compatible."
|
||||
);
|
||||
|
||||
std::size_t rowbytes = png_get_rowbytes( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
|
||||
row_buffer_helper_t buffer( rowbytes
|
||||
, true
|
||||
);
|
||||
|
||||
png_bytep row_ptr = (png_bytep)( &( buffer.data()[0]));
|
||||
|
||||
for( std::size_t pass = 0; pass < _number_passes; pass++ )
|
||||
{
|
||||
if( pass == _number_passes - 1 )
|
||||
{
|
||||
// skip lines if necessary
|
||||
for( std::ptrdiff_t y = 0; y < this->_settings._top_left.y; ++y )
|
||||
{
|
||||
// Read the image using the "sparkle" effect.
|
||||
png_read_rows( _png_ptr
|
||||
, &row_ptr
|
||||
, NULL
|
||||
, 1
|
||||
);
|
||||
}
|
||||
|
||||
for( std::ptrdiff_t y = 0
|
||||
; y < this->_settings._dim.y
|
||||
; ++y
|
||||
)
|
||||
{
|
||||
// Read the image using the "sparkle" effect.
|
||||
png_read_rows( _png_ptr
|
||||
, &row_ptr
|
||||
, NULL
|
||||
, 1
|
||||
);
|
||||
|
||||
it_t first = buffer.begin() + this->_settings._top_left.x;
|
||||
it_t last = first + this->_settings._dim.x; // one after last element
|
||||
|
||||
this->_cc_policy.read( first
|
||||
, last
|
||||
, view.row_begin( y ));
|
||||
}
|
||||
|
||||
// Read the rest of the image. libpng needs that.
|
||||
std::ptrdiff_t remaining_rows = static_cast< std::ptrdiff_t >( this->_info._height )
|
||||
- this->_settings._top_left.y
|
||||
- this->_settings._dim.y;
|
||||
for( std::ptrdiff_t y = 0
|
||||
; y < remaining_rows
|
||||
; ++y
|
||||
)
|
||||
{
|
||||
// Read the image using the "sparkle" effect.
|
||||
png_read_rows( _png_ptr
|
||||
, &row_ptr
|
||||
, NULL
|
||||
, 1
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( int y = 0; y < view.height(); ++y )
|
||||
{
|
||||
// Read the image using the "sparkle" effect.
|
||||
png_read_rows( _png_ptr
|
||||
, &row_ptr
|
||||
, NULL
|
||||
, 1
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void init_reader()
|
||||
{
|
||||
// Create and initialize the png_struct with the desired error handler
|
||||
// functions. If you want to use the default stderr and longjump method,
|
||||
// you can supply NULL for the last three parameters. We also supply the
|
||||
// the compiler header file version, so that we know if the application
|
||||
// was compiled with a compatible version of the library. REQUIRED
|
||||
_png_ptr = png_create_read_struct( PNG_LIBPNG_VER_STRING
|
||||
, NULL // user_error_ptr
|
||||
, NULL // user_error_fn
|
||||
, NULL // user_warning_fn
|
||||
);
|
||||
|
||||
io_error_if( _png_ptr == NULL
|
||||
, "png_reader: fail to call png_create_write_struct()"
|
||||
);
|
||||
|
||||
png_uint_32 user_chunk_data[4];
|
||||
user_chunk_data[0] = 0;
|
||||
user_chunk_data[1] = 0;
|
||||
user_chunk_data[2] = 0;
|
||||
user_chunk_data[3] = 0;
|
||||
png_set_read_user_chunk_fn( _png_ptr
|
||||
, user_chunk_data
|
||||
, png_io_base< Device >::read_user_chunk_callback
|
||||
);
|
||||
|
||||
// Allocate/initialize the memory for image information. REQUIRED.
|
||||
_info_ptr = png_create_info_struct( _png_ptr );
|
||||
|
||||
if( _info_ptr == NULL )
|
||||
{
|
||||
png_destroy_read_struct( &_png_ptr
|
||||
, NULL
|
||||
, NULL
|
||||
);
|
||||
|
||||
io_error( "png_reader: fail to call png_create_info_struct()" );
|
||||
}
|
||||
|
||||
// Set error handling if you are using the setjmp/longjmp method (this is
|
||||
// the normal method of doing things with libpng). REQUIRED unless you
|
||||
// set up your own error handlers in the png_create_read_struct() earlier.
|
||||
if( setjmp( png_jmpbuf( _png_ptr )))
|
||||
{
|
||||
//free all of the memory associated with the png_ptr and info_ptr
|
||||
png_destroy_read_struct( &_png_ptr
|
||||
, &_info_ptr
|
||||
, NULL
|
||||
);
|
||||
|
||||
io_error( "png is invalid" );
|
||||
}
|
||||
|
||||
png_set_read_fn( _png_ptr
|
||||
, static_cast< png_voidp >( &this->_io_dev )
|
||||
, png_io_base< Device >::read_data
|
||||
);
|
||||
|
||||
// Set up a callback function that will be
|
||||
// called after each row has been read, which you can use to control
|
||||
// a progress meter or the like.
|
||||
png_set_read_status_fn( _png_ptr
|
||||
, png_io_base< Device >::read_row_callback
|
||||
);
|
||||
|
||||
// Set up a callback which implements user defined transformation.
|
||||
// @todo
|
||||
png_set_read_user_transform_fn( _png_ptr
|
||||
, png_user_transform_ptr( NULL )
|
||||
);
|
||||
|
||||
png_set_keep_unknown_chunks( _png_ptr
|
||||
, PNG_HANDLE_CHUNK_ALWAYS
|
||||
, NULL
|
||||
, 0
|
||||
);
|
||||
|
||||
|
||||
// Make sure we read the signature.
|
||||
// @todo make it an option
|
||||
png_set_sig_bytes( _png_ptr
|
||||
, PNG_BYTES_TO_CHECK
|
||||
);
|
||||
|
||||
// The call to png_read_info() gives us all of the information from the
|
||||
// PNG file before the first IDAT (image data chunk). REQUIRED
|
||||
png_read_info( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
png_structp _png_ptr;
|
||||
png_infop _info_ptr;
|
||||
|
||||
std::size_t _number_passes;
|
||||
};
|
||||
|
||||
|
||||
struct png_type_format_checker
|
||||
{
|
||||
png_type_format_checker( png_bitdepth::type bit_depth
|
||||
, png_color_type::type color_type
|
||||
)
|
||||
: _bit_depth ( bit_depth )
|
||||
, _color_type( color_type )
|
||||
{}
|
||||
|
||||
template< typename Image >
|
||||
bool apply()
|
||||
{
|
||||
typedef is_read_supported< typename get_pixel_type< typename Image::view_t >::type
|
||||
, png_tag
|
||||
> is_supported_t;
|
||||
|
||||
return is_supported_t::_bit_depth == _bit_depth
|
||||
&& is_supported_t::_color_type == _color_type;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
png_bitdepth::type _bit_depth;
|
||||
png_color_type::type _color_type;
|
||||
};
|
||||
|
||||
struct png_read_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply : public is_read_supported< typename get_pixel_type< View >::type
|
||||
, png_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device
|
||||
>
|
||||
class dynamic_image_reader< Device
|
||||
, png_tag
|
||||
>
|
||||
: public reader< Device
|
||||
, png_tag
|
||||
, detail::read_and_no_convert
|
||||
>
|
||||
{
|
||||
typedef reader< Device
|
||||
, png_tag
|
||||
, detail::read_and_no_convert
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_reader( Device& device
|
||||
, const image_read_settings< png_tag >& settings
|
||||
)
|
||||
: parent_t( device
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
{
|
||||
png_type_format_checker format_checker( this->_info._bit_depth
|
||||
, this->_info._color_type
|
||||
);
|
||||
|
||||
if( !construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
io_error( "No matching image type between those of the given any_image and that of the file" );
|
||||
}
|
||||
else
|
||||
{
|
||||
init_image( images
|
||||
, this->_info
|
||||
);
|
||||
|
||||
dynamic_io_fnobj< png_read_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_PNG_IO_READ_HPP
|
||||
@@ -0,0 +1,366 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_PNG_SUPPORTED_TYPES_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNG_SUPPORTED_TYPES_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
#include <boost/gil/extension/toolbox/gray_alpha.hpp>
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
static const size_t PNG_BYTES_TO_CHECK = 4;
|
||||
|
||||
// Read support
|
||||
template< png_bitdepth::type BitDepth
|
||||
, png_color_type::type ColorType
|
||||
>
|
||||
struct png_rw_support_base
|
||||
{
|
||||
static const png_bitdepth::type _bit_depth = BitDepth;
|
||||
static const png_color_type::type _color_type = ColorType;
|
||||
};
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct png_read_support : read_support_false
|
||||
, png_rw_support_base< 1
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
> {};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_read_support< packed_dynamic_channel_reference< BitField
|
||||
, 1
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 1
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
> {};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_read_support< packed_dynamic_channel_reference< BitField
|
||||
, 2
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 2
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
> {};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_read_support< packed_dynamic_channel_reference< BitField
|
||||
, 4
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 4
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
> {};
|
||||
|
||||
template<>
|
||||
struct png_read_support< bits8
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
> {};
|
||||
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
template<>
|
||||
struct png_read_support< bits8
|
||||
, gray_alpha_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_GA
|
||||
> {};
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
template<>
|
||||
struct png_read_support< bits8
|
||||
, rgb_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_RGB
|
||||
> {};
|
||||
|
||||
template<>
|
||||
struct png_read_support< bits8
|
||||
, rgba_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_RGBA
|
||||
> {};
|
||||
|
||||
template<>
|
||||
struct png_read_support< bits16
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
> {};
|
||||
|
||||
template<>
|
||||
struct png_read_support< bits16
|
||||
, rgb_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_RGB
|
||||
> {};
|
||||
|
||||
template<>
|
||||
struct png_read_support< bits16
|
||||
, rgba_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_RGBA
|
||||
> {};
|
||||
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
template<>
|
||||
struct png_read_support< bits16
|
||||
, gray_alpha_t
|
||||
> : read_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_GA
|
||||
> {};
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
// Write support
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct png_write_support : write_support_false
|
||||
, png_rw_support_base< 1
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
> {};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_write_support< packed_dynamic_channel_reference< BitField
|
||||
, 1
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 1
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_write_support< packed_dynamic_channel_reference< BitField
|
||||
, 1
|
||||
, Mutable
|
||||
> const
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 1
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_write_support< packed_dynamic_channel_reference< BitField
|
||||
, 2
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 2
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_write_support< packed_dynamic_channel_reference< BitField
|
||||
, 2
|
||||
, Mutable
|
||||
> const
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 2
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_write_support< packed_dynamic_channel_reference< BitField
|
||||
, 4
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 4
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
template< typename BitField
|
||||
, bool Mutable
|
||||
>
|
||||
struct png_write_support< packed_dynamic_channel_reference< BitField
|
||||
, 4
|
||||
, Mutable
|
||||
> const
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 4
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct png_write_support< bits8
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
template<>
|
||||
struct png_write_support< bits8
|
||||
, gray_alpha_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_GA
|
||||
>
|
||||
{};
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
template<>
|
||||
struct png_write_support< bits8
|
||||
, rgb_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_RGB
|
||||
>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct png_write_support< bits8
|
||||
, rgba_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 8
|
||||
, PNG_COLOR_TYPE_RGBA
|
||||
>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct png_write_support< bits16
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_GRAY
|
||||
>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct png_write_support< bits16
|
||||
, rgb_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_RGB
|
||||
>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct png_write_support< bits16
|
||||
, rgba_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_RGBA
|
||||
>
|
||||
{};
|
||||
|
||||
#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
template<>
|
||||
struct png_write_support< bits16
|
||||
, gray_alpha_t
|
||||
> : write_support_true
|
||||
, png_rw_support_base< 16
|
||||
, PNG_COLOR_TYPE_GA
|
||||
>
|
||||
{};
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_read_supported< Pixel
|
||||
, png_tag
|
||||
>
|
||||
: mpl::bool_< detail::png_read_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
typedef detail::png_read_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
> parent_t;
|
||||
|
||||
static const png_bitdepth::type _bit_depth = parent_t::_bit_depth;
|
||||
static const png_color_type::type _color_type = parent_t::_color_type;
|
||||
};
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_write_supported< Pixel
|
||||
, png_tag
|
||||
>
|
||||
: mpl::bool_< detail::png_write_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
typedef detail::png_write_support< typename channel_type< Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
> parent_t;
|
||||
|
||||
static const png_bitdepth::type _bit_depth = parent_t::_bit_depth;
|
||||
static const png_color_type::type _color_type = parent_t::_color_type;
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNG_SUPPORTED_TYPES_HPP
|
||||
@@ -0,0 +1,521 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_DETAIL_PNG_IO_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_PNG_IO_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include <png.h>
|
||||
}
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/typedefs.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/row_buffer_helper.hpp>
|
||||
|
||||
#include "base.hpp"
|
||||
#include "supported_types.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template<typename Device>
|
||||
class writer< Device
|
||||
, png_tag
|
||||
> : png_io_base< Device >
|
||||
{
|
||||
|
||||
public:
|
||||
|
||||
writer( Device& io_dev )
|
||||
: png_io_base< Device >( io_dev )
|
||||
, _png_ptr ( NULL )
|
||||
, _info_ptr( NULL )
|
||||
{
|
||||
// Create and initialize the png_struct with the desired error handler
|
||||
// functions. If you want to use the default stderr and longjump method,
|
||||
// you can supply NULL for the last three parameters. We also check that
|
||||
// the library version is compatible with the one used at compile time,
|
||||
// in case we are using dynamically linked libraries. REQUIRED.
|
||||
_png_ptr = png_create_write_struct( PNG_LIBPNG_VER_STRING
|
||||
, NULL // user_error_ptr
|
||||
, NULL // user_error_fn
|
||||
, NULL // user_warning_fn
|
||||
);
|
||||
|
||||
io_error_if( _png_ptr == NULL
|
||||
, "png_writer: fail to call png_create_write_struct()"
|
||||
);
|
||||
|
||||
// Allocate/initialize the image information data. REQUIRED
|
||||
_info_ptr = png_create_info_struct( _png_ptr );
|
||||
|
||||
if( _info_ptr == NULL )
|
||||
{
|
||||
png_destroy_write_struct( &_png_ptr
|
||||
, NULL
|
||||
);
|
||||
|
||||
io_error( "png_writer: fail to call png_create_info_struct()" );
|
||||
}
|
||||
|
||||
// Set error handling. REQUIRED if you aren't supplying your own
|
||||
// error handling functions in the png_create_write_struct() call.
|
||||
if( setjmp( png_jmpbuf( _png_ptr )))
|
||||
{
|
||||
//free all of the memory associated with the png_ptr and info_ptr
|
||||
png_destroy_write_struct( &_png_ptr
|
||||
, &_info_ptr
|
||||
);
|
||||
|
||||
io_error( "png_writer: fail to call setjmp()" );
|
||||
}
|
||||
|
||||
this->init_io( _png_ptr );
|
||||
}
|
||||
|
||||
~writer()
|
||||
{
|
||||
png_destroy_write_struct( &_png_ptr
|
||||
, &_info_ptr
|
||||
);
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void apply( const View& view )
|
||||
{
|
||||
apply( view, image_write_info< png_tag >() );
|
||||
}
|
||||
|
||||
template <typename View>
|
||||
void apply( const View& view
|
||||
, const image_write_info< png_tag >& info
|
||||
)
|
||||
{
|
||||
typedef png_write_support< typename channel_type < typename get_pixel_type< View >::type >::type
|
||||
, typename color_space_type< View >::type
|
||||
> png_rw_info_t;
|
||||
|
||||
io_error_if( view.width() == 0 && view.height() == 0
|
||||
, "png format cannot handle empty views."
|
||||
);
|
||||
|
||||
// Set the image information here. Width and height are up to 2^31,
|
||||
// bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
|
||||
// the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
|
||||
// PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
|
||||
// or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
|
||||
// PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
|
||||
// currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
|
||||
png_set_IHDR( _png_ptr
|
||||
, _info_ptr
|
||||
, static_cast< png_image_width::type >( view.width() )
|
||||
, static_cast< png_image_height::type >( view.height() )
|
||||
, static_cast< png_bitdepth::type >( png_rw_info_t::_bit_depth )
|
||||
, static_cast< png_color_type::type >( png_rw_info_t::_color_type )
|
||||
, info._interlace_method
|
||||
, info._compression_method
|
||||
, info._filter_method
|
||||
);
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
if( info._valid_cie_colors )
|
||||
{
|
||||
png_set_cHRM( _png_ptr
|
||||
, _info_ptr
|
||||
, info._white_x
|
||||
, info._white_y
|
||||
, info._red_x
|
||||
, info._red_y
|
||||
, info._green_x
|
||||
, info._green_y
|
||||
, info._blue_x
|
||||
, info._blue_y
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_file_gamma )
|
||||
{
|
||||
png_set_gAMA( _png_ptr
|
||||
, _info_ptr
|
||||
, info._gamma
|
||||
);
|
||||
}
|
||||
#else
|
||||
if( info._valid_cie_colors )
|
||||
{
|
||||
png_set_cHRM_fixed( _png_ptr
|
||||
, _info_ptr
|
||||
, info._white_x
|
||||
, info._white_y
|
||||
, info._red_x
|
||||
, info._red_y
|
||||
, info._green_x
|
||||
, info._green_y
|
||||
, info._blue_x
|
||||
, info._blue_y
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_file_gamma )
|
||||
{
|
||||
png_set_gAMA_fixed( _png_ptr
|
||||
, _info_ptr
|
||||
, info._file_gamma
|
||||
);
|
||||
}
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
if( info._valid_icc_profile )
|
||||
{
|
||||
png_set_iCCP( _png_ptr
|
||||
, _info_ptr
|
||||
, const_cast< png_charp >( info._icc_name.c_str() )
|
||||
, info._iccp_compression_type
|
||||
, const_cast< png_charp >( info._profile.c_str() )
|
||||
, info._profile_length
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_intent )
|
||||
{
|
||||
png_set_sRGB( _png_ptr
|
||||
, _info_ptr
|
||||
, info._intent
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_palette )
|
||||
{
|
||||
png_set_PLTE( _png_ptr
|
||||
, _info_ptr
|
||||
, const_cast< png_colorp >( &info._palette.front() )
|
||||
, info._num_palette
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_background )
|
||||
{
|
||||
png_set_bKGD( _png_ptr
|
||||
, _info_ptr
|
||||
, const_cast< png_color_16p >( &info._background )
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_histogram )
|
||||
{
|
||||
png_set_hIST( _png_ptr
|
||||
, _info_ptr
|
||||
, const_cast< png_uint_16p >( &info._histogram.front() )
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_offset )
|
||||
{
|
||||
png_set_oFFs( _png_ptr
|
||||
, _info_ptr
|
||||
, info._offset_x
|
||||
, info._offset_y
|
||||
, info._off_unit_type
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_pixel_calibration )
|
||||
{
|
||||
std::vector< const char* > params( info._num_params );
|
||||
for( std::size_t i = 0; i < params.size(); ++i )
|
||||
{
|
||||
params[i] = info._params[ i ].c_str();
|
||||
}
|
||||
|
||||
png_set_pCAL( _png_ptr
|
||||
, _info_ptr
|
||||
, const_cast< png_charp >( info._purpose.c_str() )
|
||||
, info._X0
|
||||
, info._X1
|
||||
, info._cal_type
|
||||
, info._num_params
|
||||
, const_cast< png_charp >( info._units.c_str() )
|
||||
, const_cast< png_charpp >( ¶ms.front() )
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_resolution )
|
||||
{
|
||||
png_set_pHYs( _png_ptr
|
||||
, _info_ptr
|
||||
, info._res_x
|
||||
, info._res_y
|
||||
, info._phy_unit_type
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_significant_bits )
|
||||
{
|
||||
png_set_sBIT( _png_ptr
|
||||
, _info_ptr
|
||||
, const_cast< png_color_8p >( &info._sig_bits )
|
||||
);
|
||||
}
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
if( info._valid_scale_factors )
|
||||
{
|
||||
png_set_sCAL( _png_ptr
|
||||
, _info_ptr
|
||||
, info._scale_unit
|
||||
, info._scale_width
|
||||
, info._scale_height
|
||||
);
|
||||
}
|
||||
#else
|
||||
#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
|
||||
|
||||
if( info._valid_scale_factors )
|
||||
{
|
||||
png_set_sCAL_s( _png_ptr
|
||||
, _info_ptr
|
||||
, _scale_unit
|
||||
, const_cast< png_charp >( _scale_width.c_str() )
|
||||
, const_cast< png_charp >( _scale_height.c_str() )
|
||||
);
|
||||
}
|
||||
#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
|
||||
if( info._valid_text )
|
||||
{
|
||||
std::vector< png_text > texts( info._num_text );
|
||||
for( std::size_t i = 0; i < texts.size(); ++i )
|
||||
{
|
||||
png_text pt;
|
||||
pt.compression = info._text[i]._compression;
|
||||
pt.key = const_cast< png_charp >( info._text[i]._key.c_str() );
|
||||
pt.text = const_cast< png_charp >( info._text[i]._text.c_str() );
|
||||
pt.text_length = info._text[i]._text.length();
|
||||
|
||||
texts[i] = pt;
|
||||
}
|
||||
|
||||
png_set_text( _png_ptr
|
||||
, _info_ptr
|
||||
, &texts.front()
|
||||
, info._num_text
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_modification_time )
|
||||
{
|
||||
png_set_tIME( _png_ptr
|
||||
, _info_ptr
|
||||
, const_cast< png_timep >( &info._mod_time )
|
||||
);
|
||||
}
|
||||
|
||||
if( info._valid_transparency_factors )
|
||||
{
|
||||
int sample_max = ( 1 << info._bit_depth );
|
||||
|
||||
/* libpng doesn't reject a tRNS chunk with out-of-range samples */
|
||||
if( !( ( info._color_type == PNG_COLOR_TYPE_GRAY
|
||||
&& (int) info._trans_values[0].gray > sample_max
|
||||
)
|
||||
|| ( info._color_type == PNG_COLOR_TYPE_RGB
|
||||
&&( (int) info._trans_values[0].red > sample_max
|
||||
|| (int) info._trans_values[0].green > sample_max
|
||||
|| (int) info._trans_values[0].blue > sample_max
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
{
|
||||
//@todo Fix that once reading transparency values works
|
||||
/*
|
||||
png_set_tRNS( _png_ptr
|
||||
, _info_ptr
|
||||
, trans
|
||||
, num_trans
|
||||
, trans_values
|
||||
);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
png_write_info( _png_ptr
|
||||
,_info_ptr
|
||||
);
|
||||
|
||||
write_view( view
|
||||
, typename is_bit_aligned< View >::type()
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename View>
|
||||
void write_view( const View& view
|
||||
, mpl::false_ // is bit aligned
|
||||
)
|
||||
{
|
||||
typedef typename get_pixel_type< View >::type pixel_t;
|
||||
|
||||
typedef png_write_support< typename channel_type < pixel_t >::type
|
||||
, typename color_space_type< pixel_t >::type
|
||||
> png_rw_info;
|
||||
|
||||
if( little_endian() )
|
||||
{
|
||||
if( png_rw_info::_bit_depth == 16 )
|
||||
{
|
||||
png_set_swap( _png_ptr );
|
||||
}
|
||||
|
||||
if( png_rw_info::_bit_depth < 8 )
|
||||
{
|
||||
png_set_packswap( _png_ptr );
|
||||
}
|
||||
}
|
||||
|
||||
row_buffer_helper_view< View > row_buffer( view.width()
|
||||
, false
|
||||
);
|
||||
|
||||
for( int y = 0; y != view.height(); ++ y)
|
||||
{
|
||||
std::copy( view.row_begin( y )
|
||||
, view.row_end ( y )
|
||||
, row_buffer.begin()
|
||||
);
|
||||
|
||||
png_write_row( _png_ptr
|
||||
, reinterpret_cast< png_bytep >( row_buffer.data() )
|
||||
);
|
||||
}
|
||||
|
||||
png_write_end( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void write_view( const View& view
|
||||
, mpl::true_ // is bit aligned
|
||||
)
|
||||
{
|
||||
typedef png_write_support< typename kth_semantic_element_type< typename View::value_type
|
||||
, 0
|
||||
>::type
|
||||
, typename color_space_type<View>::type
|
||||
> png_rw_info;
|
||||
|
||||
if (little_endian() )
|
||||
{
|
||||
if( png_rw_info::_bit_depth == 16 )
|
||||
{
|
||||
png_set_swap( _png_ptr );
|
||||
}
|
||||
|
||||
if( png_rw_info::_bit_depth < 8 )
|
||||
{
|
||||
png_set_packswap( _png_ptr );
|
||||
}
|
||||
}
|
||||
|
||||
row_buffer_helper_view< View > row_buffer( view.width()
|
||||
, false
|
||||
);
|
||||
|
||||
for( int y = 0; y != view.height(); ++y )
|
||||
{
|
||||
std::copy( view.row_begin( y )
|
||||
, view.row_end ( y )
|
||||
, row_buffer.begin()
|
||||
);
|
||||
|
||||
png_write_row( _png_ptr
|
||||
, reinterpret_cast< png_bytep >( row_buffer.data() )
|
||||
);
|
||||
}
|
||||
|
||||
png_free_data( _png_ptr
|
||||
, _info_ptr
|
||||
, PNG_FREE_UNKN
|
||||
, -1
|
||||
);
|
||||
|
||||
png_write_end( _png_ptr
|
||||
, _info_ptr
|
||||
);
|
||||
}
|
||||
|
||||
void init_io( png_structp png_ptr )
|
||||
{
|
||||
png_set_write_fn( png_ptr
|
||||
, static_cast< void* > ( &this->_io_dev )
|
||||
, static_cast< png_rw_ptr > ( &png_io_base<Device>::write_data )
|
||||
, static_cast< png_flush_ptr >( &png_io_base<Device>::flush )
|
||||
);
|
||||
}
|
||||
|
||||
png_structp _png_ptr;
|
||||
png_infop _info_ptr;
|
||||
};
|
||||
|
||||
struct png_write_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply
|
||||
: public is_write_supported< typename get_pixel_type< View >::type
|
||||
, png_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device >
|
||||
class dynamic_image_writer< Device
|
||||
, png_tag
|
||||
>
|
||||
: public writer< Device
|
||||
, png_tag
|
||||
>
|
||||
{
|
||||
typedef writer< Device
|
||||
, png_tag
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_writer( Device& file )
|
||||
: parent_t( file )
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
{
|
||||
dynamic_io_fnobj< png_write_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( views, op );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_PNG_IO_WRITE_HPP
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
Copyright 2009 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_IO_IS_ALLOWED_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_IO_IS_ALLOWED_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< pnm_tag >& info
|
||||
, mpl::true_ // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
pnm_image_type::type asc_type = is_read_supported< typename get_pixel_type< View >::type
|
||||
, pnm_tag
|
||||
>::_asc_type;
|
||||
|
||||
pnm_image_type::type bin_type = is_read_supported< typename get_pixel_type< View >::type
|
||||
, pnm_tag
|
||||
>::_bin_type;
|
||||
if( info._type == pnm_image_type::mono_asc_t::value )
|
||||
{
|
||||
// ascii mono images are read gray8_image_t
|
||||
return ( asc_type == pnm_image_type::gray_asc_t::value );
|
||||
}
|
||||
|
||||
|
||||
return ( asc_type == info._type
|
||||
|| bin_type == info._type
|
||||
);
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< pnm_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_IO_IS_ALLOWED_HPP
|
||||
@@ -0,0 +1,498 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_IO_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_IO_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <vector>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
#include <boost/gil/extension/io_new/pnm_tags.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/conversion_policies.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/row_buffer_helper.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/bit_operations.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/reader_base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/typedefs.hpp>
|
||||
|
||||
#include "is_allowed.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename View, typename T >
|
||||
struct calc_pitch {};
|
||||
|
||||
template< typename View >
|
||||
struct calc_pitch< View, mpl::false_ >
|
||||
{
|
||||
static uint32_t do_it( uint32_t width ) { return width * num_channels< View >::value; }
|
||||
};
|
||||
|
||||
template< typename View >
|
||||
struct calc_pitch< View, mpl::true_ >
|
||||
{
|
||||
static uint32_t do_it( uint32_t width ) { return ( width + 7 ) >> 3; }
|
||||
};
|
||||
|
||||
|
||||
template< typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
class reader< Device
|
||||
, pnm_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
: public reader_base< pnm_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
{
|
||||
private:
|
||||
|
||||
typedef typename ConversionPolicy::color_converter_type cc_t;
|
||||
|
||||
public:
|
||||
reader( Device& device
|
||||
, const image_read_settings< pnm_tag >& settings
|
||||
)
|
||||
: reader_base< pnm_tag
|
||||
, ConversionPolicy >( settings )
|
||||
, _io_dev( device )
|
||||
{}
|
||||
|
||||
reader( Device& device
|
||||
, const cc_t& cc
|
||||
, const image_read_settings< pnm_tag >& settings
|
||||
)
|
||||
: reader_base< pnm_tag
|
||||
, ConversionPolicy >( cc
|
||||
, settings
|
||||
)
|
||||
, _io_dev( device )
|
||||
{}
|
||||
|
||||
image_read_info<pnm_tag> get_info()
|
||||
{
|
||||
image_read_info<pnm_tag> ret;
|
||||
|
||||
// read signature
|
||||
io_error_if( read_char() != 'P', "Invalid PNM signature" );
|
||||
|
||||
ret._type = read_char() - '0';
|
||||
|
||||
io_error_if( ret._type < pnm_image_type::mono_asc_t::value || ret._type > pnm_image_type::color_bin_t::value
|
||||
, "Invalid PNM file (supports P1 to P6)"
|
||||
);
|
||||
|
||||
ret._width = read_int();
|
||||
ret._height = read_int();
|
||||
|
||||
if( ret._type == pnm_image_type::mono_asc_t::value || ret._type == pnm_image_type::mono_bin_t::value )
|
||||
{
|
||||
ret._max_value = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret._max_value = read_int();
|
||||
|
||||
io_error_if( ret._max_value > 255
|
||||
, "Unsupported PNM format (supports maximum value 255)"
|
||||
);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
|
||||
typedef typename is_same< ConversionPolicy
|
||||
, read_and_no_convert
|
||||
>::type is_read_and_convert_t;
|
||||
|
||||
io_error_if( !is_allowed< View >( this->_info
|
||||
, is_read_and_convert_t()
|
||||
)
|
||||
, "Image types aren't compatible."
|
||||
);
|
||||
|
||||
switch( this->_info._type )
|
||||
{
|
||||
// reading mono text is reading grayscale but with only two values
|
||||
case pnm_image_type::mono_asc_t::value: { read_text_data< gray8_view_t >( view ); break; }
|
||||
case pnm_image_type::gray_asc_t::value: { read_text_data< gray8_view_t >( view ); break; }
|
||||
case pnm_image_type::color_asc_t::value: { read_text_data< rgb8_view_t >( view ); break; }
|
||||
|
||||
case pnm_image_type::mono_bin_t::value: { read_bin_data< gray1_image_t::view_t >( view ); break; }
|
||||
case pnm_image_type::gray_bin_t::value: { read_bin_data< gray8_view_t >( view ); break; }
|
||||
case pnm_image_type::color_bin_t::value: { read_bin_data< rgb8_view_t >( view ); break; }
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template< typename View_Src
|
||||
, typename View_Dst
|
||||
>
|
||||
void read_text_data( const View_Dst& dst )
|
||||
{
|
||||
typedef typename View_Dst::y_coord_t y_t;
|
||||
|
||||
uint32_t pitch = this->_info._width * num_channels< View_Src >::value;
|
||||
|
||||
byte_vector_t row( pitch );
|
||||
|
||||
//Skip scanlines if necessary.
|
||||
for( int y = 0; y < this->_settings._top_left.y; ++y )
|
||||
{
|
||||
read_text_row< View_Src >( dst, row, pitch, y, false );
|
||||
}
|
||||
|
||||
for( y_t y = 0; y < dst.height(); ++y )
|
||||
{
|
||||
read_text_row< View_Src >( dst, row, pitch, y, true );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View_Src
|
||||
, typename View_Dst
|
||||
>
|
||||
void read_text_row( const View_Dst& dst
|
||||
, byte_vector_t& row
|
||||
, uint32_t pitch
|
||||
, typename View_Dst::y_coord_t y
|
||||
, bool process
|
||||
)
|
||||
{
|
||||
static char buf[16];
|
||||
|
||||
View_Src src = interleaved_view( this->_info._width
|
||||
, 1
|
||||
, (typename View_Src::value_type*) &row.front()
|
||||
, pitch
|
||||
);
|
||||
|
||||
for( uint32_t x = 0; x < pitch; ++x )
|
||||
{
|
||||
for( uint32_t k = 0; ; )
|
||||
{
|
||||
int ch = _io_dev.getc_unchecked();
|
||||
|
||||
if( isdigit( ch ))
|
||||
{
|
||||
buf[ k++ ] = static_cast< char >( ch );
|
||||
}
|
||||
else if( k )
|
||||
{
|
||||
buf[ k ] = 0;
|
||||
break;
|
||||
}
|
||||
else if( ch == EOF || !isspace( ch ))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( process )
|
||||
{
|
||||
int value = atoi( buf );
|
||||
|
||||
if( this->_info._max_value == 1 )
|
||||
{
|
||||
typedef typename channel_type< typename get_pixel_type< View_Dst >::type >::type channel_t;
|
||||
|
||||
// for pnm format 0 is white
|
||||
row[x] = ( value != 0 )
|
||||
? typename channel_traits< channel_t >::value_type( 0 )
|
||||
: channel_traits< channel_t >::max_value();
|
||||
}
|
||||
else
|
||||
{
|
||||
row[x] = static_cast< byte_t >( value );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( process )
|
||||
{
|
||||
// We are reading a gray1_image like a gray8_image but the two pixel_t
|
||||
// aren't compatible. Though, read_and_no_convert::read(...) wont work.
|
||||
copy_data< View_Dst
|
||||
, View_Src >( dst
|
||||
, src
|
||||
, y
|
||||
, typename is_same< View_Dst
|
||||
, gray1_image_t::view_t
|
||||
>::type()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View_Dst
|
||||
, typename View_Src
|
||||
>
|
||||
void copy_data( const View_Dst& dst
|
||||
, const View_Src& src
|
||||
, typename View_Dst::y_coord_t y
|
||||
, mpl::true_ // is gray1_view
|
||||
)
|
||||
{
|
||||
if( this->_info._max_value == 1 )
|
||||
{
|
||||
typename View_Dst::x_iterator it = dst.row_begin( y );
|
||||
|
||||
for( typename View_Dst::x_coord_t x = 0
|
||||
; x < dst.width()
|
||||
; ++x
|
||||
)
|
||||
{
|
||||
it[x] = src[x];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_data( dst
|
||||
, src
|
||||
, y
|
||||
, mpl::false_()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View_Dst
|
||||
, typename View_Src
|
||||
>
|
||||
void copy_data( const View_Dst& view
|
||||
, const View_Src& src
|
||||
, typename View_Dst::y_coord_t y
|
||||
, mpl::false_ // is gray1_view
|
||||
)
|
||||
{
|
||||
typename View_Src::x_iterator beg = src.row_begin( 0 ) + this->_settings._top_left.x;
|
||||
typename View_Src::x_iterator end = beg + this->_settings._dim.x;
|
||||
|
||||
this->_cc_policy.read( beg
|
||||
, end
|
||||
, view.row_begin( y )
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template< typename View_Src
|
||||
, typename View_Dst
|
||||
>
|
||||
void read_bin_data( const View_Dst& view )
|
||||
{
|
||||
typedef typename View_Dst::y_coord_t y_t;
|
||||
typedef typename is_bit_aligned<
|
||||
typename View_Src::value_type >::type is_bit_aligned_t;
|
||||
|
||||
uint32_t pitch = calc_pitch< View_Src, is_bit_aligned_t >::do_it( this->_info._width );
|
||||
|
||||
typedef row_buffer_helper_view< View_Src > rh_t;
|
||||
rh_t rh( pitch, true );
|
||||
|
||||
typename rh_t::iterator_t beg = rh.begin() + this->_settings._top_left.x;
|
||||
typename rh_t::iterator_t end = beg + this->_settings._dim.x;
|
||||
|
||||
// For bit_aligned images we need to negate all bytes in the row_buffer
|
||||
// to make sure that 0 is black and 255 is white.
|
||||
negate_bits< typename rh_t::buffer_t
|
||||
, is_bit_aligned_t
|
||||
> neg;
|
||||
|
||||
swap_half_bytes< typename rh_t::buffer_t
|
||||
, is_bit_aligned_t
|
||||
> swhb;
|
||||
|
||||
//Skip scanlines if necessary.
|
||||
for( y_t y = 0; y < this->_settings._top_left.y; ++y )
|
||||
{
|
||||
_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
|
||||
, pitch
|
||||
);
|
||||
}
|
||||
|
||||
for( y_t y = 0; y < view.height(); ++y )
|
||||
{
|
||||
_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
|
||||
, pitch
|
||||
);
|
||||
|
||||
neg( rh.buffer() );
|
||||
swhb( rh.buffer() );
|
||||
|
||||
this->_cc_policy.read( beg
|
||||
, end
|
||||
, view.row_begin( y )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// Read a character and skip a comment if necessary.
|
||||
char read_char()
|
||||
{
|
||||
char ch;
|
||||
|
||||
if(( ch = _io_dev.getc() ) == '#' )
|
||||
{
|
||||
// skip comment to EOL
|
||||
do
|
||||
{
|
||||
ch = _io_dev.getc();
|
||||
}
|
||||
while (ch != '\n' && ch != '\r');
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
unsigned int read_int()
|
||||
{
|
||||
char ch;
|
||||
|
||||
// skip whitespaces, tabs, and new lines
|
||||
do
|
||||
{
|
||||
ch = read_char();
|
||||
}
|
||||
while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
|
||||
|
||||
if( ch < '0' || ch > '9' )
|
||||
{
|
||||
io_error( "Unexpected characters reading decimal digits" );
|
||||
}
|
||||
|
||||
unsigned val = 0;
|
||||
|
||||
do
|
||||
{
|
||||
unsigned dig = ch - '0';
|
||||
|
||||
if( val > INT_MAX / 10 - dig )
|
||||
{
|
||||
io_error( "Integer too large" );
|
||||
}
|
||||
|
||||
val = val * 10 + dig;
|
||||
|
||||
ch = read_char();
|
||||
}
|
||||
while( '0' <= ch && ch <= '9' );
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Device& _io_dev;
|
||||
};
|
||||
|
||||
struct pnm_type_format_checker
|
||||
{
|
||||
pnm_type_format_checker( pnm_image_type::type type )
|
||||
: _type( type )
|
||||
{}
|
||||
|
||||
template< typename Image >
|
||||
bool apply()
|
||||
{
|
||||
typedef is_read_supported< typename get_pixel_type< typename Image::view_t >::type
|
||||
, pnm_tag
|
||||
> is_supported_t;
|
||||
|
||||
return is_supported_t::_asc_type == _type
|
||||
|| is_supported_t::_bin_type == _type;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
pnm_image_type::type _type;
|
||||
};
|
||||
|
||||
struct pnm_read_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply : public is_read_supported< typename get_pixel_type< View >::type
|
||||
, pnm_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device
|
||||
>
|
||||
class dynamic_image_reader< Device
|
||||
, pnm_tag
|
||||
>
|
||||
: public reader< Device
|
||||
, pnm_tag
|
||||
, detail::read_and_no_convert
|
||||
>
|
||||
{
|
||||
typedef reader< Device
|
||||
, pnm_tag
|
||||
, detail::read_and_no_convert
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_reader( Device& device
|
||||
, const image_read_settings< pnm_tag >& settings
|
||||
)
|
||||
: parent_t( device
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
{
|
||||
pnm_type_format_checker format_checker( this->_info._type );
|
||||
|
||||
if( !construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
io_error( "No matching image type between those of the given any_image and that of the file" );
|
||||
}
|
||||
else
|
||||
{
|
||||
init_image( images
|
||||
, this->_info
|
||||
);
|
||||
|
||||
dynamic_io_fnobj< pnm_read_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_IO_READ_HPP
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_SUPPORTED_TYPES_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_SUPPORTED_TYPES_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/gil/color_base.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
// Read Support
|
||||
|
||||
template< pnm_image_type::type ASCII_Type
|
||||
, pnm_image_type::type Binary_Type
|
||||
>
|
||||
struct pnm_rw_support_base
|
||||
{
|
||||
static const pnm_image_type::type _asc_type = ASCII_Type;
|
||||
static const pnm_image_type::type _bin_type = Binary_Type;
|
||||
};
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct pnm_read_support : read_support_false
|
||||
, pnm_rw_support_base< 0
|
||||
, 0
|
||||
> {};
|
||||
|
||||
template< typename BitField, bool Mutable >
|
||||
struct pnm_read_support< packed_dynamic_channel_reference< BitField
|
||||
, 1
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, pnm_rw_support_base< pnm_image_type::mono_asc_t::value
|
||||
, pnm_image_type::mono_bin_t::value
|
||||
> {};
|
||||
|
||||
template<>
|
||||
struct pnm_read_support< bits8
|
||||
, gray_t
|
||||
> : read_support_true
|
||||
, pnm_rw_support_base< pnm_image_type::gray_asc_t::value
|
||||
, pnm_image_type::gray_bin_t::value
|
||||
> {};
|
||||
|
||||
|
||||
template<>
|
||||
struct pnm_read_support< bits8
|
||||
, rgb_t
|
||||
> : read_support_true
|
||||
, pnm_rw_support_base< pnm_image_type::color_asc_t::value
|
||||
, pnm_image_type::color_bin_t::value
|
||||
> {};
|
||||
|
||||
// Write support
|
||||
|
||||
template< typename Channel
|
||||
, typename ColorSpace
|
||||
>
|
||||
struct pnm_write_support : write_support_false
|
||||
{};
|
||||
|
||||
template< typename BitField, bool Mutable >
|
||||
struct pnm_write_support< packed_dynamic_channel_reference< BitField
|
||||
, 1
|
||||
, Mutable
|
||||
>
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, pnm_rw_support_base< pnm_image_type::mono_asc_t::value
|
||||
, pnm_image_type::mono_bin_t::value
|
||||
> {};
|
||||
|
||||
|
||||
template<>
|
||||
struct pnm_write_support< bits8
|
||||
, gray_t
|
||||
> : write_support_true
|
||||
, pnm_rw_support_base< pnm_image_type::gray_asc_t::value
|
||||
, pnm_image_type::gray_bin_t::value
|
||||
> {};
|
||||
|
||||
|
||||
template<>
|
||||
struct pnm_write_support< bits8
|
||||
, rgb_t
|
||||
> : write_support_true
|
||||
, pnm_rw_support_base< pnm_image_type::color_asc_t::value
|
||||
, pnm_image_type::color_bin_t::value
|
||||
> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_read_supported< Pixel
|
||||
, pnm_tag
|
||||
>
|
||||
: mpl::bool_< detail::pnm_read_support< typename channel_type < Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
typedef detail::pnm_read_support< typename channel_type < Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
> parent_t;
|
||||
|
||||
static const pnm_image_type::type _asc_type = parent_t::_asc_type;
|
||||
static const pnm_image_type::type _bin_type = parent_t::_bin_type;
|
||||
};
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_write_supported< Pixel
|
||||
, pnm_tag
|
||||
>
|
||||
: mpl::bool_< detail::pnm_write_support< typename channel_type < Pixel >::type
|
||||
, typename color_space_type< Pixel >::type
|
||||
>::is_supported
|
||||
> {};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_SUPPORTED_TYPES_HPP
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_IO_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_IO_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/pnm_tags.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename Device >
|
||||
class writer< Device
|
||||
, pnm_tag
|
||||
>
|
||||
{
|
||||
typedef image_write_info< pnm_tag > info_t;
|
||||
|
||||
public:
|
||||
|
||||
writer( Device & file )
|
||||
: _out( file )
|
||||
{
|
||||
}
|
||||
|
||||
~writer()
|
||||
{
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
info_t info;
|
||||
|
||||
apply( view
|
||||
, info );
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view
|
||||
, const info_t& /* info */
|
||||
)
|
||||
{
|
||||
typedef typename get_pixel_type< View >::type pixel_t;
|
||||
|
||||
std::size_t width = view.width();
|
||||
std::size_t height = view.height();
|
||||
|
||||
std::size_t chn = num_channels< View >::value;
|
||||
std::size_t pitch = chn * width;
|
||||
|
||||
unsigned int type;
|
||||
if( num_channels< View >::value == 1 )
|
||||
{
|
||||
if( is_bit_aligned< pixel_t >::value )
|
||||
{
|
||||
type = pnm_image_type::mono_bin_t::value;
|
||||
}
|
||||
else
|
||||
{
|
||||
type = pnm_image_type::gray_bin_t::value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
type = pnm_image_type::color_bin_t::value;
|
||||
}
|
||||
|
||||
// write header
|
||||
|
||||
// Add a white space at each string so read_int() can decide when a numbers ends.
|
||||
|
||||
std::string str( "P" );
|
||||
str += lexical_cast< std::string >( type ) + std::string( " " );
|
||||
_out.print_line( str );
|
||||
|
||||
str.clear();
|
||||
str += lexical_cast< std::string >( width ) + std::string( " " );
|
||||
_out.print_line( str );
|
||||
|
||||
str.clear();
|
||||
str += lexical_cast< std::string >( height ) + std::string( " " );
|
||||
_out.print_line( str );
|
||||
|
||||
if( type != pnm_image_type::mono_bin_t::value )
|
||||
{
|
||||
_out.print_line( "255 ");
|
||||
}
|
||||
|
||||
// write data
|
||||
write_data( view
|
||||
, pitch
|
||||
, typename is_bit_aligned< pixel_t >::type()
|
||||
);
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void write_data( const View& src
|
||||
, std::size_t pitch
|
||||
, const mpl::true_& // bit_aligned
|
||||
)
|
||||
{
|
||||
BOOST_STATIC_ASSERT(( is_same< View
|
||||
, typename gray1_image_t::view_t
|
||||
>::value
|
||||
));
|
||||
|
||||
byte_vector_t row( pitch / 8 );
|
||||
|
||||
typedef typename View::x_iterator x_it_t;
|
||||
x_it_t row_it = x_it_t( &( *row.begin() ));
|
||||
|
||||
negate_bits< byte_vector_t
|
||||
, mpl::true_
|
||||
> neg;
|
||||
|
||||
mirror_bits< byte_vector_t
|
||||
, mpl::true_
|
||||
> mirror;
|
||||
|
||||
|
||||
for( typename View::y_coord_t y = 0; y < src.height(); ++y )
|
||||
{
|
||||
std::copy( src.row_begin( y )
|
||||
, src.row_end( y )
|
||||
, row_it
|
||||
);
|
||||
|
||||
mirror( row );
|
||||
neg ( row );
|
||||
|
||||
_out.write( &row.front()
|
||||
, pitch / 8
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void write_data( const View& src
|
||||
, std::size_t pitch
|
||||
, const mpl::false_& // bit_aligned
|
||||
)
|
||||
{
|
||||
byte_vector_t buf( pitch );
|
||||
|
||||
typedef typename View::value_type pixel_t;
|
||||
typedef typename view_type_from_pixel< pixel_t >::type view_t;
|
||||
|
||||
view_t row = interleaved_view( src.width()
|
||||
, 1
|
||||
, reinterpret_cast< pixel_t* >( &buf.front() )
|
||||
, pitch
|
||||
);
|
||||
|
||||
for( typename View::y_coord_t y = 0
|
||||
; y < src.height()
|
||||
; ++y
|
||||
)
|
||||
{
|
||||
copy_pixels( subimage_view( src
|
||||
, 0
|
||||
, (int) y
|
||||
, (int) src.width()
|
||||
, 1
|
||||
)
|
||||
, row
|
||||
);
|
||||
|
||||
_out.write( &buf.front(), pitch );
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Device& _out;
|
||||
};
|
||||
|
||||
struct pnm_write_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply
|
||||
: public is_write_supported< typename get_pixel_type< View >::type
|
||||
, pnm_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device >
|
||||
class dynamic_image_writer< Device
|
||||
, pnm_tag
|
||||
>
|
||||
: public writer< Device
|
||||
, pnm_tag
|
||||
>
|
||||
{
|
||||
typedef writer< Device
|
||||
, pnm_tag
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_writer( Device& file )
|
||||
: parent_t( file )
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
{
|
||||
dynamic_io_fnobj< pnm_write_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( views, op );
|
||||
}
|
||||
};
|
||||
|
||||
} // detail
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_IO_WRITE_HPP
|
||||
@@ -0,0 +1,360 @@
|
||||
/*
|
||||
Copyright 2007-2008 Andreas Pokorny, Christian Henning
|
||||
Use, modification and distribution are subject to 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_DETAIL_TIFF_IO_DEVICE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_DETAIL_TIFF_IO_DEVICE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Andreas Pokorny, Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include "tiff.h"
|
||||
#include "tiffio.h"
|
||||
}
|
||||
|
||||
#include "tiffio.hxx"
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/utility/enable_if.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
class tiff_device_base
|
||||
{
|
||||
public:
|
||||
|
||||
tiff_device_base()
|
||||
{}
|
||||
|
||||
tiff_device_base( TIFF* tiff_file )
|
||||
: _tiff_file( tiff_file
|
||||
, TIFFClose )
|
||||
{}
|
||||
|
||||
|
||||
template <typename Property>
|
||||
bool get_property( typename Property::type& value )
|
||||
{
|
||||
if( TIFFGetFieldDefaulted( _tiff_file.get()
|
||||
, Property::tag
|
||||
, &value ) == 1 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <typename Property>
|
||||
inline
|
||||
bool set_property( const typename Property::type& value )
|
||||
{
|
||||
if( TIFFSetField( _tiff_file.get()
|
||||
, Property::tag
|
||||
, value ) == 1 )
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// TIFFIsByteSwapped returns a non-zero value if the image data was in a different
|
||||
// byte-order than the host machine. Zero is returned if the TIFF file and local
|
||||
// host byte-orders are the same.
|
||||
bool are_bytes_swapped()
|
||||
{
|
||||
return ( TIFFIsByteSwapped( _tiff_file.get() )) ? true : false;
|
||||
}
|
||||
|
||||
bool is_tiled() const
|
||||
{
|
||||
return ( TIFFIsTiled( _tiff_file.get() )) ? true : false;
|
||||
}
|
||||
|
||||
unsigned int get_default_strip_size()
|
||||
{
|
||||
return TIFFDefaultStripSize( _tiff_file.get()
|
||||
, 0 );
|
||||
}
|
||||
|
||||
std::size_t get_scanline_size()
|
||||
{
|
||||
return TIFFScanlineSize( _tiff_file.get() );
|
||||
}
|
||||
|
||||
std::size_t get_tile_size()
|
||||
{
|
||||
return TIFFTileSize( _tiff_file.get() );
|
||||
}
|
||||
|
||||
|
||||
int get_field_defaulted( uint16_t*& red
|
||||
, uint16_t*& green
|
||||
, uint16_t*& blue
|
||||
)
|
||||
{
|
||||
return TIFFGetFieldDefaulted( _tiff_file.get()
|
||||
, TIFFTAG_COLORMAP
|
||||
, &red
|
||||
, &green
|
||||
, &blue
|
||||
);
|
||||
}
|
||||
|
||||
template< typename Buffer >
|
||||
void read_scanline( Buffer& buffer
|
||||
, std::ptrdiff_t row
|
||||
, tsample_t plane
|
||||
)
|
||||
{
|
||||
io_error_if( TIFFReadScanline( _tiff_file.get()
|
||||
, reinterpret_cast< tdata_t >( &buffer.front() )
|
||||
, (uint32) row
|
||||
, plane ) == -1
|
||||
, "Read error."
|
||||
);
|
||||
}
|
||||
|
||||
template< typename Buffer >
|
||||
void read_tile( Buffer& buffer
|
||||
, std::ptrdiff_t x
|
||||
, std::ptrdiff_t y
|
||||
, std::ptrdiff_t z
|
||||
, tsample_t plane
|
||||
)
|
||||
{
|
||||
if( TIFFReadTile( _tiff_file.get()
|
||||
, reinterpret_cast< tdata_t >( &buffer.front() )
|
||||
, (uint32) x
|
||||
, (uint32) y
|
||||
, (uint32) z
|
||||
, plane
|
||||
) == -1 )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Read tile error (" << x << "," << y << "," << z << "," << plane << ").";
|
||||
io_error(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Buffer >
|
||||
void write_scaline( Buffer& buffer
|
||||
, uint32 row
|
||||
, tsample_t plane
|
||||
)
|
||||
{
|
||||
io_error_if( TIFFWriteScanline( _tiff_file.get()
|
||||
, &buffer.front()
|
||||
, row
|
||||
, plane
|
||||
) == -1
|
||||
, "Write error"
|
||||
);
|
||||
}
|
||||
|
||||
template< typename Buffer >
|
||||
void write_tile( Buffer& buffer
|
||||
, uint32 x
|
||||
, uint32 y
|
||||
, uint32 z
|
||||
, tsample_t plane
|
||||
)
|
||||
{
|
||||
if( TIFFWriteTile( _tiff_file.get()
|
||||
, &buffer.front()
|
||||
, x
|
||||
, y
|
||||
, z
|
||||
, plane
|
||||
) == -1 )
|
||||
{
|
||||
std::ostringstream oss;
|
||||
oss << "Write tile error (" << x << "," << y << "," << z << "," << plane << ").";
|
||||
io_error(oss.str());
|
||||
}
|
||||
}
|
||||
|
||||
void set_directory( tdir_t directory )
|
||||
{
|
||||
io_error_if( TIFFSetDirectory( _tiff_file.get()
|
||||
, directory
|
||||
) != 1
|
||||
, "Failing to set directory"
|
||||
);
|
||||
}
|
||||
|
||||
// return false if the given tile width or height is not TIFF compliant (multiple of 16) or larger than image size, true otherwise
|
||||
bool check_tile_size( tiff_tile_width::type& width
|
||||
, tiff_tile_length::type& height
|
||||
|
||||
)
|
||||
{
|
||||
bool result = true;
|
||||
uint32 tw = static_cast< uint32 >( width );
|
||||
uint32 th = static_cast< uint32 >( height );
|
||||
|
||||
TIFFDefaultTileSize( _tiff_file.get()
|
||||
, &tw
|
||||
, &th
|
||||
);
|
||||
|
||||
if(width==0 || width%16!=0)
|
||||
{
|
||||
width = tw;
|
||||
result = false;
|
||||
}
|
||||
if(height==0 || height%16!=0)
|
||||
{
|
||||
height = th;
|
||||
result = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
typedef shared_ptr<TIFF> tiff_file_t;
|
||||
tiff_file_t _tiff_file;
|
||||
|
||||
};
|
||||
|
||||
/*!
|
||||
*
|
||||
* file_stream_device specialization for tiff images, which are based on TIFF*.
|
||||
*/
|
||||
template<>
|
||||
class file_stream_device< tiff_tag > : public tiff_device_base
|
||||
{
|
||||
public:
|
||||
|
||||
struct read_tag {};
|
||||
struct write_tag {};
|
||||
|
||||
file_stream_device( std::string const& file_name, read_tag )
|
||||
{
|
||||
TIFF* tiff;
|
||||
|
||||
io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "r" )) == NULL
|
||||
, "file_stream_device: failed to open file" );
|
||||
|
||||
_tiff_file = tiff_file_t( tiff, TIFFClose );
|
||||
}
|
||||
|
||||
file_stream_device( std::string const& file_name, write_tag )
|
||||
{
|
||||
TIFF* tiff;
|
||||
|
||||
io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "w" )) == NULL
|
||||
, "file_stream_device: failed to open file" );
|
||||
|
||||
_tiff_file = tiff_file_t( tiff, TIFFClose );
|
||||
}
|
||||
|
||||
file_stream_device( TIFF* tiff_file )
|
||||
: tiff_device_base( tiff_file )
|
||||
{}
|
||||
};
|
||||
|
||||
/*!
|
||||
*
|
||||
* ostream_device specialization for tiff images.
|
||||
*/
|
||||
template<>
|
||||
class ostream_device< tiff_tag > : public tiff_device_base
|
||||
{
|
||||
public:
|
||||
ostream_device( std::ostream & out )
|
||||
: _out( out )
|
||||
{
|
||||
TIFF* tiff;
|
||||
|
||||
io_error_if( ( tiff = TIFFStreamOpen( ""
|
||||
, &_out
|
||||
)
|
||||
) == NULL
|
||||
, "ostream_device: failed to stream"
|
||||
);
|
||||
|
||||
_tiff_file = tiff_file_t( tiff, TIFFClose );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::ostream& _out;
|
||||
};
|
||||
|
||||
/*!
|
||||
*
|
||||
* ostream_device specialization for tiff images.
|
||||
*/
|
||||
template<>
|
||||
class istream_device< tiff_tag > : public tiff_device_base
|
||||
{
|
||||
public:
|
||||
istream_device( std::istream & in )
|
||||
: _in( in )
|
||||
{
|
||||
TIFF* tiff;
|
||||
|
||||
io_error_if( ( tiff = TIFFStreamOpen( ""
|
||||
, &_in
|
||||
)
|
||||
) == NULL
|
||||
, "istream_device: failed to stream"
|
||||
);
|
||||
|
||||
_tiff_file = tiff_file_t( tiff, TIFFClose );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
std::istream& _in;
|
||||
};
|
||||
|
||||
/*
|
||||
template< typename T, typename D >
|
||||
struct is_adaptable_input_device< tiff_tag, T, D > : mpl::false_{};
|
||||
*/
|
||||
|
||||
template< typename FormatTag >
|
||||
struct is_adaptable_input_device< FormatTag
|
||||
, TIFF*
|
||||
, void
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
typedef file_stream_device< FormatTag > device_type;
|
||||
};
|
||||
|
||||
template< typename FormatTag >
|
||||
struct is_adaptable_output_device< FormatTag
|
||||
, TIFF*
|
||||
, void
|
||||
>
|
||||
: mpl::true_
|
||||
{
|
||||
typedef file_stream_device< FormatTag > device_type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_DETAIL_TIFF_IO_DEVICE_HPP
|
||||
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_TIFF_IO_IS_ALLOWED_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_IO_IS_ALLOWED_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
typedef std::vector< tiff_bits_per_sample::type > channel_sizes_t;
|
||||
|
||||
template< typename Channel >
|
||||
int format_value( mpl::true_ ) // is_bit_aligned
|
||||
{
|
||||
return SAMPLEFORMAT_UINT;
|
||||
}
|
||||
|
||||
template< typename Channel >
|
||||
int format_value( mpl::false_ ) // is_bit_aligned
|
||||
{
|
||||
if( is_unsigned< Channel >::value )
|
||||
{
|
||||
return SAMPLEFORMAT_UINT;
|
||||
}
|
||||
if( is_signed< Channel >::value )
|
||||
{
|
||||
return SAMPLEFORMAT_INT;
|
||||
}
|
||||
else if( is_floating_point< Channel >::value )
|
||||
{
|
||||
return SAMPLEFORMAT_IEEEFP;
|
||||
}
|
||||
|
||||
io_error( "Unkown channel format." );
|
||||
}
|
||||
|
||||
// The following two functions look the same but are different since one is using
|
||||
// a pixel_t as template parameter whereas the other is using reference_t.
|
||||
template< typename View >
|
||||
bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
|
||||
, mpl::false_ // is_bit_aligned
|
||||
, mpl::true_ // is_homogeneous
|
||||
)
|
||||
{
|
||||
typedef typename View::value_type pixel_t;
|
||||
typedef typename channel_traits<
|
||||
typename element_type< pixel_t >::type >::value_type channel_t;
|
||||
|
||||
unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
|
||||
|
||||
return ( s == channel_sizes[0] );
|
||||
}
|
||||
|
||||
|
||||
template< typename View >
|
||||
bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
|
||||
, mpl::true_ // is_bit_aligned
|
||||
, mpl::true_ // is_homogeneous
|
||||
)
|
||||
{
|
||||
typedef typename View::reference ref_t;
|
||||
|
||||
typedef typename channel_traits< typename element_type< ref_t >::type >::value_type channel_t;
|
||||
channel_t c;
|
||||
|
||||
unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
|
||||
|
||||
return ( s == channel_sizes[0] );
|
||||
}
|
||||
|
||||
struct compare_channel_sizes_fn
|
||||
{
|
||||
compare_channel_sizes_fn( uint16_t* a )
|
||||
: _a( a )
|
||||
, _b( true )
|
||||
{}
|
||||
|
||||
template< typename ChannelSize >
|
||||
void operator()( ChannelSize x)
|
||||
{
|
||||
if( x != *_a++ )
|
||||
{
|
||||
_b = false;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t* _a;
|
||||
bool _b;
|
||||
};
|
||||
|
||||
template< typename T >
|
||||
struct channel_sizes_type {};
|
||||
|
||||
template< typename B, typename C, typename L, bool M >
|
||||
struct channel_sizes_type< bit_aligned_pixel_reference< B, C, L, M > > { typedef C type; };
|
||||
|
||||
template< typename B, typename C, typename L, bool M >
|
||||
struct channel_sizes_type< const bit_aligned_pixel_reference< B, C, L, M > > { typedef C type; };
|
||||
|
||||
template< typename View >
|
||||
bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
|
||||
, mpl::true_ // is_bit_aligned
|
||||
, mpl::false_ // is_homogeneous
|
||||
)
|
||||
{
|
||||
// loop through all channels and compare
|
||||
|
||||
typedef typename View::reference ref_t;
|
||||
typedef typename channel_sizes_type< ref_t >::type cs_t;
|
||||
|
||||
compare_channel_sizes_fn fn( &channel_sizes.front() );
|
||||
mpl::for_each< cs_t >( fn );
|
||||
|
||||
return fn._b;
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< tiff_tag >& info
|
||||
, mpl::true_ // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
channel_sizes_t channel_sizes( info._samples_per_pixel
|
||||
, info._bits_per_sample
|
||||
);
|
||||
|
||||
typedef typename get_pixel_type< View >::type pixel_t;
|
||||
typedef typename channel_traits<
|
||||
typename element_type< pixel_t >::type >::value_type channel_t;
|
||||
|
||||
typedef typename num_channels< pixel_t >::value_type num_channel_t;
|
||||
|
||||
const num_channel_t dst_samples_per_pixel = num_channels< pixel_t >::value;
|
||||
const num_channel_t dst_sample_format = format_value< channel_t >( typename is_bit_aligned< pixel_t >::type() );
|
||||
|
||||
return ( dst_samples_per_pixel == info._samples_per_pixel
|
||||
&& compare_channel_sizes< View >( channel_sizes
|
||||
, typename is_bit_aligned< pixel_t >::type()
|
||||
, typename is_homogeneous< pixel_t >::type()
|
||||
)
|
||||
&& dst_sample_format == info._sample_format
|
||||
);
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< tiff_tag >& /* info */
|
||||
, mpl::false_ // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_IO_IS_ALLOWED_HPP
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
Copyright 2009 Christian Henning
|
||||
Use, modification and distribution are subject to 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_TIFF_IO_LOG_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_IO_LOG_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2009 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include "tiffio.h"
|
||||
}
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
class console_log
|
||||
{
|
||||
public:
|
||||
|
||||
console_log()
|
||||
{
|
||||
TIFFSetErrorHandler ( console_log::error );
|
||||
TIFFSetWarningHandler( console_log::warning );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
static void error( const char* /* module */
|
||||
, const char* fmt
|
||||
, va_list ap
|
||||
)
|
||||
{
|
||||
char buf[1000];
|
||||
sprintf(buf, fmt, ap);
|
||||
std::cout << "error: " << buf << std::endl;
|
||||
}
|
||||
|
||||
static void warning( char const* /* module */
|
||||
, char const* fmt
|
||||
, va_list ap
|
||||
)
|
||||
{
|
||||
char buf[1000];
|
||||
sprintf(buf, fmt, ap);
|
||||
std::cout << "warning: " << fmt << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_IO_LOG_HPP
|
||||
@@ -0,0 +1,782 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_TIFF_IO_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_IO_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include "tiff.h"
|
||||
#include "tiffio.h"
|
||||
}
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/static_assert.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/conversion_policies.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/bit_operations.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/row_buffer_helper.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/reader_base.hpp>
|
||||
|
||||
#include "device.hpp"
|
||||
#include "is_allowed.hpp"
|
||||
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template < int K >
|
||||
struct plane_recursion
|
||||
{
|
||||
template< typename View
|
||||
, typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
static
|
||||
void read_plane( const View& dst_view
|
||||
, reader< Device
|
||||
, tiff_tag
|
||||
, ConversionPolicy >* p
|
||||
)
|
||||
{
|
||||
typedef typename kth_channel_view_type< K, View >::type plane_t;
|
||||
plane_t plane = kth_channel_view<K>( dst_view );
|
||||
|
||||
p->template read_data< row_buffer_helper_view< plane_t > >( plane, K );
|
||||
|
||||
plane_recursion< K - 1 >::read_plane( dst_view, p );
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct plane_recursion< -1 >
|
||||
{
|
||||
template< typename View
|
||||
, typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
static
|
||||
void read_plane( const View& /* dst_view */
|
||||
, reader< Device
|
||||
, tiff_tag
|
||||
, ConversionPolicy
|
||||
>* /* p */
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
template< typename Device
|
||||
, typename ConversionPolicy
|
||||
>
|
||||
class reader< Device
|
||||
, tiff_tag
|
||||
, ConversionPolicy
|
||||
>
|
||||
: public reader_base< tiff_tag
|
||||
, ConversionPolicy >
|
||||
{
|
||||
public:
|
||||
|
||||
reader( Device& device
|
||||
, const image_read_settings< tiff_tag >& settings
|
||||
)
|
||||
: reader_base< tiff_tag
|
||||
, ConversionPolicy
|
||||
>( settings )
|
||||
, _io_dev( device )
|
||||
{
|
||||
init_multipage_read( settings );
|
||||
}
|
||||
|
||||
reader( Device& device
|
||||
, const typename ConversionPolicy::color_converter_type& cc
|
||||
, const image_read_settings< tiff_tag >& settings
|
||||
)
|
||||
: reader_base< tiff_tag
|
||||
, ConversionPolicy
|
||||
>( cc
|
||||
, settings
|
||||
)
|
||||
, _io_dev( device )
|
||||
{
|
||||
init_multipage_read( settings );
|
||||
}
|
||||
|
||||
image_read_info<tiff_tag> get_info() const
|
||||
{
|
||||
image_read_info<tiff_tag> info;
|
||||
|
||||
io_error_if( _io_dev.template get_property<tiff_image_width> ( info._width ) == false
|
||||
, "cannot read tiff tag." );
|
||||
io_error_if( _io_dev.template get_property<tiff_image_height> ( info._height ) == false
|
||||
, "cannot read tiff tag." );
|
||||
io_error_if( _io_dev.template get_property<tiff_compression> ( info._compression ) == false
|
||||
, "cannot read tiff tag." );
|
||||
io_error_if( _io_dev.template get_property<tiff_samples_per_pixel> ( info._samples_per_pixel ) == false
|
||||
, "cannot read tiff tag." );
|
||||
io_error_if( _io_dev.template get_property<tiff_bits_per_sample> ( info._bits_per_sample ) == false
|
||||
, "cannot read tiff tag." );
|
||||
io_error_if( _io_dev.template get_property<tiff_sample_format> ( info._sample_format ) == false
|
||||
, "cannot read tiff tag." );
|
||||
io_error_if( _io_dev.template get_property<tiff_planar_configuration> ( info._planar_configuration ) == false
|
||||
, "cannot read tiff tag." );
|
||||
io_error_if( _io_dev.template get_property<tiff_photometric_interpretation>( info._photometric_interpretation ) == false
|
||||
, "cannot read tiff tag." );
|
||||
|
||||
info._is_tiled = false;
|
||||
|
||||
// Tile tags
|
||||
if( _io_dev.is_tiled() )
|
||||
{
|
||||
info._is_tiled = true;
|
||||
|
||||
io_error_if( !_io_dev.template get_property< tiff_tile_width >( info._tile_width )
|
||||
, "cannot read tiff_tile_width tag." );
|
||||
io_error_if( !_io_dev.template get_property< tiff_tile_length >( info._tile_length )
|
||||
, "cannot read tiff_tile_length tag." );
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
// only works for homogeneous image types
|
||||
template< typename View >
|
||||
void apply( View& dst_view )
|
||||
{
|
||||
if( this->_info._photometric_interpretation == PHOTOMETRIC_PALETTE )
|
||||
{
|
||||
// Steps:
|
||||
// 1. Read indices. It's an array of grayX_pixel_t.
|
||||
// 2. Read palette. It's an array of rgb16_pixel_t.
|
||||
// 3. ??? Create virtual image or transform the two arrays
|
||||
// into a rgb16_image_t object. The latter might
|
||||
// be a good first solution.
|
||||
|
||||
switch( this->_info._bits_per_sample )
|
||||
{
|
||||
case 1: { read_palette_image< gray1_image_t >( dst_view ); break; }
|
||||
case 2: { read_palette_image< gray2_image_t >( dst_view ); break; }
|
||||
case 4: { read_palette_image< gray4_image_t >( dst_view ); break; }
|
||||
case 8: { read_palette_image< gray8_image_t >( dst_view ); break; }
|
||||
case 16: { read_palette_image< gray16_image_t >( dst_view ); break; }
|
||||
|
||||
default: { io_error( "Not supported palette " ); }
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// In case we only read the image the user's type and
|
||||
// the tiff type need to compatible. Which means:
|
||||
// color_spaces_are_compatible && channels_are_pairwise_compatible
|
||||
|
||||
typedef typename is_same< ConversionPolicy
|
||||
, read_and_no_convert
|
||||
>::type is_read_only;
|
||||
|
||||
io_error_if( !is_allowed< View >( this->_info
|
||||
, is_read_only()
|
||||
)
|
||||
, "Image types aren't compatible."
|
||||
);
|
||||
|
||||
if( this->_info._planar_configuration == PLANARCONFIG_SEPARATE )
|
||||
{
|
||||
plane_recursion< num_channels< View >::value - 1 >::read_plane( dst_view
|
||||
, this
|
||||
);
|
||||
}
|
||||
else if( this->_info._planar_configuration == PLANARCONFIG_CONTIG )
|
||||
{
|
||||
if( is_read_only::value == false )
|
||||
{
|
||||
// the read_data function needs to know what gil type the source image is
|
||||
// to have the default color converter function correctly
|
||||
|
||||
switch( this->_info._photometric_interpretation )
|
||||
{
|
||||
case PHOTOMETRIC_MINISWHITE:
|
||||
case PHOTOMETRIC_MINISBLACK:
|
||||
{
|
||||
switch( this->_info._bits_per_sample )
|
||||
{
|
||||
case 1: { read_data< row_buffer_helper_view< gray1_image_t::view_t > >( dst_view, 0 ); break; }
|
||||
case 2: { read_data< row_buffer_helper_view< gray2_image_t::view_t > >( dst_view, 0 ); break; }
|
||||
case 4: { read_data< row_buffer_helper_view< gray4_image_t::view_t > >( dst_view, 0 ); break; }
|
||||
case 8: { read_data< row_buffer_helper_view< gray8_view_t > >( dst_view, 0 ); break; }
|
||||
case 16: { read_data< row_buffer_helper_view< gray16_view_t > >( dst_view, 0 ); break; }
|
||||
case 32: { read_data< row_buffer_helper_view< gray32_view_t > >( dst_view, 0 ); break; }
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PHOTOMETRIC_RGB:
|
||||
{
|
||||
switch( this->_info._bits_per_sample )
|
||||
{
|
||||
case 8: { read_data< row_buffer_helper_view< rgb8_view_t > >( dst_view, 0 ); break; }
|
||||
case 16: { read_data< row_buffer_helper_view< rgb16_view_t > >( dst_view, 0 ); break; }
|
||||
case 32: { read_data< row_buffer_helper_view< rgb32_view_t > >( dst_view, 0 ); break; }
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PHOTOMETRIC_SEPARATED: // CYMK
|
||||
{
|
||||
switch( this->_info._bits_per_sample )
|
||||
{
|
||||
case 8: { read_data< row_buffer_helper_view< cmyk8_view_t > >( dst_view, 0 ); break; }
|
||||
case 16: { read_data< row_buffer_helper_view< cmyk16_view_t > >( dst_view, 0 ); break; }
|
||||
case 32: { read_data< row_buffer_helper_view< cmyk32_view_t > >( dst_view, 0 ); break; }
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default: { io_error( "Not supported colorspace " ); }
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
read_data< row_buffer_helper_view< View > >( dst_view, 0 );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
io_error( "Wrong planar configuration setting." );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void init_multipage_read( const image_read_settings< tiff_tag >& settings )
|
||||
{
|
||||
if( settings._directory > 0 )
|
||||
{
|
||||
_io_dev.set_directory( settings._directory );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename PaletteImage
|
||||
, typename View
|
||||
>
|
||||
void read_palette_image( const View& dst_view )
|
||||
{
|
||||
PaletteImage indices( this->_info._width - this->_settings._top_left.x
|
||||
, this->_info._height - this->_settings._top_left.y );
|
||||
|
||||
// read the palette first
|
||||
read_data< row_buffer_helper_view< typename PaletteImage::view_t > >( view( indices ), 0 );
|
||||
|
||||
read_palette_image( dst_view
|
||||
, view( indices )
|
||||
, typename is_same< View, rgb16_view_t >::type() );
|
||||
}
|
||||
|
||||
template< typename View
|
||||
, typename Indices_View
|
||||
>
|
||||
void read_palette_image( const View& dst_view
|
||||
, const Indices_View& indices_view
|
||||
, mpl::true_ // is View rgb16_view_t
|
||||
)
|
||||
{
|
||||
tiff_color_map::red_t red = NULL;
|
||||
tiff_color_map::green_t green = NULL;
|
||||
tiff_color_map::blue_t blue = NULL;
|
||||
|
||||
_io_dev.get_field_defaulted( red, green, blue );
|
||||
|
||||
typedef typename channel_traits<
|
||||
typename element_type<
|
||||
typename Indices_View::value_type >::type >::value_type channel_t;
|
||||
|
||||
int num_colors = channel_traits< channel_t >::max_value();
|
||||
|
||||
rgb16_planar_view_t palette = planar_rgb_view( num_colors
|
||||
, 1
|
||||
, red
|
||||
, green
|
||||
, blue
|
||||
, sizeof( bits16 ) * num_colors );
|
||||
|
||||
typename rgb16_planar_view_t::x_iterator palette_it = palette.row_begin( 0 );
|
||||
|
||||
for( typename rgb16_view_t::y_coord_t y = 0; y < dst_view.height(); ++y )
|
||||
{
|
||||
typename rgb16_view_t::x_iterator it = dst_view.row_begin( y );
|
||||
typename rgb16_view_t::x_iterator end = dst_view.row_end( y );
|
||||
|
||||
typename Indices_View::x_iterator indices_it = indices_view.row_begin( y );
|
||||
|
||||
for( ; it != end; ++it, ++indices_it )
|
||||
{
|
||||
bits16 i = gil::at_c<0>( *indices_it );
|
||||
|
||||
*it = palette[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View
|
||||
, typename Indices_View
|
||||
>
|
||||
inline
|
||||
void read_palette_image( const View& /* dst_view */
|
||||
, const Indices_View& /* indices_view */
|
||||
, mpl::false_ // is View rgb16_view_t
|
||||
)
|
||||
{
|
||||
io_error( "User supplied image type must be rgb16_image_t." );
|
||||
}
|
||||
|
||||
template< typename Buffer >
|
||||
void skip_over_rows( Buffer& buffer
|
||||
, int plane
|
||||
)
|
||||
{
|
||||
if( this->_info._compression != COMPRESSION_NONE )
|
||||
{
|
||||
// Skipping over rows is not possible for compressed images( no random access ). See man
|
||||
// page ( diagnostics section ) for more information.
|
||||
for( std::ptrdiff_t row = 0; row < this->_settings._top_left.y; ++row )
|
||||
{
|
||||
_io_dev.read_scanline( buffer
|
||||
, row
|
||||
, static_cast< tsample_t >( plane ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Buffer
|
||||
, typename View
|
||||
>
|
||||
void read_data( const View& dst_view
|
||||
, int plane )
|
||||
{
|
||||
if( _io_dev.is_tiled() )
|
||||
{
|
||||
read_tiled_data< Buffer >( dst_view, 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
read_stripped_data< Buffer >( dst_view, 0 );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template< typename Buffer
|
||||
, typename View
|
||||
>
|
||||
void read_tiled_data( const View& dst_view
|
||||
, int plane
|
||||
)
|
||||
{
|
||||
if( dst_view.width() != this->_info._width
|
||||
|| dst_view.height() != this->_info._height
|
||||
)
|
||||
{
|
||||
// read a subimage
|
||||
read_tiled_data_subimage< Buffer >( dst_view, plane );
|
||||
}
|
||||
else
|
||||
{
|
||||
// read full image
|
||||
read_tiled_data_full< Buffer >( dst_view, plane );
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Buffer
|
||||
, typename View
|
||||
>
|
||||
void read_tiled_data_subimage( const View& dst_view
|
||||
, int plane
|
||||
)
|
||||
{
|
||||
///@todo: why is
|
||||
/// typedef Buffer row_buffer_helper_t;
|
||||
/// not working? I get compiler error with MSVC10.
|
||||
/// read_stripped_data IS working.
|
||||
typedef row_buffer_helper_view< View > row_buffer_helper_t;
|
||||
|
||||
typedef typename row_buffer_helper_t::buffer_t buffer_t;
|
||||
typedef typename row_buffer_helper_t::iterator_t it_t;
|
||||
|
||||
tiff_image_width::type image_width = this->_info._width;
|
||||
tiff_image_height::type image_height = this->_info._height;
|
||||
|
||||
tiff_tile_width::type tile_width = this->_info._tile_width;
|
||||
tiff_tile_length::type tile_height = this->_info._tile_length;
|
||||
|
||||
std::ptrdiff_t subimage_x = this->_settings._top_left.x;
|
||||
std::ptrdiff_t subimage_y = this->_settings._top_left.y;
|
||||
|
||||
std::ptrdiff_t subimage_width = this->_settings._dim.x;
|
||||
std::ptrdiff_t subimage_height = this->_settings._dim.y;
|
||||
|
||||
row_buffer_helper_t row_buffer_helper( _io_dev.get_tile_size(), true );
|
||||
|
||||
mirror_bits< buffer_t
|
||||
, typename is_bit_aligned< typename View::value_type >::type
|
||||
> mirror_bits( _io_dev.are_bytes_swapped() );
|
||||
|
||||
for( unsigned int y = 0; y < image_height; y += tile_height )
|
||||
{
|
||||
for( unsigned int x = 0; x < image_width; x += tile_width )
|
||||
{
|
||||
uint32_t current_tile_width = ( x + tile_width < image_width ) ? tile_width : image_width - x;
|
||||
uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;
|
||||
|
||||
_io_dev.read_tile( row_buffer_helper.buffer()
|
||||
, x
|
||||
, y
|
||||
, 0
|
||||
, static_cast< tsample_t >( plane )
|
||||
);
|
||||
|
||||
mirror_bits( row_buffer_helper.buffer() );
|
||||
|
||||
// these are all whole image coordinates
|
||||
point_t tile_top_left ( x, y );
|
||||
point_t tile_lower_right( x + current_tile_width - 1, y + current_tile_length - 1 );
|
||||
|
||||
point_t view_top_left ( subimage_x, subimage_y );
|
||||
point_t view_lower_right( subimage_x + subimage_width - 1
|
||||
, subimage_y + subimage_height - 1 );
|
||||
|
||||
if( tile_top_left.x > view_lower_right.x
|
||||
|| tile_top_left.y > view_lower_right.y
|
||||
|| tile_lower_right.x < view_top_left.x
|
||||
|| tile_lower_right.y < view_top_left.y
|
||||
)
|
||||
{
|
||||
// current tile and dst_view do not overlap
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// dst_view is overlapping the current tile
|
||||
|
||||
// next is to define the portion in the tile that needs to be copied
|
||||
|
||||
// get the whole image coordinates
|
||||
std::ptrdiff_t img_x0 = ( tile_top_left.x >= view_top_left.x ) ? tile_top_left.x : view_top_left.x;
|
||||
std::ptrdiff_t img_y0 = ( tile_top_left.y >= view_top_left.y ) ? tile_top_left.y : view_top_left.y;
|
||||
|
||||
std::ptrdiff_t img_x1 = ( tile_lower_right.x <= view_lower_right.x ) ? tile_lower_right.x : view_lower_right.x;
|
||||
std::ptrdiff_t img_y1 = ( tile_lower_right.y <= view_lower_right.y ) ? tile_lower_right.y : view_lower_right.y;
|
||||
|
||||
// convert to tile coordinates
|
||||
std::ptrdiff_t tile_x0 = img_x0 - x;
|
||||
std::ptrdiff_t tile_y0 = img_y0 - y;
|
||||
std::ptrdiff_t tile_x1 = img_x1 - x;
|
||||
std::ptrdiff_t tile_y1 = img_y1 - y;
|
||||
|
||||
assert( tile_x0 >= 0 && tile_y0 >= 0 && tile_x1 >= 0 && tile_y1 >= 0 );
|
||||
assert( tile_x0 <= img_x1 && tile_y0 <= img_y1 );
|
||||
assert( tile_x0 < tile_width && tile_y0 < tile_height && tile_x1 < tile_width && tile_y1 < tile_height );
|
||||
|
||||
std::ptrdiff_t tile_subimage_view_width = tile_x1 - tile_x0 + 1;
|
||||
std::ptrdiff_t tile_subimage_view_height = tile_y1 - tile_y0 + 1;
|
||||
|
||||
// convert to dst_view coordinates
|
||||
std::ptrdiff_t dst_x0 = img_x0 - subimage_x;
|
||||
std::ptrdiff_t dst_y0 = img_y0 - subimage_y;
|
||||
assert( dst_x0 >= 0 && dst_y0 >= 0 );
|
||||
|
||||
View dst_subimage_view = subimage_view( dst_view
|
||||
, (int) dst_x0
|
||||
, (int) dst_y0
|
||||
, (int) tile_subimage_view_width
|
||||
, (int) tile_subimage_view_height
|
||||
);
|
||||
|
||||
// the row_buffer is a 1D array which represents a 2D image. We cannot
|
||||
// use interleaved_view here, since row_buffer could be bit_aligned.
|
||||
// Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
|
||||
// for bit_aligned pixels.
|
||||
|
||||
for( std::ptrdiff_t dst_row = 0; dst_row < dst_subimage_view.height(); ++dst_row )
|
||||
{
|
||||
std::ptrdiff_t tile_row = dst_row + tile_y0;
|
||||
|
||||
// jump to the beginning of the current tile row
|
||||
it_t begin = row_buffer_helper.begin() + tile_row * tile_width;
|
||||
|
||||
begin += tile_x0;
|
||||
it_t end = begin + dst_subimage_view.width();
|
||||
|
||||
this->_cc_policy.read( begin
|
||||
, end
|
||||
, dst_subimage_view.row_begin( dst_row )
|
||||
);
|
||||
} //for
|
||||
}
|
||||
} // for
|
||||
} // for
|
||||
}
|
||||
|
||||
template< typename Buffer
|
||||
, typename View
|
||||
>
|
||||
void read_tiled_data_full( const View& dst_view
|
||||
, int plane
|
||||
)
|
||||
{
|
||||
///@todo: why is
|
||||
/// typedef Buffer row_buffer_helper_t;
|
||||
/// not working? I get compiler error with MSVC10.
|
||||
/// read_stripped_data IS working.
|
||||
typedef row_buffer_helper_view< View > row_buffer_helper_t;
|
||||
|
||||
typedef typename row_buffer_helper_t::buffer_t buffer_t;
|
||||
typedef typename row_buffer_helper_t::iterator_t it_t;
|
||||
|
||||
tiff_image_width::type image_width = this->_info._width;
|
||||
tiff_image_height::type image_height = this->_info._height;
|
||||
|
||||
tiff_tile_width::type tile_width = this->_info._tile_width;
|
||||
tiff_tile_length::type tile_height = this->_info._tile_length;
|
||||
|
||||
row_buffer_helper_t row_buffer_helper( _io_dev.get_tile_size(), true );
|
||||
|
||||
mirror_bits< buffer_t
|
||||
, typename is_bit_aligned< typename View::value_type >::type
|
||||
> mirror_bits( _io_dev.are_bytes_swapped() );
|
||||
|
||||
for( unsigned int y = 0; y < image_height; y += tile_height )
|
||||
{
|
||||
for( unsigned int x = 0; x < image_width; x += tile_width )
|
||||
{
|
||||
uint32_t current_tile_width = ( x + tile_width < image_width ) ? tile_width : image_width - x;
|
||||
uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;
|
||||
|
||||
_io_dev.read_tile( row_buffer_helper.buffer()
|
||||
, x
|
||||
, y
|
||||
, 0
|
||||
, static_cast< tsample_t >( plane )
|
||||
);
|
||||
|
||||
mirror_bits( row_buffer_helper.buffer() );
|
||||
|
||||
View dst_subimage_view = subimage_view( dst_view
|
||||
, x
|
||||
, y
|
||||
, current_tile_width
|
||||
, current_tile_length
|
||||
);
|
||||
|
||||
// the row_buffer is a 1D array which represents a 2D image. We cannot
|
||||
// use interleaved_view here, since row_buffer could be bit_aligned.
|
||||
// Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
|
||||
// for bit_aligned pixels.
|
||||
|
||||
for( int row = 0; row < dst_subimage_view.height(); ++row )
|
||||
{
|
||||
it_t begin = row_buffer_helper.begin() + row * tile_width;
|
||||
it_t end = begin + dst_subimage_view.width();
|
||||
|
||||
this->_cc_policy.read( begin
|
||||
, end
|
||||
, dst_subimage_view.row_begin( row )
|
||||
);
|
||||
} //for
|
||||
} // for
|
||||
} // for
|
||||
}
|
||||
|
||||
template< typename Buffer
|
||||
, typename View
|
||||
>
|
||||
void read_stripped_data( const View& dst_view
|
||||
, int plane )
|
||||
{
|
||||
typedef typename is_bit_aligned< typename View::value_type >::type is_view_bit_aligned_t;
|
||||
|
||||
//typedef row_buffer_helper_view< View > row_buffer_helper_t;
|
||||
typedef Buffer row_buffer_helper_t;
|
||||
|
||||
typedef typename row_buffer_helper_t::buffer_t buffer_t;
|
||||
typedef typename row_buffer_helper_t::iterator_t it_t;
|
||||
|
||||
std::size_t size_to_allocate = buffer_size< typename View::value_type >( dst_view.width()
|
||||
, is_view_bit_aligned_t() );
|
||||
row_buffer_helper_t row_buffer_helper( size_to_allocate, true );
|
||||
|
||||
it_t begin = row_buffer_helper.begin();
|
||||
|
||||
it_t first = begin + this->_settings._top_left.x;
|
||||
it_t last = first + this->_settings._dim.x; // one after last element
|
||||
|
||||
// I don't think tiff allows for random access of row, that's why we need
|
||||
// to read and discard rows when reading subimages.
|
||||
skip_over_rows( row_buffer_helper.buffer()
|
||||
, plane
|
||||
);
|
||||
|
||||
mirror_bits< buffer_t
|
||||
, typename is_bit_aligned< View >::type
|
||||
> mirror_bits( _io_dev.are_bytes_swapped() );
|
||||
|
||||
std::ptrdiff_t row = this->_settings._top_left.y;
|
||||
std::ptrdiff_t row_end = row + this->_settings._dim.y;
|
||||
std::ptrdiff_t dst_row = 0;
|
||||
|
||||
for(
|
||||
; row < row_end
|
||||
; ++row, ++dst_row
|
||||
)
|
||||
{
|
||||
_io_dev.read_scanline( row_buffer_helper.buffer()
|
||||
, row
|
||||
, static_cast< tsample_t >( plane )
|
||||
);
|
||||
|
||||
mirror_bits( row_buffer_helper.buffer() );
|
||||
|
||||
this->_cc_policy.read( first
|
||||
, last
|
||||
, dst_view.row_begin( dst_row ));
|
||||
}
|
||||
}
|
||||
|
||||
template< typename Pixel >
|
||||
std::size_t buffer_size( std::size_t width
|
||||
, mpl::false_ // is_bit_aligned
|
||||
)
|
||||
{
|
||||
std::size_t scanline_size_in_bytes = _io_dev.get_scanline_size();
|
||||
|
||||
std::size_t element_size = sizeof( Pixel );
|
||||
|
||||
return std::max( width
|
||||
, (( scanline_size_in_bytes + element_size - 1 ) / element_size ));
|
||||
}
|
||||
|
||||
template< typename Pixel >
|
||||
std::size_t buffer_size( std::size_t /* width */
|
||||
, mpl::true_ // is_bit_aligned
|
||||
)
|
||||
{
|
||||
return _io_dev.get_scanline_size();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Device& _io_dev;
|
||||
|
||||
template < int K > friend struct plane_recursion;
|
||||
};
|
||||
|
||||
struct tiff_type_format_checker
|
||||
{
|
||||
tiff_type_format_checker( const image_read_info< tiff_tag >& info )
|
||||
: _info( info )
|
||||
{}
|
||||
|
||||
template< typename Image >
|
||||
bool apply()
|
||||
{
|
||||
typedef typename Image::view_t view_t;
|
||||
|
||||
return is_allowed< view_t >( _info
|
||||
, mpl::true_()
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const image_read_info< tiff_tag >& _info;
|
||||
};
|
||||
|
||||
struct tiff_read_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply : public is_read_supported< typename get_pixel_type< View >::type
|
||||
, tiff_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device
|
||||
>
|
||||
class dynamic_image_reader< Device
|
||||
, tiff_tag
|
||||
>
|
||||
: public reader< Device
|
||||
, tiff_tag
|
||||
, detail::read_and_no_convert
|
||||
>
|
||||
{
|
||||
typedef reader< Device
|
||||
, tiff_tag
|
||||
, detail::read_and_no_convert
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_reader( Device& device
|
||||
, const image_read_settings< tiff_tag >& settings
|
||||
)
|
||||
: parent_t( device
|
||||
, settings
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
{
|
||||
tiff_type_format_checker format_checker( this->_info );
|
||||
|
||||
if( !construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
io_error( "No matching image type between those of the given any_image and that of the file" );
|
||||
}
|
||||
else
|
||||
{
|
||||
init_image( images
|
||||
, this->_info
|
||||
);
|
||||
|
||||
dynamic_io_fnobj< tiff_read_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_IO_READ_HPP
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_TIFF_IO_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_IO_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/gil/color_base.hpp>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Read support
|
||||
|
||||
// TIFF virtually supports everything
|
||||
struct tiff_read_support : read_support_true
|
||||
{};
|
||||
|
||||
|
||||
// Write support
|
||||
|
||||
struct tiff_write_support : write_support_true
|
||||
{};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_read_supported< Pixel
|
||||
, tiff_tag
|
||||
>
|
||||
: mpl::bool_< detail::tiff_read_support::is_supported > {};
|
||||
|
||||
template< typename Pixel >
|
||||
struct is_write_supported< Pixel
|
||||
, tiff_tag
|
||||
>
|
||||
: mpl::bool_< detail::tiff_write_support::is_supported >
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_IO_HPP
|
||||
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_TIFF_IO_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_IO_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include "tiff.h"
|
||||
#include "tiffio.h"
|
||||
}
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <boost/static_assert.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/tiff_tags.hpp>
|
||||
|
||||
#include <boost/gil/extension/io_new/detail/base.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_device.hpp>
|
||||
|
||||
#include "device.hpp"
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template <typename PixelReference>
|
||||
struct my_interleaved_pixel_iterator_type_from_pixel_reference
|
||||
{
|
||||
private:
|
||||
typedef typename remove_reference< PixelReference >::type::value_type pixel_t;
|
||||
public:
|
||||
typedef typename iterator_type_from_pixel< pixel_t
|
||||
, false
|
||||
, false
|
||||
, true
|
||||
>::type type;
|
||||
};
|
||||
|
||||
|
||||
template< typename Channel
|
||||
, typename Layout
|
||||
, bool Mutable
|
||||
>
|
||||
struct my_interleaved_pixel_iterator_type_from_pixel_reference< const bit_aligned_pixel_reference< byte_t
|
||||
, Channel
|
||||
, Layout
|
||||
, Mutable
|
||||
>
|
||||
>
|
||||
: public iterator_type_from_pixel< const bit_aligned_pixel_reference< uint8_t
|
||||
, Channel
|
||||
, Layout
|
||||
, Mutable
|
||||
>
|
||||
,false
|
||||
,false
|
||||
,true
|
||||
> {};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
template < typename Channel > struct sample_format : public mpl::int_<SAMPLEFORMAT_UINT> {};
|
||||
template<> struct sample_format<bits8> : public mpl::int_<SAMPLEFORMAT_UINT> {};
|
||||
template<> struct sample_format<bits16> : public mpl::int_<SAMPLEFORMAT_UINT> {};
|
||||
template<> struct sample_format<bits32> : public mpl::int_<SAMPLEFORMAT_UINT> {};
|
||||
template<> struct sample_format<bits32f> : public mpl::int_<SAMPLEFORMAT_IEEEFP> {};
|
||||
template<> struct sample_format<double> : public mpl::int_<SAMPLEFORMAT_IEEEFP> {};
|
||||
template<> struct sample_format<bits8s> : public mpl::int_<SAMPLEFORMAT_INT> {};
|
||||
template<> struct sample_format<bits16s> : public mpl::int_<SAMPLEFORMAT_INT> {};
|
||||
template<> struct sample_format<bits32s> : public mpl::int_<SAMPLEFORMAT_INT> {};
|
||||
|
||||
template <typename Channel> struct photometric_interpretation {};
|
||||
template<> struct photometric_interpretation< gray_t > : public mpl::int_< PHOTOMETRIC_MINISBLACK > {};
|
||||
template<> struct photometric_interpretation< rgb_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
|
||||
template<> struct photometric_interpretation< rgba_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
|
||||
template<> struct photometric_interpretation< cmyk_t > : public mpl::int_< PHOTOMETRIC_SEPARATED > {};
|
||||
|
||||
template < typename Device, typename Log >
|
||||
class writer< Device
|
||||
, tiff_tag
|
||||
, Log
|
||||
>
|
||||
{
|
||||
public:
|
||||
|
||||
typedef image_write_info<tiff_tag, Log> info_t;
|
||||
|
||||
writer( Device& dev )
|
||||
: _io_dev( dev ) {}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
typedef typename color_space_type<View>::type color_space_t;
|
||||
|
||||
info_t info;
|
||||
|
||||
// write photometric interpretion - Warning: This value is rather subjective.
|
||||
// The user should better set this value itself. There is no way to decide if
|
||||
// a image is PHOTOMETRIC_MINISWHITE or PHOTOMETRIC_MINISBLACK. This writer
|
||||
// will assume PHOTOMETRIC_MINISBLACK for gray_t images and PHOTOMETRIC_RGB
|
||||
// for rgb_t images.
|
||||
info._photometric_interpretation = photometric_interpretation< color_space_t >::value;
|
||||
|
||||
write_view( view
|
||||
, info );
|
||||
}
|
||||
|
||||
template<typename View>
|
||||
void apply( const View& view
|
||||
, const info_t& info )
|
||||
{
|
||||
write_view( view
|
||||
, info );
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template< typename View >
|
||||
void write_view( const View& src_view
|
||||
, const info_t& info
|
||||
)
|
||||
{
|
||||
typedef typename View::value_type pixel_t;
|
||||
|
||||
// get the type of the first channel (heterogeneous pixels might be broken for now!)
|
||||
typedef typename channel_traits< typename element_type< pixel_t >::type >::value_type channel_t;
|
||||
|
||||
// write dimensions
|
||||
tiff_image_width::type width = (tiff_image_width::type) src_view.width();
|
||||
tiff_image_height::type height = (tiff_image_height::type) src_view.height();
|
||||
|
||||
_io_dev.template set_property< tiff_image_width >( width );
|
||||
_io_dev.template set_property< tiff_image_height >( height );
|
||||
|
||||
// write planar configuration
|
||||
if( is_bit_aligned< View >::value == false )
|
||||
{
|
||||
_io_dev.template set_property<tiff_planar_configuration>( info._planar_configuration );
|
||||
}
|
||||
|
||||
// write samples per pixel
|
||||
tiff_samples_per_pixel::type samples_per_pixel = num_channels< pixel_t >::value;
|
||||
_io_dev.template set_property<tiff_samples_per_pixel>( samples_per_pixel );
|
||||
|
||||
// write bits per sample
|
||||
// @todo: Settings this value usually requires to write for each sample the bit
|
||||
// value seperately in case they are different, like rgb556.
|
||||
tiff_bits_per_sample::type bits_per_sample = unsigned_integral_num_bits<channel_t>::value;
|
||||
_io_dev.template set_property<tiff_bits_per_sample>( bits_per_sample );
|
||||
|
||||
// write sample format
|
||||
tiff_sample_format::type sampl_format = sample_format< channel_t >::type::value;
|
||||
_io_dev.template set_property<tiff_sample_format>( sampl_format );
|
||||
|
||||
// write photometric format
|
||||
_io_dev.template set_property<tiff_photometric_interpretation>( info._photometric_interpretation );
|
||||
|
||||
// write compression
|
||||
_io_dev.template set_property<tiff_compression>( info._compression );
|
||||
|
||||
// write orientation
|
||||
_io_dev.template set_property<tiff_orientation>( info._orientation );
|
||||
|
||||
// write rows per strip
|
||||
_io_dev.template set_property<tiff_rows_per_strip>( _io_dev.get_default_strip_size() );
|
||||
|
||||
if(!info._is_tiled)
|
||||
{
|
||||
write_data( src_view
|
||||
, info
|
||||
, (src_view.width() * samples_per_pixel * bits_per_sample + 7) / 8
|
||||
, typename is_bit_aligned< pixel_t >::type()
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
tiff_tile_width::type tw = info._tile_width;
|
||||
tiff_tile_length::type th = info._tile_length;
|
||||
|
||||
if(!_io_dev.check_tile_size( tw, th ))
|
||||
{
|
||||
io_error( "Tile sizes need to be multiples of 16." );
|
||||
}
|
||||
|
||||
// tile related tags
|
||||
_io_dev.template set_property<tiff_tile_width> ( tw );
|
||||
_io_dev.template set_property<tiff_tile_length>( th );
|
||||
|
||||
write_tiled_data( src_view
|
||||
, tw
|
||||
, th
|
||||
, typename is_bit_aligned< pixel_t >::type()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void write_data( const View& src_view
|
||||
, const info_t& /* info */
|
||||
, std::size_t row_size_in_bytes
|
||||
, const mpl::true_& // bit_aligned
|
||||
)
|
||||
{
|
||||
byte_vector_t row( row_size_in_bytes );
|
||||
|
||||
typedef typename View::x_iterator x_it_t;
|
||||
x_it_t row_it = x_it_t( &(*row.begin()));
|
||||
|
||||
for( typename View::y_coord_t y = 0; y < src_view.height(); ++y )
|
||||
{
|
||||
std::copy( src_view.row_begin( y )
|
||||
, src_view.row_end( y )
|
||||
, row_it
|
||||
);
|
||||
|
||||
_io_dev.write_scaline( row
|
||||
, (uint32) y
|
||||
, 0
|
||||
);
|
||||
|
||||
// @todo: do optional bit swapping here if you need to...
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void write_tiled_data( const View& src_view
|
||||
, tiff_tile_width::type tw
|
||||
, tiff_tile_length::type th
|
||||
, const mpl::true_& // bit_aligned
|
||||
)
|
||||
{
|
||||
byte_vector_t row( _io_dev.get_tile_size() );
|
||||
|
||||
typedef typename View::x_iterator x_it_t;
|
||||
x_it_t row_it = x_it_t( &(*row.begin()));
|
||||
|
||||
internal_write_tiled_data(src_view, tw, th, row, row_it);
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void write_data( const View& src_view
|
||||
, const info_t& info
|
||||
, std::size_t row_size_in_bytes
|
||||
, const mpl::false_& // bit_aligned
|
||||
)
|
||||
{
|
||||
byte_vector_t row( row_size_in_bytes );
|
||||
|
||||
typedef typename my_interleaved_pixel_iterator_type_from_pixel_reference< typename View::reference
|
||||
>::type x_iterator;
|
||||
|
||||
x_iterator row_it = x_iterator( &(*row.begin()));
|
||||
|
||||
for( typename View::y_coord_t y = 0; y < src_view.height(); ++y )
|
||||
{
|
||||
std::copy( src_view.row_begin( y )
|
||||
, src_view.row_end( y )
|
||||
, row_it
|
||||
);
|
||||
|
||||
_io_dev.write_scaline( row
|
||||
, (uint32) y
|
||||
, 0
|
||||
);
|
||||
|
||||
// @todo: do optional bit swapping here if you need to...
|
||||
}
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void write_tiled_data( const View& src_view
|
||||
, tiff_tile_width::type tw
|
||||
, tiff_tile_length::type th
|
||||
, const mpl::false_& // bit_aligned
|
||||
)
|
||||
{
|
||||
byte_vector_t row( _io_dev.get_tile_size() );
|
||||
|
||||
typedef typename my_interleaved_pixel_iterator_type_from_pixel_reference< typename View::reference
|
||||
>::type x_iterator;
|
||||
x_iterator row_it = x_iterator( &(*row.begin()));
|
||||
|
||||
internal_write_tiled_data(src_view, tw, th, row, row_it);
|
||||
}
|
||||
|
||||
template< typename View,
|
||||
typename IteratorType >
|
||||
void internal_write_tiled_data( const View& src_view
|
||||
, tiff_tile_width::type tw
|
||||
, tiff_tile_length::type th
|
||||
, byte_vector_t& row
|
||||
, IteratorType it
|
||||
)
|
||||
{
|
||||
std::ptrdiff_t i = 0, j = 0;
|
||||
View tile_subimage_view;
|
||||
while( i < src_view.height() )
|
||||
{
|
||||
while( j < src_view.width() )
|
||||
{
|
||||
if( j + tw < src_view.width() && i + th < src_view.height() )
|
||||
{
|
||||
// a tile is fully included in the image: just copy values
|
||||
tile_subimage_view = subimage_view( src_view
|
||||
, static_cast< int >( j )
|
||||
, static_cast< int >( i )
|
||||
, static_cast< int >( tw )
|
||||
, static_cast< int >( th )
|
||||
);
|
||||
|
||||
std::copy( tile_subimage_view.begin()
|
||||
, tile_subimage_view.end()
|
||||
, it
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::ptrdiff_t width = src_view.width();
|
||||
std::ptrdiff_t height = src_view.height();
|
||||
|
||||
std::ptrdiff_t current_tile_width = ( j + tw < width ) ? tw : width - j;
|
||||
std::ptrdiff_t current_tile_length = ( i + th < height) ? th : height - i;
|
||||
|
||||
tile_subimage_view = subimage_view( src_view
|
||||
, static_cast< int >( j )
|
||||
, static_cast< int >( i )
|
||||
, static_cast< int >( current_tile_width )
|
||||
, static_cast< int >( current_tile_length )
|
||||
);
|
||||
|
||||
for( typename View::y_coord_t y = 0; y < tile_subimage_view.height(); ++y )
|
||||
{
|
||||
std::copy( tile_subimage_view.row_begin( y )
|
||||
, tile_subimage_view.row_end( y )
|
||||
, it
|
||||
);
|
||||
std::advance(it, tw);
|
||||
}
|
||||
|
||||
it = IteratorType( &(*row.begin()));
|
||||
}
|
||||
|
||||
_io_dev.write_tile( row
|
||||
, static_cast< uint32 >( j )
|
||||
, static_cast< uint32 >( i )
|
||||
, 0
|
||||
, 0
|
||||
);
|
||||
j += tw;
|
||||
}
|
||||
j = 0;
|
||||
i += th;
|
||||
}
|
||||
// @todo: do optional bit swapping here if you need to...
|
||||
}
|
||||
|
||||
Device& _io_dev;
|
||||
};
|
||||
|
||||
struct tiff_write_is_supported
|
||||
{
|
||||
template< typename View >
|
||||
struct apply
|
||||
: public is_write_supported< typename get_pixel_type< View >::type
|
||||
, tiff_tag
|
||||
>
|
||||
{};
|
||||
};
|
||||
|
||||
template< typename Device >
|
||||
class dynamic_image_writer< Device
|
||||
, tiff_tag
|
||||
>
|
||||
: public writer< Device
|
||||
, tiff_tag
|
||||
>
|
||||
{
|
||||
typedef writer< Device
|
||||
, tiff_tag
|
||||
> parent_t;
|
||||
|
||||
public:
|
||||
|
||||
dynamic_image_writer( Device& file )
|
||||
: parent_t( file )
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
{
|
||||
dynamic_io_fnobj< tiff_write_is_supported
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( views, op );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_IO_WRITE_HPP
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_ALL_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_ALL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "jpeg_read.hpp"
|
||||
#include "jpeg_write.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_ALL_HPP
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_IO_OLD_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_JPEG_IO_OLD_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "jpeg_all.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
|
||||
point2< std::ptrdiff_t > jpeg_read_dimensions( const String& filename )
|
||||
{
|
||||
image_read_info< jpeg_tag > info = read_image_info( filename
|
||||
, jpeg_tag()
|
||||
);
|
||||
|
||||
return point2< std::ptrdiff_t >( info._width
|
||||
, 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 // BOOST_GIL_EXTENSION_IO_JPEG_IO_OLD_HPP
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "jpeg_tags.hpp"
|
||||
#include "formats/jpeg/supported_types.hpp"
|
||||
#include "formats/jpeg/read.hpp"
|
||||
|
||||
#include "detail/read_image.hpp"
|
||||
#include "detail/read_view.hpp"
|
||||
#include "detail/read_image_info.hpp"
|
||||
#include "detail/read_and_convert_image.hpp"
|
||||
#include "detail/read_and_convert_view.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_READ_HPP
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief All supported jpeg tags by the gil io extension.
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include <jpeglib.h>
|
||||
}
|
||||
|
||||
#include "detail/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 > {};
|
||||
|
||||
/// 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 >
|
||||
{
|
||||
/// 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;
|
||||
};
|
||||
|
||||
/// 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<jpeg_tag>()
|
||||
: 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( const point_t& top_left
|
||||
, const point_t& 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.
|
||||
image_write_info( const jpeg_quality::type quality = jpeg_quality::default_value
|
||||
, const jpeg_dct_method::type dct_method = jpeg_dct_method::default_value
|
||||
)
|
||||
: _quality ( quality )
|
||||
, _dct_method( dct_method )
|
||||
{}
|
||||
|
||||
/// The jpeg quality.
|
||||
jpeg_quality::type _quality;
|
||||
|
||||
/// The dct ( discrete cosine transformation ) method.
|
||||
jpeg_dct_method::type _dct_method;
|
||||
};
|
||||
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_TAGS_HPP
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "jpeg_tags.hpp"
|
||||
#include "formats/jpeg/supported_types.hpp"
|
||||
#include "formats/jpeg/write.hpp"
|
||||
|
||||
#include "detail/write_view.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_JPEG_WRITE_HPP
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNG_ALL_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNG_ALL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "png_read.hpp"
|
||||
#include "png_write.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNG_ALL_HPP
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNG_IO_OLD_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNG_IO_OLD_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "png_all.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Returns the width and height of the PNG file at the specified location.
|
||||
/// Throws std::ios_base::failure if the location does not correspond to a valid PNG file
|
||||
template< typename String >
|
||||
inline
|
||||
point2< std::ptrdiff_t > png_read_dimensions( const String& filename )
|
||||
{
|
||||
image_read_info< png_tag > info = read_image_info( filename
|
||||
, png_tag()
|
||||
);
|
||||
|
||||
return point2< std::ptrdiff_t >( info._width
|
||||
, info._height
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Loads the image specified by the given png image file name into the given view.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the PNG library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNG 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 png_read_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_view( filename
|
||||
, view
|
||||
, png_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given png 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 PNG library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNG 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 png_read_image( const String& filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_image( filename
|
||||
, img
|
||||
, png_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Loads the image specified by the given png image file name and color-converts it into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void png_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, cc
|
||||
, png_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Loads the image specified by the given png image file name and color-converts it into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
>
|
||||
inline
|
||||
void png_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, png_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNG file
|
||||
template< typename String
|
||||
, typename Image
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void png_read_and_convert_image( const String& filename
|
||||
, Image& img
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, cc
|
||||
, png_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNG file
|
||||
template< typename String
|
||||
, typename Image
|
||||
>
|
||||
inline
|
||||
void png_read_and_convert_image( const String filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, png_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
/// \brief Saves the view to a png file specified by the given png image file name.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the PNG 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 png_write_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
write_view( filename
|
||||
, view
|
||||
, png_tag()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNG_IO_OLD_HPP
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNG_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNG_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "png_tags.hpp"
|
||||
#include "formats/png/supported_types.hpp"
|
||||
#include "formats/png/read.hpp"
|
||||
|
||||
#include "detail/read_image.hpp"
|
||||
#include "detail/read_view.hpp"
|
||||
#include "detail/read_image_info.hpp"
|
||||
#include "detail/read_and_convert_image.hpp"
|
||||
#include "detail/read_and_convert_view.hpp"
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNG_READ_HPP
|
||||
@@ -0,0 +1,613 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_PNG_TAGS_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNG_TAGS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include <png.h>
|
||||
}
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "detail/base.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// Defines png tag.
|
||||
struct png_tag : format_tag {};
|
||||
|
||||
/// see http://en.wikipedia.org/wiki/Portable_Network_Graphics for reference
|
||||
|
||||
/// Defines type for image width property.
|
||||
struct png_image_width : property_base< png_uint_32 > {};
|
||||
|
||||
/// Defines type for image height property.
|
||||
struct png_image_height : property_base< png_uint_32 > {};
|
||||
|
||||
/// Defines type for interlace method property.
|
||||
struct png_interlace_method : property_base< int > {};
|
||||
|
||||
/// Defines type for compression method property.
|
||||
struct png_compression_method : property_base< int > {};
|
||||
|
||||
/// Defines type for filter method property.
|
||||
struct png_filter_method : property_base< int > {};
|
||||
|
||||
/// Defines type for bit depth method property.
|
||||
struct png_bitdepth : property_base< int > {};
|
||||
|
||||
/// Defines type for bit depth method property.
|
||||
struct png_color_type : property_base< int > {};
|
||||
|
||||
/// Defines type for number of channels property.
|
||||
struct png_num_channels : property_base< png_byte > {};
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
/// Defines type for CIE chromacities property.
|
||||
struct png_chromacities_type : property_base< double > {};
|
||||
|
||||
/// Defines type for gamma correction property.
|
||||
struct png_gamma : property_base< double > {};
|
||||
|
||||
/// Defines type for physical scale unit property.
|
||||
struct png_unit : property_base< int > {};
|
||||
|
||||
/// Defines type for physical scale property.
|
||||
struct png_scale : property_base< double > {};
|
||||
|
||||
#else
|
||||
/// Defines type for CIE chromacities property.
|
||||
struct png_chromacities_type : property_base< png_fixed_point > {};
|
||||
|
||||
/// Defines type for gamma correction property.
|
||||
struct png_gamma : property_base< png_fixed_point > {};
|
||||
|
||||
/// Defines type for physical scale unit property.
|
||||
struct png_unit : property_base< int > {};
|
||||
|
||||
/// Defines type for physical scale property.
|
||||
struct png_scale : property_base< std::string > {};
|
||||
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
/// Defines type for ICC profile name property.
|
||||
struct png_ICC_name : property_base< std::string > {};
|
||||
/// Defines type for ICC profile property.
|
||||
struct png_ICC_profile : property_base< std::string > {};
|
||||
/// Defines type for ICC profile length property.
|
||||
struct png_ICC_profile_length : property_base< png_uint_32 > {};
|
||||
/// Defines type for ICC compression property.
|
||||
struct png_ICC_compression_type : property_base< int > {};
|
||||
|
||||
/// Defines type for rendering intent property.
|
||||
struct png_intent : property_base< int > {};
|
||||
|
||||
/// Defines type for color palette property.
|
||||
struct png_color_palette : property_base< std::vector< png_color > > {};
|
||||
/// Defines type for number of colors property.
|
||||
struct png_num_palette : property_base< int > {};
|
||||
|
||||
/// Defines type for background property.
|
||||
struct png_background : property_base< png_color_16 > {};
|
||||
|
||||
/// Defines type for histogram property.
|
||||
struct png_histrogram : property_base< std::vector< png_uint_16 > > {};
|
||||
|
||||
/// Defines type for screen offset property.
|
||||
struct png_offset : property_base< png_int_32 > {};
|
||||
/// Defines type for screen offset type property.
|
||||
struct png_offset_type : property_base< int > {};
|
||||
|
||||
/// Defines type pixel calibration for property.
|
||||
struct png_CAL : property_base< std::string > {};
|
||||
/// Defines type for pixel calibration parameters property.
|
||||
struct png_CAL_params : property_base< std::vector< std::string > > {};
|
||||
/// Defines type for pixel calibration x property.
|
||||
struct png_CAL_X : property_base< png_int_32 > {};
|
||||
/// Defines type for pixel calibration type property.
|
||||
struct png_CAL_type : property_base< int > {};
|
||||
/// Defines type for number of pixel calibration properties.
|
||||
struct png_CAL_nparam : property_base< int > {};
|
||||
|
||||
/// Defines type for physical resolution property.
|
||||
struct png_resolution : property_base< png_uint_32 > {};
|
||||
/// Defines type for physical resolution unit property.
|
||||
struct png_unit_type : property_base< int > {};
|
||||
|
||||
/// Defines type for significant bits property.
|
||||
struct png_significant_bits : property_base< png_color_8 > {};
|
||||
|
||||
/// Helper structure for reading text property.
|
||||
struct gil_io_png_text
|
||||
{
|
||||
/// Compression type
|
||||
int _compression;
|
||||
// Key
|
||||
std::string _key;
|
||||
/// Text
|
||||
std::string _text;
|
||||
};
|
||||
|
||||
/// Defines type for text property.
|
||||
struct png_text_ : property_base< std::vector< gil_io_png_text > > {};
|
||||
/// Defines type for number of text property.
|
||||
struct png_num_text : property_base< int > {};
|
||||
|
||||
/// Defines type for modification time property.
|
||||
struct png_mod_time : property_base< png_time > {};
|
||||
|
||||
/// Defines type for transparency data property.
|
||||
struct png_trans : property_base< std::vector< png_byte > > {};
|
||||
/// Defines type for number of transparency data property.
|
||||
struct png_num_trans : property_base< int > {};
|
||||
/// Defines type for transparency data values property.
|
||||
struct png_trans_values : property_base< std::vector< png_color_16 > > {};
|
||||
|
||||
/// Defines type for png function return type.
|
||||
struct png_return_value : property_base< png_uint_32 > {};
|
||||
|
||||
/// PNG info base class. Containing all header information both for reading and writing.
|
||||
///
|
||||
/// This base structure was created to avoid code doubling.
|
||||
struct png_info_base
|
||||
{
|
||||
/// Default constructor
|
||||
png_info_base()
|
||||
: _width ( 0 )
|
||||
, _height( 0 )
|
||||
|
||||
, _bit_depth ( 0 )
|
||||
, _color_type ( 0 )
|
||||
, _interlace_method ( PNG_INTERLACE_NONE )
|
||||
, _compression_method( PNG_COMPRESSION_TYPE_DEFAULT )
|
||||
, _filter_method ( PNG_FILTER_TYPE_DEFAULT )
|
||||
|
||||
, _num_channels( 0 )
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
, _valid_cie_colors( 0 )
|
||||
, _white_x ( 0.0 )
|
||||
, _white_y ( 0.0 )
|
||||
, _red_x ( 0.0 )
|
||||
, _red_y ( 0.0 )
|
||||
, _green_x ( 0.0 )
|
||||
, _green_y ( 0.0 )
|
||||
, _blue_x ( 0.0 )
|
||||
, _blue_y ( 0.0 )
|
||||
|
||||
, _valid_file_gamma( 0 )
|
||||
, _file_gamma ( 1.0 )
|
||||
#else
|
||||
, _valid_cie_colors( 0 )
|
||||
, _white_x ( 0 )
|
||||
, _white_y ( 0 )
|
||||
, _red_x ( 0 )
|
||||
, _red_y ( 0 )
|
||||
, _green_x ( 0 )
|
||||
, _green_y ( 0 )
|
||||
, _blue_x ( 0 )
|
||||
, _blue_y ( 0 )
|
||||
|
||||
, _valid_file_gamma( 0 )
|
||||
, _file_gamma ( 1 )
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
, _valid_icc_profile ( 0 )
|
||||
, _icc_name ( )
|
||||
, _iccp_compression_type( PNG_COMPRESSION_TYPE_BASE )
|
||||
, _profile ( )
|
||||
, _profile_length ( 0 )
|
||||
|
||||
, _valid_intent( 0 )
|
||||
, _intent ( 0 )
|
||||
|
||||
, _valid_palette( 0 )
|
||||
, _palette ( )
|
||||
, _num_palette ( 0 )
|
||||
|
||||
, _valid_background( 0 )
|
||||
, _background ( )
|
||||
|
||||
, _valid_histogram( 0 )
|
||||
, _histogram ( )
|
||||
|
||||
, _valid_offset ( 0 )
|
||||
, _offset_x ( 0 )
|
||||
, _offset_y ( 0 )
|
||||
, _off_unit_type( PNG_OFFSET_PIXEL )
|
||||
|
||||
, _valid_pixel_calibration( 0 )
|
||||
, _purpose ( )
|
||||
, _X0 ( 0 )
|
||||
, _X1 ( 0 )
|
||||
, _cal_type ( 0 )
|
||||
, _num_params ( 0 )
|
||||
, _units ( )
|
||||
, _params ( )
|
||||
|
||||
, _valid_resolution( 0 )
|
||||
, _res_x ( 0 )
|
||||
, _res_y ( 0 )
|
||||
, _phy_unit_type ( PNG_RESOLUTION_UNKNOWN )
|
||||
|
||||
, _valid_significant_bits( 0 )
|
||||
, _sig_bits ( )
|
||||
|
||||
, _valid_scale_factors( 0 )
|
||||
, _scale_unit ( PNG_SCALE_UNKNOWN )
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
, _scale_width ( 0.0 )
|
||||
, _scale_height( 0.0 )
|
||||
#else
|
||||
, _scale_width ()
|
||||
, _scale_height()
|
||||
#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
, _valid_text( 0 )
|
||||
, _text ( )
|
||||
, _num_text ( 0 )
|
||||
|
||||
, _valid_modification_time( 0 )
|
||||
, _mod_time ( )
|
||||
|
||||
, _valid_transparency_factors( 0 )
|
||||
, _trans ( )
|
||||
, _num_trans ( 0 )
|
||||
, _trans_values ( )
|
||||
{}
|
||||
|
||||
/// The image width.
|
||||
png_image_width::type _width;
|
||||
/// The image height.
|
||||
png_image_height::type _height;
|
||||
|
||||
/// The bit depth per channel.
|
||||
png_bitdepth::type _bit_depth;
|
||||
/// The color space type.
|
||||
png_color_type::type _color_type;
|
||||
/// The interlace methos.
|
||||
png_interlace_method::type _interlace_method;
|
||||
/// The compression method.
|
||||
png_compression_method::type _compression_method;
|
||||
/// The filer method.
|
||||
png_filter_method::type _filter_method;
|
||||
|
||||
/// The number of channels.
|
||||
png_num_channels::type _num_channels;
|
||||
|
||||
// CIE chromacities
|
||||
/// The return value when reading CIE chromacities.
|
||||
png_return_value::type _valid_cie_colors;
|
||||
/// The white x value.
|
||||
png_chromacities_type::type _white_x;
|
||||
/// The white y value.
|
||||
png_chromacities_type::type _white_y;
|
||||
/// The red x value.
|
||||
png_chromacities_type::type _red_x;
|
||||
/// The red y value.
|
||||
png_chromacities_type::type _red_y;
|
||||
/// The green x value.
|
||||
png_chromacities_type::type _green_x;
|
||||
/// The green y value.
|
||||
png_chromacities_type::type _green_y;
|
||||
/// The blue x value.
|
||||
png_chromacities_type::type _blue_x;
|
||||
/// The blue y value.
|
||||
png_chromacities_type::type _blue_y;
|
||||
|
||||
// Gamma Value
|
||||
/// The return value when reading gamma value.
|
||||
png_return_value::type _valid_file_gamma;
|
||||
/// The file gamma value.
|
||||
png_gamma::type _file_gamma;
|
||||
|
||||
// Embedded ICC profile
|
||||
/// The return value when reading ICC profile.
|
||||
png_return_value::type _valid_icc_profile;
|
||||
/// The ICC name.
|
||||
png_ICC_name::type _icc_name;
|
||||
/// The icc compression type.
|
||||
png_ICC_compression_type::type _iccp_compression_type;
|
||||
/// The ICC profile.
|
||||
png_ICC_profile::type _profile;
|
||||
/// The ICC profile length.
|
||||
png_ICC_profile_length::type _profile_length;
|
||||
|
||||
// Rendering intent
|
||||
/// The return value when reading rendering intent.
|
||||
png_return_value::type _valid_intent;
|
||||
/// The rendering intent value.
|
||||
png_intent::type _intent;
|
||||
|
||||
// Image palette
|
||||
/// The return value when reading image palette.
|
||||
png_return_value::type _valid_palette;
|
||||
/// The color palette.
|
||||
png_color_palette::type _palette;
|
||||
/// The number of colors in the palettes.
|
||||
png_num_palette::type _num_palette;
|
||||
|
||||
// Background
|
||||
/// The return value when reading background.
|
||||
png_return_value::type _valid_background;
|
||||
/// The background color.
|
||||
png_background::type _background;
|
||||
|
||||
// Histogram
|
||||
/// The return value when reading histogram.
|
||||
png_return_value::type _valid_histogram;
|
||||
/// The histogram.
|
||||
png_histrogram::type _histogram;
|
||||
|
||||
// Screen offsets
|
||||
/// The return value when reading screen offsets.
|
||||
png_return_value::type _valid_offset;
|
||||
/// The x offset.
|
||||
png_offset::type _offset_x;
|
||||
/// The y offset.
|
||||
png_offset::type _offset_y;
|
||||
/// The offset unit.
|
||||
png_offset_type::type _off_unit_type;
|
||||
|
||||
// Pixel Calibration
|
||||
/// The return value when reading pixel calibration.
|
||||
png_return_value::type _valid_pixel_calibration;
|
||||
/// The purpose.
|
||||
png_CAL::type _purpose;
|
||||
/// The x_0 value.
|
||||
png_CAL_X::type _X0;
|
||||
/// The x_1 value.
|
||||
png_CAL_X::type _X1;
|
||||
/// The calibration type.
|
||||
png_CAL_type::type _cal_type;
|
||||
/// The number of calibration parameters.
|
||||
png_CAL_nparam::type _num_params;
|
||||
/// The calibration unit type.
|
||||
png_CAL::type _units;
|
||||
/// The calibration parameters.
|
||||
png_CAL_params::type _params;
|
||||
|
||||
// Physical resolution
|
||||
/// The return value when reading physical resolution properties.
|
||||
png_return_value::type _valid_resolution;
|
||||
/// The x physical resolution.
|
||||
png_resolution::type _res_x;
|
||||
/// The y physical resolution.
|
||||
png_resolution::type _res_y;
|
||||
/// The physical resolution unit.
|
||||
png_unit_type::type _phy_unit_type;
|
||||
|
||||
// Number of significant bits
|
||||
/// The return value when reading significant bits.
|
||||
png_return_value::type _valid_significant_bits;
|
||||
/// The significant bits.
|
||||
png_significant_bits::type _sig_bits;
|
||||
|
||||
// Scale Factors
|
||||
/// The return value when reading scale factors.
|
||||
png_return_value::type _valid_scale_factors;
|
||||
/// The scaling unit.
|
||||
png_unit::type _scale_unit;
|
||||
/// The scaling width.
|
||||
png_scale::type _scale_width;
|
||||
/// The scaling height.
|
||||
png_scale::type _scale_height;
|
||||
|
||||
// Comments information
|
||||
/// The return value when reading image comments.
|
||||
png_return_value::type _valid_text;
|
||||
/// The comments.
|
||||
png_text_::type _text;
|
||||
/// The number of comments.
|
||||
png_num_text::type _num_text;
|
||||
|
||||
// Last modification time
|
||||
/// The return value when reading modification time.
|
||||
png_return_value::type _valid_modification_time;
|
||||
/// The modification time.
|
||||
png_mod_time::type _mod_time;
|
||||
|
||||
// Transparency data
|
||||
/// The return value when reading transparency data.
|
||||
png_return_value::type _valid_transparency_factors;
|
||||
/// The transparency data.
|
||||
png_trans::type _trans;
|
||||
/// The number of transparency data.
|
||||
png_num_trans::type _num_trans;
|
||||
/// The transparency data values.
|
||||
png_trans_values::type _trans_values;
|
||||
};
|
||||
|
||||
/// Read information for png images.
|
||||
///
|
||||
/// The structure is returned when using read_image_info.
|
||||
template<>
|
||||
struct image_read_info< png_tag > : public png_info_base
|
||||
{
|
||||
/// Default constructor.
|
||||
image_read_info< png_tag >()
|
||||
: png_info_base()
|
||||
{}
|
||||
};
|
||||
|
||||
/// PNG settings base class.
|
||||
///
|
||||
/// This base structure was created to avoid code doubling.
|
||||
struct png_read_settings_base
|
||||
{
|
||||
/// Default Constructor.
|
||||
png_read_settings_base()
|
||||
{
|
||||
_read_cie_chromacities = false;
|
||||
_read_file_gamma = false;
|
||||
_read_icc_profile = false;
|
||||
_read_intent = false;
|
||||
_read_palette = false;
|
||||
_read_background = false;
|
||||
_read_histogram = false;
|
||||
_read_screen_offsets = false;
|
||||
_read_pixel_calibration = false;
|
||||
_read_physical_resolution = false;
|
||||
_read_number_of_significant_bits = false;
|
||||
_read_scale_factors = false;
|
||||
_read_comments = false;
|
||||
_read_last_modification_time = false;
|
||||
_read_transparency_data = false;
|
||||
}
|
||||
|
||||
/// Helper function to enabling reading all png properties.
|
||||
void set_read_members_true()
|
||||
{
|
||||
_read_cie_chromacities = true;
|
||||
_read_file_gamma = true;
|
||||
_read_icc_profile = true;
|
||||
_read_intent = true;
|
||||
_read_palette = true;
|
||||
_read_background = true;
|
||||
_read_histogram = true;
|
||||
_read_screen_offsets = true;
|
||||
_read_pixel_calibration = true;
|
||||
_read_physical_resolution = true;
|
||||
_read_number_of_significant_bits = true;
|
||||
_read_scale_factors = true;
|
||||
_read_comments = true;
|
||||
_read_last_modification_time = true;
|
||||
_read_transparency_data = true;
|
||||
}
|
||||
|
||||
/// Enable reading CIE chromacities.
|
||||
bool _read_cie_chromacities;
|
||||
/// Enable reading file gamma.
|
||||
bool _read_file_gamma;
|
||||
/// Enable reading ICC profile.
|
||||
bool _read_icc_profile;
|
||||
/// Enable reading rendering intent.
|
||||
bool _read_intent;
|
||||
/// Enable reading color palette.
|
||||
bool _read_palette;
|
||||
/// Enable reading background color.
|
||||
bool _read_background;
|
||||
/// Enable reading histogram.
|
||||
bool _read_histogram;
|
||||
/// Enable reading screen offsets.
|
||||
bool _read_screen_offsets;
|
||||
/// Enable reading pixel calibration.
|
||||
bool _read_pixel_calibration;
|
||||
/// Enable reading physical resolution.
|
||||
bool _read_physical_resolution;
|
||||
/// Enable reading significant bits.
|
||||
bool _read_number_of_significant_bits;
|
||||
/// Enable reading scaling factors.
|
||||
bool _read_scale_factors;
|
||||
/// Enable reading comments.
|
||||
bool _read_comments;
|
||||
/// Enable reading modification time.
|
||||
bool _read_last_modification_time;
|
||||
/// Enable reading transparency data.
|
||||
bool _read_transparency_data;
|
||||
};
|
||||
|
||||
#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
|
||||
|
||||
/// Read settings for png images.
|
||||
///
|
||||
/// The structure can be used for all read_xxx functions, except read_image_info.
|
||||
template<>
|
||||
struct image_read_settings< png_tag > : public image_read_settings_base
|
||||
, public png_read_settings_base
|
||||
{
|
||||
/// Default Constructor
|
||||
image_read_settings< png_tag >()
|
||||
: image_read_settings_base()
|
||||
, png_read_settings_base()
|
||||
, _screen_gamma( 1.0 )
|
||||
{}
|
||||
|
||||
/// Constructor
|
||||
/// \param top_left Top left coordinate for reading partial image.
|
||||
/// \param dim Dimensions for reading partial image.
|
||||
/// \param gamma Screen gamma value.
|
||||
image_read_settings( const point_t& top_left
|
||||
, const point_t& dim
|
||||
, double gamma = 1.0
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
)
|
||||
, png_read_settings_base()
|
||||
, _apply_screen_gamma( false )
|
||||
, _screen_gamma( screen_gamma )
|
||||
{}
|
||||
|
||||
/// Apply screen gamma value.
|
||||
bool _apply_screen_gamma;
|
||||
/// The screen gamma value.
|
||||
png_gamma::type _screen_gamma;
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
/// Read settings for png images.
|
||||
///
|
||||
/// The structure can be used for all read_xxx functions, except read_image_info.
|
||||
template<>
|
||||
struct image_read_settings< png_tag > : public image_read_settings_base
|
||||
, public png_read_settings_base
|
||||
{
|
||||
/// Default Constructor.
|
||||
image_read_settings< png_tag >()
|
||||
: image_read_settings_base()
|
||||
, png_read_settings_base()
|
||||
{}
|
||||
|
||||
image_read_settings( const point_t& top_left
|
||||
, const point_t& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
)
|
||||
, png_read_settings_base()
|
||||
, _apply_screen_gamma( false )
|
||||
, _screen_gamma ( 2 )
|
||||
{}
|
||||
|
||||
/// Apply screen gamma value.
|
||||
bool _apply_screen_gamma;
|
||||
/// The screen gamma value.
|
||||
png_gamma::type _screen_gamma;
|
||||
};
|
||||
#endif
|
||||
|
||||
/// Write information for png images.
|
||||
///
|
||||
/// The structure can be used for write_view() function.
|
||||
template<>
|
||||
struct image_write_info< png_tag > : public png_info_base
|
||||
{
|
||||
image_write_info()
|
||||
: png_info_base()
|
||||
{}
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNG_TAGS_HPP
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNG_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNG_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "png_tags.hpp"
|
||||
#include "formats/png/supported_types.hpp"
|
||||
#include "formats/png/write.hpp"
|
||||
|
||||
#include "detail/write_view.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNG_WRITE_HPP
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_ALL_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_ALL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pnm_read.hpp"
|
||||
#include "pnm_write.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_ALL_HPP
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_IO_OLD_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_IO_OLD_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pnm_all.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Returns the width and height of the PNM file at the specified location.
|
||||
/// Throws std::ios_base::failure if the location does not correspond to a valid PNM file
|
||||
template< typename String >
|
||||
inline
|
||||
point2< std::ptrdiff_t > pnm_read_dimensions( const String& filename )
|
||||
{
|
||||
image_read_info< pnm_tag > info = read_image_info( filename
|
||||
, pnm_tag()
|
||||
);
|
||||
|
||||
return point2< std::ptrdiff_t >( info._width
|
||||
, info._height
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Loads the image specified by the given pnm image file name into the given view.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the PNM library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNM 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 pnm_read_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_view( filename
|
||||
, view
|
||||
, pnm_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given pnm 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 PNM library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNM 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 pnm_read_image( const String& filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_image( filename
|
||||
, img
|
||||
, pnm_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Loads and color-converts the image specified by the given pnm image file name into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNM file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void pnm_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, cc
|
||||
, pnm_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Loads and color-converts the image specified by the given pnm image file name into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNM file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
>
|
||||
inline
|
||||
void pnm_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, pnm_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given pnm image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNM file
|
||||
template< typename String
|
||||
, typename Image
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void pnm_read_and_convert_image( const String& filename
|
||||
, Image& img
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, cc
|
||||
, pnm_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given pnm image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid PNM file
|
||||
template< typename String
|
||||
, typename Image
|
||||
>
|
||||
inline
|
||||
void pnm_read_and_convert_image( const String filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, pnm_tag()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup PNM_IO
|
||||
/// \brief Saves the view to a pnm file specified by the given pnm image file name.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the PNM 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 pnm_write_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
write_view( filename
|
||||
, view
|
||||
, pnm_tag()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_IO_OLD_HPP
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pnm_tags.hpp"
|
||||
#include "formats/pnm/supported_types.hpp"
|
||||
#include "formats/pnm/read.hpp"
|
||||
|
||||
#include "detail/read_image.hpp"
|
||||
#include "detail/read_view.hpp"
|
||||
#include "detail/read_image_info.hpp"
|
||||
#include "detail/read_and_convert_image.hpp"
|
||||
#include "detail/read_and_convert_view.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_READ_HPP
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_TAGS_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_TAGS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/mpl/integral_c.hpp>
|
||||
|
||||
#include "detail/base.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// Defines pnm tag.
|
||||
struct pnm_tag : format_tag {};
|
||||
|
||||
/// see http://en.wikipedia.org/wiki/Portable_Bitmap_File_Format for reference
|
||||
|
||||
/// Defines type for image type property.
|
||||
struct pnm_image_type : property_base< uint32_t >
|
||||
{
|
||||
typedef boost::mpl::integral_c< type, 1 > mono_asc_t;
|
||||
typedef boost::mpl::integral_c< type, 2 > gray_asc_t;
|
||||
typedef boost::mpl::integral_c< type, 3 > color_asc_t;
|
||||
|
||||
typedef boost::mpl::integral_c< type, 4 > mono_bin_t;
|
||||
typedef boost::mpl::integral_c< type, 5 > gray_bin_t;
|
||||
typedef boost::mpl::integral_c< type, 6 > color_bin_t;
|
||||
};
|
||||
|
||||
/// Defines type for image width property.
|
||||
struct pnm_image_width : property_base< uint32_t > {};
|
||||
|
||||
/// Defines type for image height property.
|
||||
struct pnm_image_height : property_base< uint32_t > {};
|
||||
|
||||
/// Defines type for image max value property.
|
||||
struct pnm_image_max_value : property_base< uint32_t > {};
|
||||
|
||||
/// Read information for pnm images.
|
||||
///
|
||||
/// The structure is returned when using read_image_info.
|
||||
template<>
|
||||
struct image_read_info< pnm_tag >
|
||||
{
|
||||
/// The image type.
|
||||
pnm_image_type::type _type;
|
||||
/// The image width.
|
||||
pnm_image_width::type _width;
|
||||
/// The image height.
|
||||
pnm_image_height::type _height;
|
||||
/// The image max value.
|
||||
pnm_image_max_value::type _max_value;
|
||||
};
|
||||
|
||||
/// Read settings for pnm images.
|
||||
///
|
||||
/// The structure can be used for all read_xxx functions, except read_image_info.
|
||||
template<>
|
||||
struct image_read_settings< pnm_tag > : public image_read_settings_base
|
||||
{
|
||||
/// Default constructor
|
||||
image_read_settings< pnm_tag >()
|
||||
: image_read_settings_base()
|
||||
{}
|
||||
|
||||
/// Constructor
|
||||
/// \param top_left Top left coordinate for reading partial image.
|
||||
/// \param dim Dimensions for reading partial image.
|
||||
image_read_settings( const point_t& top_left
|
||||
, const point_t& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
)
|
||||
{}
|
||||
};
|
||||
|
||||
/// Write information for pnm images.
|
||||
///
|
||||
/// The structure can be used for write_view() function.
|
||||
template<>
|
||||
struct image_write_info< pnm_tag >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_TAGS_HPP
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_PNM_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_PNM_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "pnm_tags.hpp"
|
||||
#include "formats/pnm/supported_types.hpp"
|
||||
#include "formats/pnm/write.hpp"
|
||||
|
||||
#include "detail/write_view.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_PNM_WRITE_HPP
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_TIFF_ALL_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_ALL_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tiff_read.hpp"
|
||||
#include "tiff_write.hpp"
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_ALL_HPP
|
||||
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_TIFF_IO_OLD_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_IO_OLD_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tiff_all.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Returns the width and height of the TIFF file at the specified location.
|
||||
/// Throws std::ios_base::failure if the location does not correspond to a valid TIFF file
|
||||
template< typename String >
|
||||
inline
|
||||
point2< std::ptrdiff_t > tiff_read_dimensions( const String& filename )
|
||||
{
|
||||
image_read_info< tiff_tag > info = read_image_info( filename
|
||||
, tiff_tag()
|
||||
);
|
||||
|
||||
return point2< std::ptrdiff_t >( info._width
|
||||
, info._height
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Loads the image specified by the given tiff image file name into the given view.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid TIFF 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 tiff_read_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_view( filename
|
||||
, view
|
||||
, tiff_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given tiff 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 TIFF library or by the I/O extension.
|
||||
/// Throws std::ios_base::failure if the file is not a valid TIFF 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 tiff_read_image( const String& filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_image( filename
|
||||
, img
|
||||
, tiff_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void tiff_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, cc
|
||||
, tiff_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
|
||||
/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view.
|
||||
template< typename String
|
||||
, typename View
|
||||
>
|
||||
inline
|
||||
void tiff_read_and_convert_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
read_and_convert_view( filename
|
||||
, view
|
||||
, tiff_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid TIFF file
|
||||
template< typename String
|
||||
, typename Image
|
||||
, typename CC
|
||||
>
|
||||
inline
|
||||
void tiff_read_and_convert_image( const String& filename
|
||||
, Image& img
|
||||
, CC cc
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, cc
|
||||
, tiff_tag()
|
||||
);
|
||||
}
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
|
||||
/// Throws std::ios_base::failure if the file is not a valid TIFF file
|
||||
template< typename String
|
||||
, typename Image
|
||||
>
|
||||
inline
|
||||
void tiff_read_and_convert_image( const String filename
|
||||
, Image& img
|
||||
)
|
||||
{
|
||||
read_and_convert_image( filename
|
||||
, img
|
||||
, tiff_tag()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup TIFF_IO
|
||||
/// \brief Saves the view to a tiff file specified by the given tiff image file name.
|
||||
/// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF 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 tiff_write_view( const String& filename
|
||||
, const View& view
|
||||
)
|
||||
{
|
||||
write_view( filename
|
||||
, view
|
||||
, tiff_tag()
|
||||
);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_IO_OLD_HPP
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_TIFF_READ_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_READ_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tiff_tags.hpp"
|
||||
#include "formats/tiff/supported_types.hpp"
|
||||
#include "formats/tiff/read.hpp"
|
||||
|
||||
#include "detail/read_image_info.hpp"
|
||||
#include "detail/read_view.hpp"
|
||||
#include "detail/read_image.hpp"
|
||||
#include "detail/read_and_convert_image.hpp"
|
||||
#include "detail/read_and_convert_view.hpp"
|
||||
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_READ_HPP
|
||||
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_TIFF_TAGS_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_TAGS_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief All supported tiff tags by the gil io extension.
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern "C" {
|
||||
#include "tiff.h"
|
||||
}
|
||||
|
||||
#include "detail/base.hpp"
|
||||
#include "formats/tiff/log.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// Defines tiff tag.
|
||||
struct tiff_tag : format_tag {};
|
||||
|
||||
/// For a description see: http://www.awaresystems.be/imaging/tiff/tifftags/baseline.html
|
||||
/// see http://www.remotesensing.org/libtiff/
|
||||
/// or http://www.libtiff.org/man/
|
||||
|
||||
/// TIFF property base class
|
||||
template< typename T, int Value >
|
||||
struct tiff_property_base : property_base< T >
|
||||
{
|
||||
/// Tag, needed when reading or writing image properties.
|
||||
static const unsigned int tag = Value;
|
||||
};
|
||||
|
||||
/// baseline tags
|
||||
|
||||
/// Defines type for new subfile property.
|
||||
struct tiff_new_subfile_type : tiff_property_base< uint32_t, TIFFTAG_SUBFILETYPE > {};
|
||||
|
||||
/// Defines type for subfile property.
|
||||
struct tiff_subfile_type : tiff_property_base< uint16_t, TIFFTAG_OSUBFILETYPE > {};
|
||||
|
||||
/// Defines type for image width property.
|
||||
struct tiff_image_width : tiff_property_base< uint32_t, TIFFTAG_IMAGEWIDTH > {};
|
||||
|
||||
/// Defines type for image height property.
|
||||
struct tiff_image_height : tiff_property_base< uint32_t, TIFFTAG_IMAGELENGTH > {};
|
||||
|
||||
/// Defines type for bits per sample property.
|
||||
struct tiff_bits_per_sample : tiff_property_base< uint16_t, TIFFTAG_BITSPERSAMPLE > {};
|
||||
|
||||
/// Defines type for compression property.
|
||||
struct tiff_compression : tiff_property_base< uint16_t, TIFFTAG_COMPRESSION > {};
|
||||
|
||||
/// Defines type for photometric interpretation property.
|
||||
struct tiff_photometric_interpretation : tiff_property_base< uint16_t, TIFFTAG_PHOTOMETRIC > {};
|
||||
|
||||
/// Defines type for threshold property.
|
||||
struct tiff_thresholding : tiff_property_base< uint16_t, TIFFTAG_THRESHHOLDING > {};
|
||||
|
||||
/// Defines type for cell width property.
|
||||
struct tiff_cell_width : tiff_property_base< uint16_t, TIFFTAG_CELLWIDTH > {};
|
||||
|
||||
/// Defines type for cell length property.
|
||||
struct tiff_cell_length : tiff_property_base< uint16_t, TIFFTAG_CELLLENGTH > {};
|
||||
|
||||
/// Defines type for fill order property.
|
||||
struct tiff_fill_order : tiff_property_base< std::string, TIFFTAG_FILLORDER > {};
|
||||
|
||||
/// Defines type for image description.
|
||||
struct tiff_image_description : tiff_property_base< std::string, TIFFTAG_IMAGEDESCRIPTION > {};
|
||||
|
||||
/// Defines type for make property.
|
||||
struct tiff_make : tiff_property_base< std::string, TIFFTAG_MAKE > {};
|
||||
|
||||
/// Defines type for model property.
|
||||
struct tiff_model : tiff_property_base< std::string, TIFFTAG_MODEL > {};
|
||||
|
||||
/// Defines type for image orientation.
|
||||
struct tiff_orientation : tiff_property_base< uint16_t, TIFFTAG_ORIENTATION > {};
|
||||
|
||||
/// Defines type for samples per pixel property.
|
||||
struct tiff_samples_per_pixel : tiff_property_base< uint16_t, TIFFTAG_SAMPLESPERPIXEL > {};
|
||||
|
||||
/// Defines type for rows per strip property.
|
||||
struct tiff_rows_per_strip : tiff_property_base< uint32_t, TIFFTAG_ROWSPERSTRIP > {};
|
||||
|
||||
/// Defines type for min sample property.
|
||||
struct tiff_min_sample_value : tiff_property_base< uint16_t, TIFFTAG_MINSAMPLEVALUE > {};
|
||||
|
||||
/// Defines type for max sample property.
|
||||
struct tiff_max_sample_value : tiff_property_base< uint16_t, TIFFTAG_MAXSAMPLEVALUE > {};
|
||||
|
||||
/// Defines type for x resolution property.
|
||||
struct tiff_x_resolution : tiff_property_base< float, TIFFTAG_XRESOLUTION > {};
|
||||
|
||||
/// Defines type for y resolution property.
|
||||
struct tiff_y_resolution : tiff_property_base< float, TIFFTAG_YRESOLUTION > {};
|
||||
|
||||
/// Defines type for resolution unit property.
|
||||
struct tiff_resolution_unit : tiff_property_base< uint16_t, TIFFTAG_RESOLUTIONUNIT > {};
|
||||
|
||||
/// Defines type for planar configuration property.
|
||||
struct tiff_planar_configuration : tiff_property_base< uint16_t, TIFFTAG_PLANARCONFIG > {};
|
||||
|
||||
/// Defines type for gray response unit property.
|
||||
struct tiff_gray_response_unit : tiff_property_base< uint16_t, TIFFTAG_GRAYRESPONSEUNIT > {};
|
||||
|
||||
/// Defines type for gray response curve property.
|
||||
struct tiff_gray_response_curve : tiff_property_base< uint16_t*, TIFFTAG_GRAYRESPONSECURVE > {};
|
||||
|
||||
/// Defines type for software vendor property.
|
||||
struct tiff_software : tiff_property_base< std::string, TIFFTAG_SOFTWARE > {};
|
||||
|
||||
/// Defines type for date time property.
|
||||
struct tiff_date_time : tiff_property_base< std::string, TIFFTAG_DATETIME > {};
|
||||
|
||||
/// Defines type for artist information property.
|
||||
struct tiff_artist : tiff_property_base< std::string, TIFFTAG_ARTIST > {};
|
||||
|
||||
/// Defines type for host computer property.
|
||||
struct tiff_host_computer : tiff_property_base< std::string, TIFFTAG_HOSTCOMPUTER > {};
|
||||
|
||||
/// Helper structure for reading a color mapper.
|
||||
struct tiff_color_map
|
||||
{
|
||||
typedef uint16_t* red_t;
|
||||
typedef uint16_t* green_t;
|
||||
typedef uint16_t* blue_t;
|
||||
|
||||
static const unsigned int tag = TIFFTAG_COLORMAP;
|
||||
};
|
||||
|
||||
/// Defines type for extra samples property.
|
||||
struct tiff_extra_samples : tiff_property_base< uint16_t*, TIFFTAG_EXTRASAMPLES > {};
|
||||
|
||||
/// Defines type for copyright property.
|
||||
struct tiff_copyright : tiff_property_base< std::string, TIFFTAG_COPYRIGHT > {};
|
||||
|
||||
/// non-baseline tags
|
||||
|
||||
/// Defines type for sample format property.
|
||||
struct tiff_sample_format : tiff_property_base< uint16_t, TIFFTAG_SAMPLEFORMAT > {};
|
||||
|
||||
/// Defines type for indexed property.
|
||||
struct tiff_indexed : tiff_property_base< bool, TIFFTAG_INDEXED > {};
|
||||
|
||||
/// Tile related tags
|
||||
|
||||
/// Defines type for a (not) tiled tiff image
|
||||
struct tiff_is_tiled : tiff_property_base< bool, false > {};
|
||||
|
||||
/// Defines type for tile width
|
||||
struct tiff_tile_width : tiff_property_base< long, TIFFTAG_TILEWIDTH > {};
|
||||
|
||||
/// Defines type for tile length
|
||||
struct tiff_tile_length : tiff_property_base< long, TIFFTAG_TILELENGTH > {};
|
||||
|
||||
/// Defines the page to read in a multipage tiff file.
|
||||
#include <boost/mpl/integral_c.hpp>
|
||||
struct tiff_directory : property_base< tdir_t >
|
||||
{
|
||||
typedef boost::mpl::integral_c< type, 0 > default_value;
|
||||
};
|
||||
|
||||
/// Read information for tiff images.
|
||||
///
|
||||
/// The structure is returned when using read_image_info.
|
||||
template<>
|
||||
struct image_read_info< tiff_tag >
|
||||
{
|
||||
image_read_info()
|
||||
: _width( 0 )
|
||||
, _height( 0 )
|
||||
|
||||
, _compression( COMPRESSION_NONE )
|
||||
|
||||
, _bits_per_sample( 0 )
|
||||
, _samples_per_pixel( 0 )
|
||||
, _sample_format( SAMPLEFORMAT_UINT )
|
||||
|
||||
, _planar_configuration( PLANARCONFIG_CONTIG )
|
||||
|
||||
, _photometric_interpretation( PHOTOMETRIC_MINISWHITE )
|
||||
|
||||
, _is_tiled( false )
|
||||
|
||||
, _tile_width ( 0 )
|
||||
, _tile_length( 0 )
|
||||
{}
|
||||
|
||||
/// The number of rows of pixels in the image.
|
||||
tiff_image_width::type _width;
|
||||
/// The number of columns in the image, i.e., the number of pixels per row.
|
||||
tiff_image_height::type _height;
|
||||
|
||||
/// Compression scheme used on the image data.
|
||||
tiff_compression::type _compression;
|
||||
|
||||
/// Number of bits per component.
|
||||
tiff_bits_per_sample::type _bits_per_sample;
|
||||
/// The number of components per pixel.
|
||||
tiff_samples_per_pixel::type _samples_per_pixel;
|
||||
/// Specifies how to interpret each data sample in a pixel.
|
||||
tiff_sample_format::type _sample_format;
|
||||
|
||||
/// How the components of each pixel are stored.
|
||||
tiff_planar_configuration::type _planar_configuration;
|
||||
|
||||
/// The color space of the image data.
|
||||
tiff_photometric_interpretation::type _photometric_interpretation;
|
||||
|
||||
/// Is tiled?
|
||||
tiff_is_tiled::type _is_tiled;
|
||||
/// Tile width
|
||||
tiff_tile_width::type _tile_width;
|
||||
/// Tile length
|
||||
tiff_tile_length::type _tile_length;
|
||||
};
|
||||
|
||||
/// Read settings for tiff images.
|
||||
///
|
||||
/// The structure can be used for all read_xxx functions, except read_image_info.
|
||||
template<>
|
||||
struct image_read_settings< tiff_tag > : public image_read_settings_base
|
||||
{
|
||||
/// Default constructor
|
||||
image_read_settings< tiff_tag >()
|
||||
: image_read_settings_base()
|
||||
, _directory( tiff_directory::default_value::value )
|
||||
{}
|
||||
|
||||
/// Constructor
|
||||
/// \param top_left Top left coordinate for reading partial image.
|
||||
/// \param dim Dimensions for reading partial image.
|
||||
/// \param directory Defines the page to read in a multipage tiff file.
|
||||
image_read_settings( const point_t& top_left
|
||||
, const point_t& dim
|
||||
, const tiff_directory::type& directory = tiff_directory::default_value::value
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
)
|
||||
, _directory( directory )
|
||||
{}
|
||||
|
||||
/// Defines the page to read in a multipage tiff file.
|
||||
tiff_directory::type _directory;
|
||||
};
|
||||
|
||||
/// Read settings for tiff images.
|
||||
///
|
||||
/// The structure can be used for all read_xxx functions, except read_image_info.
|
||||
template< typename Log >
|
||||
struct image_write_info< tiff_tag, Log >
|
||||
{
|
||||
/// Default constructor
|
||||
image_write_info()
|
||||
: _photometric_interpretation( PHOTOMETRIC_MINISBLACK )
|
||||
, _compression ( COMPRESSION_NONE )
|
||||
, _orientation ( ORIENTATION_TOPLEFT )
|
||||
, _planar_configuration ( PLANARCONFIG_CONTIG )
|
||||
, _is_tiled ( false )
|
||||
, _tile_width ( 0 )
|
||||
, _tile_length ( 0 )
|
||||
{}
|
||||
|
||||
/// The color space of the image data.
|
||||
tiff_photometric_interpretation::type _photometric_interpretation;
|
||||
/// Compression scheme used on the image data.
|
||||
tiff_compression::type _compression;
|
||||
/// The orientation of the image with respect to the rows and columns.
|
||||
tiff_orientation::type _orientation;
|
||||
/// How the components of each pixel are stored.
|
||||
tiff_planar_configuration::type _planar_configuration;
|
||||
|
||||
/// Is the image tiled?
|
||||
tiff_is_tiled::type _is_tiled;
|
||||
/// Tiles width
|
||||
tiff_tile_width::type _tile_width;
|
||||
/// Tiles length
|
||||
tiff_tile_length::type _tile_length;
|
||||
|
||||
/// A log to transcript error and warning messages issued by libtiff.
|
||||
Log _log;
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_TAGS_HPP
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2007-2008 Christian Henning
|
||||
Use, modification and distribution are subject to 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_TIFF_WRITE_HPP
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_WRITE_HPP
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Christian Henning \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "tiff_tags.hpp"
|
||||
#include "formats/tiff/supported_types.hpp"
|
||||
#include "formats/tiff/write.hpp"
|
||||
|
||||
#include "detail/write_view.hpp"
|
||||
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_IO_TIFF_WRITE_HPP
|
||||
Executable
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_AFFINE_HPP
|
||||
#define GIL_AFFINE_HPP
|
||||
|
||||
#include "boost/gil/utilities.hpp" // point2
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief support for affine transformations
|
||||
/// \author Lubomir Bourdev and Hailin Jin \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n September 21, 2006
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// Simple matrix to do 2D affine transformations. It is actually 3x3 but the last column is [0 0 1]
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename T>
|
||||
class matrix3x2 {
|
||||
public:
|
||||
matrix3x2() : a(1), b(0), c(0), d(1), e(0), f(0) {}
|
||||
matrix3x2(T A, T B, T C, T D, T E, T F) : a(A),b(B),c(C),d(D),e(E),f(F) {}
|
||||
matrix3x2(const matrix3x2& mat) : a(mat.a), b(mat.b), c(mat.c), d(mat.d), e(mat.e), f(mat.f) {}
|
||||
matrix3x2& operator=(const matrix3x2& m) { a=m.a; b=m.b; c=m.c; d=m.d; e=m.e; f=m.f; return *this; }
|
||||
|
||||
matrix3x2& operator*=(const matrix3x2& m) { (*this) = (*this)*m; return *this; }
|
||||
|
||||
static matrix3x2 get_rotate(T rads) { T c=std::cos(rads); T s=std::sin(rads); return matrix3x2(c,s,-s,c,0,0); }
|
||||
static matrix3x2 get_translate(const point2<T>& t) { return matrix3x2(1 ,0,0,1 ,t.x,t.y); }
|
||||
static matrix3x2 get_translate(T x, T y) { return matrix3x2(1 ,0,0,1 ,x, y ); }
|
||||
static matrix3x2 get_scale (const point2<T>& s) { return matrix3x2(s.x,0,0,s.y,0 ,0 ); }
|
||||
static matrix3x2 get_scale (T x, T y) { return matrix3x2(x, 0,0,y, 0 ,0 ); }
|
||||
static matrix3x2 get_scale (T s) { return matrix3x2(s ,0,0,s ,0 ,0 ); }
|
||||
|
||||
T a,b,c,d,e,f;
|
||||
};
|
||||
|
||||
template <typename T> GIL_FORCEINLINE
|
||||
matrix3x2<T> operator*(const matrix3x2<T>& m1, const matrix3x2<T>& m2) {
|
||||
return matrix3x2<T>(
|
||||
m1.a * m2.a + m1.b * m2.c,
|
||||
m1.a * m2.b + m1.b * m2.d,
|
||||
m1.c * m2.a + m1.d * m2.c,
|
||||
m1.c * m2.b + m1.d * m2.d,
|
||||
m1.e * m2.a + m1.f * m2.c + m2.e,
|
||||
m1.e * m2.b + m1.f * m2.d + m2.f );
|
||||
}
|
||||
|
||||
template <typename T, typename F> GIL_FORCEINLINE
|
||||
point2<F> operator*(const point2<T>& p, const matrix3x2<F>& m) {
|
||||
return point2<F>(m.a*p.x + m.c*p.y + m.e, m.b*p.x + m.d*p.y + m.f);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// Define affine mapping that transforms the source coordinates by the affine transformation
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
template <typename MapFn>
|
||||
concept MappingFunctionConcept {
|
||||
typename mapping_traits<MapFn>::result_type; where PointNDConcept<result_type>;
|
||||
|
||||
template <typename Domain> { where PointNDConcept<Domain> }
|
||||
result_type transform(MapFn&, const Domain& src);
|
||||
};
|
||||
*/
|
||||
|
||||
template <typename T> struct mapping_traits;
|
||||
|
||||
template <typename F>
|
||||
struct mapping_traits<matrix3x2<F> > {
|
||||
typedef point2<F> result_type;
|
||||
};
|
||||
|
||||
template <typename F, typename F2> GIL_FORCEINLINE
|
||||
point2<F> transform(const matrix3x2<F>& mat, const point2<F2>& src) { return src * mat; }
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
Executable
+155
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_NUMERIC_ALGORITHM_HPP
|
||||
#define GIL_NUMERIC_ALGORITHM_HPP
|
||||
|
||||
/*!
|
||||
/// \file
|
||||
/// \brief Numeric algorithms
|
||||
/// \author Hailin Jin and Lubomir Bourdev \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n Last updated on February 6, 2007
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
#include "../../gil_config.hpp"
|
||||
#include "../../pixel_iterator.hpp"
|
||||
#include "../../metafunctions.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \brief Returns the reference proxy associated with a type that has a \p "reference" member typedef.
|
||||
///
|
||||
/// The reference proxy is the reference type, but with stripped-out C++ reference. It models PixelConcept
|
||||
template <typename T>
|
||||
struct pixel_proxy : public remove_reference<typename T::reference> {};
|
||||
|
||||
/// \brief std::for_each for a pair of iterators
|
||||
template <typename Iterator1,typename Iterator2,typename BinaryFunction>
|
||||
BinaryFunction for_each(Iterator1 first1,Iterator1 last1,Iterator2 first2,BinaryFunction f) {
|
||||
while(first1!=last1)
|
||||
f(*first1++,*first2++);
|
||||
return f;
|
||||
}
|
||||
|
||||
template <typename SrcIterator,typename DstIterator>
|
||||
inline DstIterator assign_pixels(SrcIterator src,SrcIterator src_end,DstIterator dst) {
|
||||
for_each(src,src_end,dst,pixel_assigns_t<typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
|
||||
typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type>());
|
||||
return dst+(src_end-src);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <std::size_t Size>
|
||||
struct inner_product_k_t {
|
||||
template <class _InputIterator1, class _InputIterator2, class _Tp,
|
||||
class _BinaryOperation1, class _BinaryOperation2>
|
||||
static _Tp apply(_InputIterator1 __first1,
|
||||
_InputIterator2 __first2, _Tp __init,
|
||||
_BinaryOperation1 __binary_op1,
|
||||
_BinaryOperation2 __binary_op2) {
|
||||
__init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
|
||||
return inner_product_k_t<Size-1>::template apply(__first1+1,__first2+1,__init,
|
||||
__binary_op1, __binary_op2);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct inner_product_k_t<0> {
|
||||
template <class _InputIterator1, class _InputIterator2, class _Tp,
|
||||
class _BinaryOperation1, class _BinaryOperation2>
|
||||
static _Tp apply(_InputIterator1 __first1,
|
||||
_InputIterator2 __first2, _Tp __init,
|
||||
_BinaryOperation1 __binary_op1,
|
||||
_BinaryOperation2 __binary_op2) {
|
||||
return __init;
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// static version of std::inner_product
|
||||
template <std::size_t Size,
|
||||
class _InputIterator1, class _InputIterator2, class _Tp,
|
||||
class _BinaryOperation1, class _BinaryOperation2>
|
||||
GIL_FORCEINLINE
|
||||
_Tp inner_product_k(_InputIterator1 __first1,
|
||||
_InputIterator2 __first2,
|
||||
_Tp __init,
|
||||
_BinaryOperation1 __binary_op1,
|
||||
_BinaryOperation2 __binary_op2) {
|
||||
return detail::inner_product_k_t<Size>::template apply(__first1,__first2,__init,
|
||||
__binary_op1, __binary_op2);
|
||||
}
|
||||
|
||||
/// \brief 1D un-guarded correlation with a variable-size kernel
|
||||
template <typename PixelAccum,typename SrcIterator,typename KernelIterator,typename Integer,typename DstIterator>
|
||||
inline DstIterator correlate_pixels_n(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,Integer ker_size,
|
||||
DstIterator dst_begin) {
|
||||
typedef typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type PIXEL_SRC_REF;
|
||||
typedef typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type PIXEL_DST_REF;
|
||||
typedef typename std::iterator_traits<KernelIterator>::value_type kernel_type;
|
||||
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
|
||||
while(src_begin!=src_end) {
|
||||
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
|
||||
std::inner_product(src_begin,src_begin+ker_size,ker_begin,acc_zero,
|
||||
pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
|
||||
pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
|
||||
*dst_begin);
|
||||
++src_begin; ++dst_begin;
|
||||
}
|
||||
return dst_begin;
|
||||
}
|
||||
|
||||
/// \brief 1D un-guarded correlation with a fixed-size kernel
|
||||
template <std::size_t Size,typename PixelAccum,typename SrcIterator,typename KernelIterator,typename DstIterator>
|
||||
inline DstIterator correlate_pixels_k(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,
|
||||
DstIterator dst_begin) {
|
||||
typedef typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type PIXEL_SRC_REF;
|
||||
typedef typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type PIXEL_DST_REF;
|
||||
typedef typename std::iterator_traits<KernelIterator>::value_type kernel_type;
|
||||
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
|
||||
while(src_begin!=src_end) {
|
||||
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
|
||||
inner_product_k<Size>(src_begin,ker_begin,acc_zero,
|
||||
pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
|
||||
pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
|
||||
*dst_begin);
|
||||
++src_begin; ++dst_begin;
|
||||
}
|
||||
return dst_begin;
|
||||
}
|
||||
|
||||
/// \brief destination is set to be product of the source and a scalar
|
||||
template <typename PixelAccum,typename SrcView,typename Scalar,typename DstView>
|
||||
inline void view_multiplies_scalar(const SrcView& src,const Scalar& scalar,const DstView& dst) {
|
||||
assert(src.dimensions()==dst.dimensions());
|
||||
typedef typename pixel_proxy<typename SrcView::value_type>::type PIXEL_SRC_REF;
|
||||
typedef typename pixel_proxy<typename DstView::value_type>::type PIXEL_DST_REF;
|
||||
int height=src.height();
|
||||
for(int rr=0;rr<height;++rr) {
|
||||
typename SrcView::x_iterator it_src=src.row_begin(rr);
|
||||
typename DstView::x_iterator it_dst=dst.row_begin(rr);
|
||||
typename SrcView::x_iterator it_src_end=src.row_end(rr);
|
||||
while(it_src!=it_src_end) {
|
||||
pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
|
||||
pixel_multiplies_scalar_t<PIXEL_SRC_REF,Scalar,PixelAccum>()(*it_src,scalar),
|
||||
*it_dst);
|
||||
++it_src; ++it_dst;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
|
||||
#define GIL_CHANNEL_NUMERIC_OPERATIONS_HPP
|
||||
|
||||
/*!
|
||||
/// \file
|
||||
/// \brief Structures for channel-wise numeric operations
|
||||
/// \author Hailin Jin and Lubomir Bourdev \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n Last updated on September 30, 2006
|
||||
/// Currently defined structures:
|
||||
/// channel_plus_t (+), channel_minus_t (-),
|
||||
/// channel_multiplies_t (*), channel_divides_t (/),
|
||||
/// channel_plus_scalar_t (+s), channel_minus_scalar_t (-s),
|
||||
/// channel_multiplies_scalar_t (*s), channel_divides_scalar_t (/s),
|
||||
/// channel_halves_t (/=2), channel_zeros_t (=0), channel_assigns_t (=)
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include "boost/gil/gil_config.hpp"
|
||||
#include "boost/gil/channel.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for adding one channel to another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_plus_t : public std::binary_function<Channel1,Channel2,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)+ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for subtracting one channel from another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_minus_t : public std::binary_function<Channel1,Channel2,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)-ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for multiplying one channel to another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_multiplies_t : public std::binary_function<Channel1,Channel2,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)*ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for dividing channels
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2,typename ChannelR>
|
||||
struct channel_divides_t : public std::binary_function<Channel1,Channel2,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::const_reference ch2) const {
|
||||
return ChannelR(ch1)/ChannelR(ch2);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for adding a scalar to a channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_plus_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch)+ChannelR(s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for subtracting a scalar from a channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_minus_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch-s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for multiplying a scalar to one channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_multiplies_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch)*ChannelR(s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for dividing a channel by a scalar
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel,typename Scalar,typename ChannelR>
|
||||
struct channel_divides_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
|
||||
ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
|
||||
const Scalar& s) const {
|
||||
return ChannelR(ch)/ChannelR(s);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for halving a channel
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel>
|
||||
struct channel_halves_t : public std::unary_function<Channel,Channel> {
|
||||
typename channel_traits<Channel>::reference
|
||||
operator()(typename channel_traits<Channel>::reference ch) const {
|
||||
return ch/=2.0;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for setting a channel to zero
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel>
|
||||
struct channel_zeros_t : public std::unary_function<Channel,Channel> {
|
||||
typename channel_traits<Channel>::reference
|
||||
operator()(typename channel_traits<Channel>::reference ch) const {
|
||||
return ch=Channel(0);
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ChannelNumericOperations
|
||||
/// structure for assigning one channel to another
|
||||
/// this is a generic implementation; user should specialize it for better performance
|
||||
template <typename Channel1,typename Channel2>
|
||||
struct channel_assigns_t : public std::binary_function<Channel1,Channel2,Channel2> {
|
||||
typename channel_traits<Channel2>::reference
|
||||
operator()(typename channel_traits<Channel1>::const_reference ch1,
|
||||
typename channel_traits<Channel2>::reference ch2) const {
|
||||
return ch2=Channel2(ch1);
|
||||
}
|
||||
};
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
Executable
+216
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_CONVOLVE_HPP
|
||||
#define GIL_CONVOLVE_HPP
|
||||
|
||||
/*!
|
||||
/// \file
|
||||
/// \brief 2D seperable convolutions and correlations
|
||||
///
|
||||
/// \author Hailin Jin and Lubomir Bourdev \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n Last updated on February 6, 2007
|
||||
*/
|
||||
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
#include "../../gil_config.hpp"
|
||||
#include "../../image_view_factory.hpp"
|
||||
#include "../../algorithm.hpp"
|
||||
#include "../../metafunctions.hpp"
|
||||
#include "pixel_numeric_operations.hpp"
|
||||
#include "algorithm.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
/// Boundary options for 1D correlations/convolutions
|
||||
enum convolve_boundary_option {
|
||||
convolve_option_output_ignore, /// do nothing to the output
|
||||
convolve_option_output_zero, /// set the output to zero
|
||||
convolve_option_extend_padded, /// assume the source boundaries to be padded already
|
||||
convolve_option_extend_zero, /// assume the source boundaries to be zero
|
||||
convolve_option_extend_constant /// assume the source boundaries to be the boundary value
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
/// compute the correlation of 1D kernel with the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView,typename Correlator>
|
||||
void correlate_rows_imp(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option,
|
||||
Correlator correlator) {
|
||||
assert(src.dimensions()==dst.dimensions());
|
||||
assert(ker.size()!=0);
|
||||
|
||||
typedef typename pixel_proxy<typename SrcView::value_type>::type PIXEL_SRC_REF;
|
||||
typedef typename pixel_proxy<typename DstView::value_type>::type PIXEL_DST_REF;
|
||||
typedef typename Kernel::value_type kernel_type;
|
||||
|
||||
if(ker.size()==1) {//reduces to a multiplication
|
||||
view_multiplies_scalar<PixelAccum>(src,*ker.begin(),dst);
|
||||
return;
|
||||
}
|
||||
|
||||
int width=src.width(),height=src.height();
|
||||
PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
|
||||
if (width==0) return;
|
||||
if (option==convolve_option_output_ignore || option==convolve_option_output_zero) {
|
||||
typename DstView::value_type dst_zero; pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(acc_zero,dst_zero);
|
||||
if (width<(int)ker.size()) {
|
||||
if (option==convolve_option_output_zero)
|
||||
fill_pixels(dst,dst_zero);
|
||||
} else {
|
||||
std::vector<PixelAccum> buffer(width);
|
||||
for(int rr=0;rr<height;++rr) {
|
||||
assign_pixels(src.row_begin(rr),src.row_end(rr),&buffer.front());
|
||||
typename DstView::x_iterator it_dst=dst.row_begin(rr);
|
||||
if (option==convolve_option_output_zero)
|
||||
std::fill_n(it_dst,ker.left_size(),dst_zero);
|
||||
it_dst+=ker.left_size();
|
||||
correlator(&buffer.front(),&buffer.front()+width+1-ker.size(),
|
||||
ker.begin(),it_dst);
|
||||
it_dst+=width+1-ker.size();
|
||||
if (option==convolve_option_output_zero)
|
||||
std::fill_n(it_dst,ker.right_size(),dst_zero);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::vector<PixelAccum> buffer(width+ker.size()-1);
|
||||
for(int rr=0;rr<height;++rr) {
|
||||
PixelAccum* it_buffer=&buffer.front();
|
||||
if (option==convolve_option_extend_padded) {
|
||||
assign_pixels(src.row_begin(rr)-ker.left_size(),
|
||||
src.row_end(rr)+ker.right_size(),
|
||||
it_buffer);
|
||||
} else if (option==convolve_option_extend_zero) {
|
||||
std::fill_n(it_buffer,ker.left_size(),acc_zero);
|
||||
it_buffer+=ker.left_size();
|
||||
assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
|
||||
it_buffer+=width;
|
||||
std::fill_n(it_buffer,ker.right_size(),acc_zero);
|
||||
} else if (option==convolve_option_extend_constant) {
|
||||
PixelAccum filler;
|
||||
pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(*src.row_begin(rr),filler);
|
||||
std::fill_n(it_buffer,ker.left_size(),filler);
|
||||
it_buffer+=ker.left_size();
|
||||
assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
|
||||
it_buffer+=width;
|
||||
pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(src.row_end(rr)[-1],filler);
|
||||
std::fill_n(it_buffer,ker.right_size(),filler);
|
||||
}
|
||||
correlator(&buffer.front(),&buffer.front()+width,
|
||||
ker.begin(),
|
||||
dst.row_begin(rr));
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename PixelAccum>
|
||||
class correlator_n {
|
||||
private:
|
||||
std::size_t _size;
|
||||
public:
|
||||
correlator_n(std::size_t size_in) : _size(size_in) {}
|
||||
template <typename SrcIterator,typename KernelIterator,typename DstIterator>
|
||||
void operator()(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,
|
||||
DstIterator dst_begin) {
|
||||
correlate_pixels_n<PixelAccum>(src_begin,src_end,ker_begin,_size,dst_begin);
|
||||
}
|
||||
};
|
||||
template <std::size_t Size,typename PixelAccum>
|
||||
struct correlator_k {
|
||||
public:
|
||||
template <typename SrcIterator,typename KernelIterator,typename DstIterator>
|
||||
void operator()(SrcIterator src_begin,SrcIterator src_end,
|
||||
KernelIterator ker_begin,
|
||||
DstIterator dst_begin){
|
||||
correlate_pixels_k<Size,PixelAccum>(src_begin,src_end,ker_begin,dst_begin);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D variable-size kernel along the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void correlate_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_n<PixelAccum>(ker.size()));
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D variable-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void correlate_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D variable-size kernel along the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void convolve_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows<PixelAccum>(src,reverse_kernel(ker),dst,option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D variable-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void convolve_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
convolve_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D fixed-size kernel along the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void correlate_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_k<Kernel::static_size,PixelAccum>());
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///correlate a 1D fixed-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void correlate_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D fixed-size kernel along the rows of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void convolve_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
correlate_rows_fixed<PixelAccum>(src,reverse_kernel(ker),dst,option);
|
||||
}
|
||||
|
||||
/// \ingroup ImageAlgorithms
|
||||
///convolve a 1D fixed-size kernel along the columns of an image
|
||||
template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
|
||||
GIL_FORCEINLINE
|
||||
void convolve_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero) {
|
||||
convolve_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
|
||||
}
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
Executable
+101
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_KERNEL_HPP
|
||||
#define GIL_KERNEL_HPP
|
||||
|
||||
/*!
|
||||
/// \file
|
||||
/// \brief Definitions of 1D fixed-size and variable-size kernels and related operations
|
||||
/// \author Hailin Jin and Lubomir Bourdev \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n Last updated on September 26, 2006
|
||||
*/
|
||||
|
||||
#include <cstddef>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <boost/array.hpp>
|
||||
#include "../../gil_config.hpp"
|
||||
#include "../../utilities.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
namespace detail {
|
||||
|
||||
/// \brief kernel adaptor for one-dimensional cores
|
||||
/// Core needs to provide size(),begin(),end(),operator[],
|
||||
/// value_type,iterator,const_iterator,reference,const_reference
|
||||
template <typename Core>
|
||||
class kernel_1d_adaptor : public Core {
|
||||
private:
|
||||
std::size_t _center;
|
||||
public:
|
||||
kernel_1d_adaptor() : _center(0) {}
|
||||
explicit kernel_1d_adaptor(std::size_t center_in) : _center(center_in) {assert(_center<this->size());}
|
||||
kernel_1d_adaptor(std::size_t size_in,std::size_t center_in) :
|
||||
Core(size_in), _center(center_in) {assert(_center<this->size());}
|
||||
kernel_1d_adaptor(const kernel_1d_adaptor& k_in) : Core(k_in), _center(k_in._center) {}
|
||||
|
||||
kernel_1d_adaptor& operator=(const kernel_1d_adaptor& k_in) {
|
||||
Core::operator=(k_in);
|
||||
_center=k_in._center;
|
||||
return *this;
|
||||
}
|
||||
std::size_t left_size() const {assert(_center<this->size());return _center;}
|
||||
std::size_t right_size() const {assert(_center<this->size());return this->size()-_center-1;}
|
||||
std::size_t& center() {return _center;}
|
||||
const std::size_t& center() const {return _center;}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief variable-size kernel
|
||||
template <typename T, typename Alloc = std::allocator<T> >
|
||||
class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T,Alloc> > {
|
||||
typedef detail::kernel_1d_adaptor<std::vector<T,Alloc> > parent_t;
|
||||
public:
|
||||
kernel_1d() {}
|
||||
kernel_1d(std::size_t size_in,std::size_t center_in) : parent_t(size_in,center_in) {}
|
||||
template <typename FwdIterator>
|
||||
kernel_1d(FwdIterator elements, std::size_t size_in, std::size_t center_in) : parent_t(size_in,center_in) {
|
||||
detail::copy_n(elements,size_in,this->begin());
|
||||
}
|
||||
kernel_1d(const kernel_1d& k_in) : parent_t(k_in) {}
|
||||
};
|
||||
|
||||
/// \brief static-size kernel
|
||||
template <typename T,std::size_t Size>
|
||||
class kernel_1d_fixed : public detail::kernel_1d_adaptor<array<T,Size> > {
|
||||
typedef detail::kernel_1d_adaptor<array<T,Size> > parent_t;
|
||||
public:
|
||||
kernel_1d_fixed() {}
|
||||
explicit kernel_1d_fixed(std::size_t center_in) : parent_t(center_in) {}
|
||||
|
||||
template <typename FwdIterator>
|
||||
explicit kernel_1d_fixed(FwdIterator elements, std::size_t center_in) : parent_t(center_in) {
|
||||
detail::copy_n(elements,Size,this->begin());
|
||||
}
|
||||
kernel_1d_fixed(const kernel_1d_fixed& k_in) : parent_t(k_in) {}
|
||||
};
|
||||
|
||||
/// \brief reverse a kernel
|
||||
template <typename Kernel>
|
||||
inline Kernel reverse_kernel(const Kernel& kernel) {
|
||||
Kernel result(kernel);
|
||||
result.center()=kernel.right_size();
|
||||
std::reverse(result.begin(), result.end());
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_PIXEL_NUMERIC_OPERATIONS_HPP
|
||||
#define GIL_PIXEL_NUMERIC_OPERATIONS_HPP
|
||||
|
||||
/*!
|
||||
/// \file
|
||||
/// \brief Structures for pixel-wise numeric operations
|
||||
/// \author Lubomir Bourdev and Hailin Jin \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n Last updated on February 6, 2007
|
||||
/// Currently defined structures:
|
||||
/// pixel_plus_t (+), pixel_minus_t (-)
|
||||
/// pixel_multiplies_scalar_t (*), pixel_divides_scalar_t (/)
|
||||
/// pixel_halves_t (/=2), pixel_zeros_t (=0)
|
||||
/// pixel_assigns_t (=)
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
#include "boost/gil/gil_config.hpp"
|
||||
#include "boost/gil/pixel.hpp"
|
||||
#include "boost/gil/color_base_algorithm.hpp"
|
||||
#include "channel_numeric_operations.hpp"
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for adding two pixels
|
||||
template <typename PixelRef1, // models pixel concept
|
||||
typename PixelRef2, // models pixel concept
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_plus_t {
|
||||
PixelR operator() (const PixelRef1& p1,
|
||||
const PixelRef2& p2) const {
|
||||
PixelR result;
|
||||
static_transform(p1,p2,result,
|
||||
channel_plus_t<typename channel_type<PixelRef1>::type,
|
||||
typename channel_type<PixelRef2>::type,
|
||||
typename channel_type<PixelR>::type>());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for subtracting two pixels
|
||||
template <typename PixelRef1, // models pixel concept
|
||||
typename PixelRef2, // models pixel concept
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_minus_t {
|
||||
PixelR operator() (const PixelRef1& p1,
|
||||
const PixelRef2& p2) const {
|
||||
PixelR result;
|
||||
static_transform(p1,p2,result,
|
||||
channel_minus_t<typename channel_type<PixelRef1>::type,
|
||||
typename channel_type<PixelRef2>::type,
|
||||
typename channel_type<PixelR>::type>());
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for multiplying scalar to a pixel
|
||||
template <typename PixelRef, // models pixel concept
|
||||
typename Scalar, // models a scalar type
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_multiplies_scalar_t {
|
||||
PixelR operator () (const PixelRef& p,
|
||||
const Scalar& s) const {
|
||||
PixelR result;
|
||||
static_transform(p,result,
|
||||
std::bind2nd(channel_multiplies_scalar_t<typename channel_type<PixelRef>::type,
|
||||
Scalar,
|
||||
typename channel_type<PixelR>::type>(),s));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for dividing a pixel by a scalar
|
||||
template <typename PixelRef, // models pixel concept
|
||||
typename Scalar, // models a scalar type
|
||||
typename PixelR> // models pixel value concept
|
||||
struct pixel_divides_scalar_t {
|
||||
PixelR operator () (const PixelRef& p,
|
||||
const Scalar& s) const {
|
||||
PixelR result;
|
||||
static_transform(p,result,
|
||||
std::bind2nd(channel_divides_scalar_t<typename channel_type<PixelRef>::type,
|
||||
Scalar,
|
||||
typename channel_type<PixelR>::type>(),s));
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for dividing a pixel by 2
|
||||
template <typename PixelRef> // models pixel concept
|
||||
struct pixel_halves_t {
|
||||
PixelRef& operator () (PixelRef& p) const {
|
||||
static_for_each(p,channel_halves_t<typename channel_type<PixelRef>::type>());
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
/// \brief construct for setting a pixel to zero (for whatever zero means)
|
||||
template <typename PixelRef> // models pixel concept
|
||||
struct pixel_zeros_t {
|
||||
PixelRef& operator () (PixelRef& p) const {
|
||||
static_for_each(p,channel_zeros_t<typename channel_type<PixelRef>::type>());
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
// Hailin: This is how you can do it:
|
||||
template <typename Pixel>
|
||||
void zero_channels(Pixel& p) {
|
||||
static_for_each(p,channel_zeros_t<typename channel_type<Pixel>::type>());
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup PixelNumericOperations
|
||||
///definition and a generic implementation for casting and assigning a pixel to another
|
||||
///user should specialize it for better performance
|
||||
template <typename PixelRef, // models pixel concept
|
||||
typename PixelRefR> // models pixel concept
|
||||
struct pixel_assigns_t {
|
||||
PixelRefR operator () (const PixelRef& src,
|
||||
PixelRefR& dst) const {
|
||||
static_for_each(src,dst,channel_assigns_t<typename channel_type<PixelRef>::type,
|
||||
typename channel_type<PixelRefR>::type>());
|
||||
return dst;
|
||||
}
|
||||
};
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
Executable
+141
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_RESAMPLE_HPP
|
||||
#define GIL_RESAMPLE_HPP
|
||||
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
#include <boost/lambda/bind.hpp>
|
||||
#include "boost/gil/extension/dynamic_image/dynamic_image_all.hpp"
|
||||
#include "affine.hpp"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief support for generic image resampling
|
||||
/// NOTE: The code is for example use only. It is not optimized for performance
|
||||
/// \author Lubomir Bourdev and Hailin Jin \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n October 30, 2006
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
////
|
||||
//// resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
|
||||
////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename MapFn> struct mapping_traits {};
|
||||
|
||||
/// \brief Set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
|
||||
/// \ingroup ImageAlgorithms
|
||||
///
|
||||
/// The provided implementation works for 2D image views only
|
||||
template <typename Sampler, // Models SamplerConcept
|
||||
typename SrcView, // Models RandomAccess2DImageViewConcept
|
||||
typename DstView, // Models MutableRandomAccess2DImageViewConcept
|
||||
typename MapFn> // Models MappingFunctionConcept
|
||||
void resample_pixels(const SrcView& src_view, const DstView& dst_view, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
|
||||
typename DstView::point_t dst_dims=dst_view.dimensions();
|
||||
typename DstView::point_t dst_p;
|
||||
typename mapping_traits<MapFn>::result_type src_p;
|
||||
|
||||
for (dst_p.y=0; dst_p.y<dst_dims.y; ++dst_p.y) {
|
||||
typename DstView::x_iterator xit = dst_view.row_begin(dst_p.y);
|
||||
for (dst_p.x=0; dst_p.x<dst_dims.x; ++dst_p.x) {
|
||||
sample(sampler, src_view, transform(dst_to_src, dst_p), xit[dst_p.x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
////
|
||||
//// resample_pixels when one or both image views are run-time instantiated.
|
||||
////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
template <typename Sampler, typename MapFn>
|
||||
struct resample_pixels_fn : public binary_operation_obj<resample_pixels_fn<Sampler,MapFn> > {
|
||||
MapFn _dst_to_src;
|
||||
Sampler _sampler;
|
||||
resample_pixels_fn(const MapFn& dst_to_src, const Sampler& sampler) : _dst_to_src(dst_to_src), _sampler(sampler) {}
|
||||
|
||||
template <typename SrcView, typename DstView> GIL_FORCEINLINE void apply_compatible(const SrcView& src, const DstView& dst) const {
|
||||
resample_pixels(src, dst, _dst_to_src, _sampler);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief resample_pixels when the source is run-time specified
|
||||
/// If invoked on incompatible views, throws std::bad_cast()
|
||||
/// \ingroup ImageAlgorithms
|
||||
template <typename Sampler, typename Types1, typename V2, typename MapFn>
|
||||
void resample_pixels(const any_image_view<Types1>& src, const V2& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
|
||||
apply_operation(src,bind(detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler), _1, dst));
|
||||
}
|
||||
|
||||
/// \brief resample_pixels when the destination is run-time specified
|
||||
/// If invoked on incompatible views, throws std::bad_cast()
|
||||
/// \ingroup ImageAlgorithms
|
||||
template <typename Sampler, typename V1, typename Types2, typename MapFn>
|
||||
void resample_pixels(const V1& src, const any_image_view<Types2>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
|
||||
apply_operation(dst,bind(detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler), src, _1));
|
||||
}
|
||||
|
||||
/// \brief resample_pixels when both the source and the destination are run-time specified
|
||||
/// If invoked on incompatible views, throws std::bad_cast()
|
||||
/// \ingroup ImageAlgorithms
|
||||
template <typename Sampler, typename SrcTypes, typename DstTypes, typename MapFn>
|
||||
void resample_pixels(const any_image_view<SrcTypes>& src, const any_image_view<DstTypes>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
|
||||
apply_operation(src,dst,detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
////
|
||||
//// resample_subimage: copy into the destination a rotated rectangular region from the source, rescaling it to fit into the destination
|
||||
////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Extract into dst the rotated bounds [src_min..src_max] rotated at 'angle' from the source view 'src'
|
||||
// The source coordinates are in the coordinate space of the source image
|
||||
// Note that the views could also be variants (i.e. any_image_view)
|
||||
template <typename Sampler, typename SrcMetaView, typename DstMetaView>
|
||||
void resample_subimage(const SrcMetaView& src, const DstMetaView& dst,
|
||||
double src_min_x, double src_min_y,
|
||||
double src_max_x, double src_max_y,
|
||||
double angle, const Sampler& sampler=Sampler()) {
|
||||
double src_width = std::max<double>(src_max_x - src_min_x - 1,1);
|
||||
double src_height = std::max<double>(src_max_y - src_min_y - 1,1);
|
||||
double dst_width = std::max<double>(dst.width()-1,1);
|
||||
double dst_height = std::max<double>(dst.height()-1,1);
|
||||
|
||||
matrix3x2<double> mat =
|
||||
matrix3x2<double>::get_translate(-dst_width/2.0, -dst_height/2.0) *
|
||||
matrix3x2<double>::get_scale(src_width / dst_width, src_height / dst_height)*
|
||||
matrix3x2<double>::get_rotate(-angle)*
|
||||
matrix3x2<double>::get_translate(src_min_x + src_width/2.0, src_min_y + src_height/2.0);
|
||||
resample_pixels(src,dst,mat,sampler);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
////
|
||||
//// resize_view: Copy the source view into the destination, scaling to fit
|
||||
////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Sampler, typename SrcMetaView, typename DstMetaView>
|
||||
void resize_view(const SrcMetaView& src, const DstMetaView& dst, const Sampler& sampler=Sampler()) {
|
||||
resample_subimage(src,dst,0,0,src.width(),src.height(),0,sampler);
|
||||
}
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
Executable
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
Distributed under the MIT License (see accompanying file LICENSE_1_0_0.txt
|
||||
or a copy at http://opensource.adobe.com/licenses.html)
|
||||
*/
|
||||
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef GIL_SAMPLER_HPP
|
||||
#define GIL_SAMPLER_HPP
|
||||
|
||||
#include "boost/gil/extension/dynamic_image/dynamic_image_all.hpp"
|
||||
#include "pixel_numeric_operations.hpp"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Nearest-neighbor and bilinear image samplers.
|
||||
/// NOTE: The code is for example use only. It is not optimized for performance
|
||||
/// \author Lubomir Bourdev and Hailin Jin \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n October 30, 2006
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
////
|
||||
//// resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
|
||||
////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
template <typename Sampler>
|
||||
concept SamplerConcept {
|
||||
template <typename DstP, // Models PixelConcept
|
||||
typename SrcView, // Models RandomAccessNDImageViewConcept
|
||||
typename S_COORDS> // Models PointNDConcept, where S_COORDS::num_dimensions == SrcView::num_dimensions
|
||||
bool sample(const Sampler& s, const SrcView& src, const S_COORDS& p, DstP result);
|
||||
};
|
||||
*/
|
||||
|
||||
/// \brief A sampler that sets the destination pixel to the closest one in the source. If outside the bounds, it doesn't change the destination
|
||||
/// \ingroup ImageAlgorithms
|
||||
struct nearest_neighbor_sampler {};
|
||||
|
||||
template <typename DstP, typename SrcView, typename F>
|
||||
bool sample(nearest_neighbor_sampler, const SrcView& src, const point2<F>& p, DstP& result) {
|
||||
point2<int> center(iround(p));
|
||||
if (center.x>=0 && center.y>=0 && center.x<src.width() && center.y<src.height()) {
|
||||
result=src(center.x,center.y);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
struct cast_channel_fn {
|
||||
template <typename SrcChannel, typename DstChannel>
|
||||
void operator()(const SrcChannel& src, DstChannel& dst) {
|
||||
typedef typename channel_traits<DstChannel>::value_type dst_value_t;
|
||||
dst = dst_value_t(src);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename SrcPixel, typename DstPixel>
|
||||
void cast_pixel(const SrcPixel& src, DstPixel& dst) {
|
||||
static_for_each(src,dst,cast_channel_fn());
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename Weight>
|
||||
struct add_dst_mul_src_channel {
|
||||
Weight _w;
|
||||
add_dst_mul_src_channel(Weight w) : _w(w) {}
|
||||
|
||||
template <typename SrcChannel, typename DstChannel>
|
||||
void operator()(const SrcChannel& src, DstChannel& dst) const {
|
||||
dst += DstChannel(src*_w);
|
||||
}
|
||||
};
|
||||
|
||||
// dst += DST_TYPE(src * w)
|
||||
template <typename SrcP,typename Weight,typename DstP>
|
||||
struct add_dst_mul_src {
|
||||
void operator()(const SrcP& src, Weight weight, DstP& dst) const {
|
||||
static_for_each(src,dst, add_dst_mul_src_channel<Weight>(weight));
|
||||
// pixel_assigns_t<DstP,DstP&>()(
|
||||
// pixel_plus_t<DstP,DstP,DstP>()(
|
||||
// pixel_multiplies_scalar_t<SrcP,Weight,DstP>()(src,weight),
|
||||
// dst),
|
||||
// dst);
|
||||
}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
/// \brief A sampler that sets the destination pixel as the bilinear interpolation of the four closest pixels from the source.
|
||||
/// If outside the bounds, it doesn't change the destination
|
||||
/// \ingroup ImageAlgorithms
|
||||
struct bilinear_sampler {};
|
||||
|
||||
template <typename DstP, typename SrcView, typename F>
|
||||
bool sample(bilinear_sampler, const SrcView& src, const point2<F>& p, DstP& result) {
|
||||
typedef typename SrcView::value_type SrcP;
|
||||
point2<std::ptrdiff_t> p0(ifloor(p)); // the closest integer coordinate top left from p
|
||||
point2<F> frac(p.x-p0.x, p.y-p0.y);
|
||||
if (p0.x < 0 || p0.y < 0 || p0.x>=src.width() || p0.y>=src.height()) return false;
|
||||
|
||||
pixel<F,devicen_layout_t<num_channels<SrcView>::value> > mp(0); // suboptimal
|
||||
typename SrcView::xy_locator loc=src.xy_at(p0.x,p0.y);
|
||||
|
||||
if (p0.x+1<src.width()) {
|
||||
if (p0.y+1<src.height()) {
|
||||
// most common case - inside the image, not on the last row or column
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x)*(1-frac.y),mp);
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x *(1-frac.y),mp);
|
||||
++loc.y();
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x)* frac.y ,mp);
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x * frac.y ,mp);
|
||||
} else {
|
||||
// on the last row, but not the bottom-right corner pixel
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x),mp);
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x ,mp);
|
||||
}
|
||||
} else {
|
||||
if (p0.y+1<src.height()) {
|
||||
// on the last column, but not the bottom-right corner pixel
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.y),mp);
|
||||
++loc.y();
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, frac.y ,mp);
|
||||
} else {
|
||||
// the bottom-right corner pixel
|
||||
detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc,1,mp);
|
||||
}
|
||||
}
|
||||
|
||||
// Convert from floating point average value to the source type
|
||||
SrcP src_result;
|
||||
cast_pixel(mp,src_result);
|
||||
|
||||
color_convert(src_result, result);
|
||||
return true;
|
||||
}
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
Copyright 2005-2007 Adobe Systems Incorporated
|
||||
|
||||
Use, modification and distribution are subject to 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).
|
||||
|
||||
See http://opensource.adobe.com/gil for most recent version including documentation.
|
||||
*/
|
||||
/*************************************************************************************************/
|
||||
|
||||
#ifndef BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP_INCLUDED
|
||||
#define BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP_INCLUDED
|
||||
|
||||
/// \file
|
||||
/// \brief Generic io functions for dealing with dynamic images
|
||||
//
|
||||
/// \author Hailin Jin and Lubomir Bourdev \n
|
||||
/// Adobe Systems Incorporated
|
||||
/// \date 2005-2007 \n Last updated May 30, 2006
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/gil/gil_config.hpp>
|
||||
#include <boost/gil/extension/io_new/detail/io_error.hpp>
|
||||
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// need this for various meta functions.
|
||||
struct any_image_pixel_t {};
|
||||
struct any_image_channel_t {};
|
||||
struct any_image_color_space_t {};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <long N>
|
||||
struct construct_matched_t {
|
||||
template <typename Images,typename Pred>
|
||||
static bool apply(any_image<Images>& im,Pred pred) {
|
||||
if (pred.template apply<typename mpl::at_c<Images,N-1>::type>()) {
|
||||
typename mpl::at_c<Images,N-1>::type x;
|
||||
im.move_in(x);
|
||||
return true;
|
||||
} else return construct_matched_t<N-1>::apply(im,pred);
|
||||
}
|
||||
};
|
||||
template <>
|
||||
struct construct_matched_t<0> {
|
||||
template <typename Images,typename Pred>
|
||||
static bool apply(any_image<Images>&,Pred) {return false;}
|
||||
};
|
||||
|
||||
// A function object that can be passed to apply_operation.
|
||||
// Given a predicate IsSupported taking a view type and returning an MPL boolean,
|
||||
// calls the apply method of OpClass with the view if the given view IsSupported, or throws an exception otherwise
|
||||
template <typename IsSupported, typename OpClass>
|
||||
class dynamic_io_fnobj {
|
||||
OpClass* _op;
|
||||
|
||||
template <typename View>
|
||||
void apply(const View& view,mpl::true_ ) {_op->apply(view);}
|
||||
|
||||
template <typename View, typename Info >
|
||||
void apply( const View& view
|
||||
, const Info& info
|
||||
, const mpl::true_
|
||||
)
|
||||
{
|
||||
_op->apply( view, info );
|
||||
}
|
||||
|
||||
template <typename View>
|
||||
void apply(const View& /* view */ ,mpl::false_) {io_error("dynamic_io: unsupported view type for the given file format");}
|
||||
|
||||
template <typename View, typename Info >
|
||||
void apply( const View& /* view */
|
||||
, const Info& /* info */
|
||||
, const mpl::false_
|
||||
)
|
||||
{
|
||||
io_error( "dynamic_io: unsupported view type for the given file format" );
|
||||
}
|
||||
|
||||
public:
|
||||
dynamic_io_fnobj(OpClass* op) : _op(op) {}
|
||||
|
||||
typedef void result_type;
|
||||
|
||||
template <typename View>
|
||||
void operator()(const View& view) {apply(view,typename IsSupported::template apply<View>::type());}
|
||||
|
||||
template< typename View, typename Info >
|
||||
void operator()(const View& view, const Info& info )
|
||||
{
|
||||
apply( view
|
||||
, info
|
||||
, typename IsSupported::template apply< View >::type()
|
||||
);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \brief Within the any_image, constructs an image with the given dimensions
|
||||
/// and a type that satisfies the given predicate
|
||||
template <typename Images,typename Pred>
|
||||
inline bool construct_matched(any_image<Images>& im,Pred pred) {
|
||||
return detail::construct_matched_t<mpl::size<Images>::value>::apply(im,pred);
|
||||
}
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP_INCLUDED
|
||||
@@ -0,0 +1,281 @@
|
||||
/*
|
||||
Copyright 2010 Christian Henning, Andreas Pokorny, Lubomir Bourdev
|
||||
Use, modification and distribution are subject to 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_TOOLBOX_GIL_EXTENSIONS_HPP_INCLUDED
|
||||
#define BOOST_GIL_EXTENSION_TOOLBOX_GIL_EXTENSIONS_HPP_INCLUDED
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Definitions of is_bit_aligned, is_homogeneous, and is_similar metafunctions and
|
||||
/// some other goodies.
|
||||
/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
|
||||
///
|
||||
/// \date 2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
|
||||
#include <boost/gil/extension/toolbox/dynamic_images.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// is_bit_aligned metafunctions
|
||||
/// \brief Determines whether the given type is bit_aligned.
|
||||
|
||||
template< typename PixelRef >
|
||||
struct is_bit_aligned : mpl::false_{};
|
||||
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct is_bit_aligned<bit_aligned_pixel_reference<B,C,L,M> > : mpl::true_{};
|
||||
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct is_bit_aligned<const bit_aligned_pixel_reference<B,C,L,M> > : mpl::true_{};
|
||||
|
||||
template <typename B, typename C, typename L>
|
||||
struct is_bit_aligned<packed_pixel<B,C,L> > : mpl::true_{};
|
||||
|
||||
template <typename B, typename C, typename L>
|
||||
struct is_bit_aligned<const packed_pixel<B,C,L> > : mpl::true_{};
|
||||
|
||||
|
||||
/// is_similar metafunctions
|
||||
/// \brief Determines if two pixel types are similar.
|
||||
|
||||
template< typename A, typename B >
|
||||
struct is_similar : mpl::false_ {};
|
||||
|
||||
template<typename A>
|
||||
struct is_similar< A, A > : mpl::true_ {};
|
||||
|
||||
template<typename B,int I, int S, bool M, int I2>
|
||||
struct is_similar< packed_channel_reference< B, I, S, M >
|
||||
, packed_channel_reference< B, I2, S, M >
|
||||
> : mpl::true_ {};
|
||||
|
||||
/// is_homogeneous metafunctions
|
||||
/// \brief Determines if a pixel types are homogeneous.
|
||||
|
||||
template<typename C,typename CMP, int Next, int Last> struct is_homogeneous_impl;
|
||||
|
||||
template<typename C,typename CMP, int Last>
|
||||
struct is_homogeneous_impl<C,CMP,Last,Last> : mpl::true_{};
|
||||
|
||||
template<typename C,typename CMP, int Next, int Last>
|
||||
struct is_homogeneous_impl : mpl::and_< is_homogeneous_impl< C, CMP,Next + 1, Last >
|
||||
, is_same< CMP, typename mpl::at_c<C,Next>::type
|
||||
> > {};
|
||||
|
||||
template < typename P > struct is_homogeneous : mpl::false_ {};
|
||||
|
||||
// pixel
|
||||
template < typename C, typename L > struct is_homogeneous< pixel<C,L> > : mpl::true_ {};
|
||||
template < typename C, typename L > struct is_homogeneous<const pixel<C,L> > : mpl::true_ {};
|
||||
template < typename C, typename L > struct is_homogeneous< pixel<C,L>& > : mpl::true_ {};
|
||||
template < typename C, typename L > struct is_homogeneous<const pixel<C,L>& > : mpl::true_ {};
|
||||
|
||||
// planar pixel reference
|
||||
template <typename Channel, typename ColorSpace>
|
||||
struct is_homogeneous< planar_pixel_reference< Channel, ColorSpace > > : mpl::true_ {};
|
||||
template <typename Channel, typename ColorSpace>
|
||||
struct is_homogeneous< const planar_pixel_reference< Channel, ColorSpace > > : mpl::true_ {};
|
||||
|
||||
template<typename C,typename CMP, int I,int Last>
|
||||
struct is_homogeneous_impl_p {};
|
||||
|
||||
// for packed_pixel
|
||||
template <typename B, typename C, typename L >
|
||||
struct is_homogeneous<packed_pixel< B, C, L > >
|
||||
: is_homogeneous_impl_p< C
|
||||
, typename mpl::at_c< C, 0 >::type
|
||||
, 1
|
||||
, mpl::size< C >::type::value
|
||||
> {};
|
||||
|
||||
template< typename B
|
||||
, typename C
|
||||
, typename L
|
||||
>
|
||||
struct is_homogeneous< const packed_pixel< B, C, L > >
|
||||
: is_homogeneous_impl_p< C
|
||||
, typename mpl::at_c<C,0>::type
|
||||
, 1
|
||||
, mpl::size< C >::type::value
|
||||
> {};
|
||||
|
||||
// for bit_aligned_pixel_reference
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct is_homogeneous<bit_aligned_pixel_reference<B,C,L,M> >
|
||||
: is_homogeneous_impl<C,typename mpl::at_c<C,0>::type,1,mpl::size<C>::type::value>
|
||||
{};
|
||||
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct is_homogeneous<const bit_aligned_pixel_reference<B,C,L,M> >
|
||||
: is_homogeneous_impl<C,typename mpl::at_c<C,0>::type,1,mpl::size<C>::type::value>
|
||||
{};
|
||||
|
||||
//////////////////////
|
||||
/// other goodies
|
||||
|
||||
/// get_num_bits metafunctions
|
||||
/// \brief Determines the numbers of bits for the given channel type.
|
||||
|
||||
template <typename T>
|
||||
struct get_num_bits;
|
||||
|
||||
template< typename B, int I, int S, bool M >
|
||||
struct get_num_bits< packed_channel_reference< B, I, S, M > >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( int, value = S );
|
||||
};
|
||||
|
||||
template<typename B,int I, int S, bool M>
|
||||
struct get_num_bits< const packed_channel_reference< B, I, S, M > >
|
||||
{
|
||||
BOOST_STATIC_CONSTANT( int, value = S );
|
||||
};
|
||||
|
||||
|
||||
/// channel_type metafunction
|
||||
/// \brief Generates the channel type for
|
||||
|
||||
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct gen_chan_ref
|
||||
{
|
||||
typedef packed_dynamic_channel_reference< B
|
||||
, mpl::at_c< C, 0 >::type::value
|
||||
, M
|
||||
> type;
|
||||
};
|
||||
|
||||
|
||||
//! This implementation works for bit_algined_pixel_reference
|
||||
//! with a homogeneous channel layout.
|
||||
//! The result type will be a packed_dynamic_channel_reference, since the
|
||||
//! offset info will be missing.
|
||||
|
||||
// bit_aligned_pixel_reference
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct channel_type< bit_aligned_pixel_reference<B,C,L,M> >
|
||||
: lazy_enable_if< is_homogeneous< bit_aligned_pixel_reference< B, C, L, M > >
|
||||
, gen_chan_ref< B, C, L, M >
|
||||
> {};
|
||||
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct channel_type<const bit_aligned_pixel_reference<B,C,L,M> >
|
||||
: lazy_enable_if< is_homogeneous< bit_aligned_pixel_reference< B, C, L, M > >
|
||||
, gen_chan_ref< B, C, L, M >
|
||||
> {};
|
||||
|
||||
template <typename B, typename C, typename L>
|
||||
struct gen_chan_ref_p
|
||||
{
|
||||
typedef packed_dynamic_channel_reference< B
|
||||
, get_num_bits< typename mpl::at_c<C,0>::type>::value
|
||||
, true
|
||||
> type;
|
||||
};
|
||||
|
||||
// packed_pixel
|
||||
template < typename BitField
|
||||
, typename ChannelRefVec
|
||||
, typename Layout
|
||||
>
|
||||
struct channel_type< packed_pixel< BitField
|
||||
, ChannelRefVec
|
||||
, Layout
|
||||
>
|
||||
> : lazy_enable_if< is_homogeneous< packed_pixel< BitField
|
||||
, ChannelRefVec
|
||||
, Layout
|
||||
>
|
||||
>
|
||||
, gen_chan_ref_p< BitField
|
||||
, ChannelRefVec
|
||||
, Layout
|
||||
>
|
||||
> {};
|
||||
|
||||
template <typename B, typename C, typename L>
|
||||
struct channel_type< const packed_pixel< B, C, L > >
|
||||
: lazy_enable_if< is_homogeneous<packed_pixel< B, C, L > >
|
||||
, gen_chan_ref_p< B, C, L >
|
||||
>
|
||||
{};
|
||||
|
||||
template<>
|
||||
struct channel_type< any_image_pixel_t >
|
||||
{
|
||||
typedef any_image_channel_t type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct color_space_type< any_image_pixel_t >
|
||||
{
|
||||
typedef any_image_color_space_t type;
|
||||
};
|
||||
|
||||
/// get_pixel_type metafunction
|
||||
/// \brief Depending on Image this function generates either
|
||||
/// the pixel type or the reference type in case
|
||||
/// the image is bit_aligned.
|
||||
template< typename View >
|
||||
struct get_pixel_type : mpl::if_< typename is_bit_aligned< typename View::value_type >::type
|
||||
, typename View::reference
|
||||
, typename View::value_type
|
||||
> {};
|
||||
|
||||
template< typename ImageViewTypes >
|
||||
struct get_pixel_type< any_image_view< ImageViewTypes > >
|
||||
{
|
||||
typedef any_image_pixel_t type;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
/// - performance specialization double
|
||||
/// - to eliminate compiler warning 4244
|
||||
template <typename GrayChannelValue>
|
||||
struct rgb_to_luminance_fn< double, double, double, GrayChannelValue >
|
||||
{
|
||||
GrayChannelValue operator()( const double& red
|
||||
, const double& green
|
||||
, const double& blue ) const
|
||||
{
|
||||
return channel_convert<GrayChannelValue>( red * 0.30 + green * 0.59 + blue * 0.11 );
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// This one is missing in gil ( color_convert.hpp ).
|
||||
template <>
|
||||
struct default_color_converter_impl<gray_t,rgba_t>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()(const P1& src, P2& dst) const
|
||||
{
|
||||
get_color(dst,red_t()) =
|
||||
channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t()));
|
||||
get_color(dst,green_t())=
|
||||
channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
|
||||
get_color(dst,blue_t()) =
|
||||
channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t()));
|
||||
|
||||
typedef typename channel_type< P2 >::type channel_t;
|
||||
get_color(dst,alpha_t()) = channel_traits< channel_t >::max_value();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
#endif // BOOST_GIL_EXTENSION_TOOLBOX_GIL_EXTENSIONS_HPP_INCLUDED
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright 2007-2008 Andreas Pokorny
|
||||
Use, modification and distribution are subject to 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_GRAY_ALPHA_HPP_INCLUDED
|
||||
#define BOOST_GIL_GRAY_ALPHA_HPP_INCLUDED
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief
|
||||
/// \author Andreas Pokorny \n
|
||||
///
|
||||
/// \date 2007-2008 \n
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/gil/gil_config.hpp>
|
||||
#include <boost/mpl/contains.hpp>
|
||||
#include <boost/gil/gray.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
typedef mpl::vector2<gray_color_t,alpha_t> gray_alpha_t;
|
||||
|
||||
typedef layout<gray_alpha_t> gray_alpha_layout_t;
|
||||
typedef layout<gray_alpha_layout_t, mpl::vector2_c<int,1,0> > alpha_gray_layout_t;
|
||||
|
||||
GIL_DEFINE_BASE_TYPEDEFS(8, alpha_gray)
|
||||
GIL_DEFINE_BASE_TYPEDEFS(8s, alpha_gray)
|
||||
GIL_DEFINE_BASE_TYPEDEFS(16, alpha_gray)
|
||||
GIL_DEFINE_BASE_TYPEDEFS(16s,alpha_gray)
|
||||
GIL_DEFINE_BASE_TYPEDEFS(32 ,alpha_gray)
|
||||
GIL_DEFINE_BASE_TYPEDEFS(32s,alpha_gray)
|
||||
GIL_DEFINE_BASE_TYPEDEFS(32f,alpha_gray)
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS(8, gray_alpha)
|
||||
GIL_DEFINE_ALL_TYPEDEFS(8s, gray_alpha)
|
||||
GIL_DEFINE_ALL_TYPEDEFS(16, gray_alpha)
|
||||
GIL_DEFINE_ALL_TYPEDEFS(16s,gray_alpha)
|
||||
GIL_DEFINE_ALL_TYPEDEFS(32 ,gray_alpha)
|
||||
GIL_DEFINE_ALL_TYPEDEFS(32s,gray_alpha)
|
||||
GIL_DEFINE_ALL_TYPEDEFS(32f,gray_alpha)
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief Gray Alpha to RGBA
|
||||
template <>
|
||||
struct default_color_converter_impl<gray_alpha_t,rgba_t> {
|
||||
template <typename P1, typename P2>
|
||||
void operator()(const P1& src, P2& dst) const {
|
||||
get_color(dst,red_t()) =
|
||||
channel_convert<typename color_element_type<P2, red_t>::type>(get_color(src,gray_color_t()));
|
||||
get_color(dst,green_t())=
|
||||
channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
|
||||
get_color(dst,blue_t()) =
|
||||
channel_convert<typename color_element_type<P2, blue_t>::type>(get_color(src,gray_color_t()));
|
||||
get_color(dst,alpha_t()) =
|
||||
channel_convert<typename color_element_type<P2, alpha_t>::type>(get_color(src,alpha_t()));
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct default_color_converter_impl<gray_alpha_t,rgb_t> {
|
||||
template <typename P1, typename P2>
|
||||
void operator()(const P1& src, P2& dst) const {
|
||||
get_color(dst,red_t()) =
|
||||
channel_convert<typename color_element_type<P2, red_t>::type>(
|
||||
channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
|
||||
);
|
||||
get_color(dst,green_t()) =
|
||||
channel_convert<typename color_element_type<P2, green_t>::type>(
|
||||
channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
|
||||
);
|
||||
get_color(dst,blue_t()) =
|
||||
channel_convert<typename color_element_type<P2, blue_t>::type>(
|
||||
channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct default_color_converter_impl<gray_alpha_t,gray_t> {
|
||||
template <typename P1, typename P2>
|
||||
void operator()(const P1& src, P2& dst) const {
|
||||
get_color(dst,gray_color_t()) =
|
||||
channel_convert<typename color_element_type<P2, gray_color_t>::type>(
|
||||
channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
} // gil
|
||||
} // boost
|
||||
|
||||
#endif // BOOST_GIL_GRAY_ALPHA_HPP_INCLUDED
|
||||
@@ -0,0 +1,262 @@
|
||||
// Copyright 2007 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 GIL_HSL_H
|
||||
#define GIL_HSL_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Support for HSL color space
|
||||
/// \author Christian Henning \n
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \addtogroup ColorNameModel
|
||||
/// \{
|
||||
namespace hsl_color_space
|
||||
{
|
||||
/// \brief Hue
|
||||
struct hue_t {};
|
||||
/// \brief Saturation
|
||||
struct saturation_t {};
|
||||
/// \brief Lightness
|
||||
struct lightness_t {};
|
||||
}
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
typedef mpl::vector3< hsl_color_space::hue_t
|
||||
, hsl_color_space::saturation_t
|
||||
, hsl_color_space::lightness_t
|
||||
> hsl_t;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
typedef layout<hsl_t> hsl_layout_t;
|
||||
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS( 32f, hsl );
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to HSL
|
||||
template <>
|
||||
struct default_color_converter_impl< rgb_t, hsl_t >
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst ) const
|
||||
{
|
||||
using namespace hsl_color_space;
|
||||
|
||||
// only bits32f for hsl is supported
|
||||
bits32f temp_red = channel_convert<bits32f>( get_color( src, red_t() ));
|
||||
bits32f temp_green = channel_convert<bits32f>( get_color( src, green_t() ));
|
||||
bits32f temp_blue = channel_convert<bits32f>( get_color( src, blue_t() ));
|
||||
|
||||
bits32f hue, saturation, lightness;
|
||||
|
||||
bits32f min_color = (std::min)( temp_red, (std::min)( temp_green, temp_blue ));
|
||||
bits32f max_color = (std::max)( temp_red, (std::max)( temp_green, temp_blue ));
|
||||
|
||||
if( abs( min_color - max_color ) < 0.001 )
|
||||
{
|
||||
// rgb color is gray
|
||||
|
||||
hue = 0.f;
|
||||
saturation = 0.f;
|
||||
|
||||
// doesn't matter which rgb channel we use.
|
||||
lightness = temp_red;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
bits32f diff = max_color - min_color;
|
||||
|
||||
// lightness calculation
|
||||
|
||||
lightness = ( min_color + max_color ) / 2.f;
|
||||
|
||||
// saturation calculation
|
||||
|
||||
if( lightness < 0.5f )
|
||||
{
|
||||
saturation = diff
|
||||
/ ( min_color + max_color );
|
||||
}
|
||||
else
|
||||
{
|
||||
saturation = ( max_color - min_color )
|
||||
/ ( 2.f - diff );
|
||||
|
||||
}
|
||||
|
||||
// hue calculation
|
||||
if( abs( max_color - temp_red ) < 0.0001f )
|
||||
{
|
||||
// max_color is red
|
||||
hue = ( temp_green - temp_blue )
|
||||
/ diff;
|
||||
|
||||
}
|
||||
else if( abs( max_color - temp_green) < 0.0001f )
|
||||
{
|
||||
// max_color is green
|
||||
// 2.0 + (b - r) / (maxColor - minColor);
|
||||
hue = 2.f
|
||||
+ ( temp_blue - temp_red )
|
||||
/ diff;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// max_color is blue
|
||||
hue = 4.f
|
||||
+ ( temp_red - temp_blue )
|
||||
/ diff;
|
||||
}
|
||||
|
||||
hue /= 6.f;
|
||||
|
||||
if( hue < 0.f )
|
||||
{
|
||||
hue += 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
get_color( dst,hue_t() ) = hue;
|
||||
get_color( dst,saturation_t() ) = saturation;
|
||||
get_color( dst,lightness_t() ) = lightness;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief HSL to RGB
|
||||
template <>
|
||||
struct default_color_converter_impl<hsl_t,rgb_t>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst) const
|
||||
{
|
||||
using namespace hsl_color_space;
|
||||
|
||||
bits32f red, green, blue;
|
||||
|
||||
if( abs( get_color( src, saturation_t() )) < 0.0001 )
|
||||
{
|
||||
// If saturation is 0, the color is a shade of gray
|
||||
red = get_color( src, lightness_t() );
|
||||
green = get_color( src, lightness_t() );
|
||||
blue = get_color( src, lightness_t() );
|
||||
}
|
||||
else
|
||||
{
|
||||
float temp1, temp2;
|
||||
float tempr, tempg, tempb;
|
||||
|
||||
//Set the temporary values
|
||||
if( get_color( src, lightness_t() ) < 0.5 )
|
||||
{
|
||||
temp2 = get_color( src, lightness_t() )
|
||||
* ( 1.f + get_color( src, saturation_t() ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
temp2 = ( get_color( src, lightness_t() ) + get_color( src, saturation_t() ))
|
||||
- ( get_color( src, lightness_t() ) * get_color( src, saturation_t() ));
|
||||
}
|
||||
|
||||
temp1 = 2.f
|
||||
* get_color( src, lightness_t() )
|
||||
- temp2;
|
||||
|
||||
tempr = get_color( src, hue_t() ) + 1.f / 3.f;
|
||||
|
||||
if( tempr > 1.f )
|
||||
{
|
||||
tempr--;
|
||||
}
|
||||
|
||||
tempg = get_color( src, hue_t() );
|
||||
tempb = get_color( src, hue_t() ) - 1.f / 3.f;
|
||||
|
||||
if( tempb < 0.f )
|
||||
{
|
||||
tempb++;
|
||||
}
|
||||
|
||||
//Red
|
||||
if( tempr < 1.f / 6.f )
|
||||
{
|
||||
red = temp1 + ( temp2 - temp1 ) * 6.f * tempr;
|
||||
}
|
||||
else if( tempr < 0.5f )
|
||||
{
|
||||
red = temp2;
|
||||
}
|
||||
else if( tempr < 2.f / 3.f )
|
||||
{
|
||||
red = temp1 + (temp2 - temp1)
|
||||
* (( 2.f / 3.f ) - tempr) * 6.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
red = temp1;
|
||||
}
|
||||
|
||||
//Green
|
||||
if( tempg < 1.f / 6.f )
|
||||
{
|
||||
green = temp1 + ( temp2 - temp1 ) * 6.f * tempg;
|
||||
}
|
||||
else if( tempg < 0.5f )
|
||||
{
|
||||
green = temp2;
|
||||
}
|
||||
else if( tempg < 2.f / 3.f )
|
||||
{
|
||||
green = temp1 + ( temp2 - temp1 )
|
||||
* (( 2.f / 3.f ) - tempg) * 6.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
green = temp1;
|
||||
}
|
||||
|
||||
//Blue
|
||||
if( tempb < 1.f / 6.f )
|
||||
{
|
||||
blue = temp1 + (temp2 - temp1) * 6.f * tempb;
|
||||
}
|
||||
else if( tempb < 0.5f )
|
||||
{
|
||||
blue = temp2;
|
||||
}
|
||||
else if( tempb < 2.f / 3.f )
|
||||
{
|
||||
blue = temp1 + (temp2 - temp1)
|
||||
* (( 2.f / 3.f ) - tempb) * 6.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
blue = temp1;
|
||||
}
|
||||
}
|
||||
|
||||
get_color(dst,red_t()) =
|
||||
channel_convert<typename color_element_type< P2, red_t >::type>( red );
|
||||
get_color(dst,green_t())=
|
||||
channel_convert<typename color_element_type< P2, green_t >::type>( green );
|
||||
get_color(dst,blue_t()) =
|
||||
channel_convert<typename color_element_type< P2, blue_t >::type>( blue );
|
||||
}
|
||||
};
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif // GIL_HSL_H
|
||||
@@ -0,0 +1,231 @@
|
||||
// Copyright 2004 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 GIL_HSV_H
|
||||
#define GIL_HSV_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Support for HSV color space
|
||||
/// \author Christian Henning \n
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/cast.hpp>
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \addtogroup ColorNameModel
|
||||
/// \{
|
||||
namespace hsv_color_space
|
||||
{
|
||||
/// \brief Hue
|
||||
struct hue_t {};
|
||||
/// \brief Saturation
|
||||
struct saturation_t{};
|
||||
/// \brief Value
|
||||
struct value_t {};
|
||||
}
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
typedef mpl::vector3< hsv_color_space::hue_t
|
||||
, hsv_color_space::saturation_t
|
||||
, hsv_color_space::value_t
|
||||
> hsv_t;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
typedef layout<hsv_t> hsv_layout_t;
|
||||
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS( 32f, hsv )
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to HSV
|
||||
template <>
|
||||
struct default_color_converter_impl< rgb_t, hsv_t >
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst ) const
|
||||
{
|
||||
using namespace hsv_color_space;
|
||||
|
||||
// only bits32f for hsv is supported
|
||||
bits32f temp_red = channel_convert<bits32f>( get_color( src, red_t() ));
|
||||
bits32f temp_green = channel_convert<bits32f>( get_color( src, green_t() ));
|
||||
bits32f temp_blue = channel_convert<bits32f>( get_color( src, blue_t() ));
|
||||
|
||||
bits32f hue, saturation, value;
|
||||
|
||||
bits32f min_color = (std::min)( temp_red, (std::min)( temp_green, temp_blue ));
|
||||
bits32f max_color = (std::max)( temp_red, (std::max)( temp_green, temp_blue ));
|
||||
|
||||
value = max_color;
|
||||
|
||||
bits32f diff = max_color - min_color;
|
||||
|
||||
if( max_color < 0.0001f )
|
||||
{
|
||||
saturation = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
saturation = diff / max_color;
|
||||
}
|
||||
|
||||
|
||||
if( saturation < 0.0001f )
|
||||
{
|
||||
//it doesn't matter what value it has
|
||||
hue = 0.f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (std::abs)( boost::numeric_cast<int>(temp_red - max_color) ) < 0.0001f )
|
||||
{
|
||||
hue = ( temp_green - temp_blue )
|
||||
/ diff;
|
||||
}
|
||||
else if( temp_green == max_color )
|
||||
{
|
||||
hue = 2.f + ( temp_blue - temp_red )
|
||||
/ diff;
|
||||
}
|
||||
else
|
||||
{
|
||||
hue = 4.f + ( temp_red - temp_green )
|
||||
/ diff;
|
||||
}
|
||||
|
||||
//to bring it to a number between 0 and 1
|
||||
hue /= 6.f;
|
||||
|
||||
if( hue < 0.f )
|
||||
{
|
||||
hue++;
|
||||
}
|
||||
}
|
||||
|
||||
get_color( dst, hue_t() ) = hue;
|
||||
get_color( dst, saturation_t() ) = saturation;
|
||||
get_color( dst, value_t() ) = value;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief HSV to RGB
|
||||
template <>
|
||||
struct default_color_converter_impl<hsv_t,rgb_t>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst) const
|
||||
{
|
||||
using namespace hsv_color_space;
|
||||
|
||||
bits32f red, green, blue;
|
||||
|
||||
//If saturation is 0, the color is a shade of gray
|
||||
if( abs( get_color( src, saturation_t() )) < 0.0001f )
|
||||
{
|
||||
// If saturation is 0, the color is a shade of gray
|
||||
red = get_color( src, value_t() );
|
||||
green = get_color( src, value_t() );
|
||||
blue = get_color( src, value_t() );
|
||||
}
|
||||
else
|
||||
{
|
||||
bits32f frac, p, q, t, h;
|
||||
bits32 i;
|
||||
|
||||
//to bring hue to a number between 0 and 6, better for the calculations
|
||||
h = get_color( src, hue_t() );
|
||||
h *= 6.f;
|
||||
|
||||
i = static_cast<bits32>( floor( h ));
|
||||
|
||||
frac = h - i;
|
||||
|
||||
p = get_color( src, value_t() )
|
||||
* ( 1.f - get_color( src, saturation_t() ));
|
||||
|
||||
q = get_color( src, value_t() )
|
||||
* ( 1.f - ( get_color( src, saturation_t() ) * frac ));
|
||||
|
||||
t = get_color( src, value_t() )
|
||||
* ( 1.f - ( get_color( src, saturation_t() ) * ( 1.f - frac )));
|
||||
|
||||
switch( i )
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
red = get_color( src, value_t() );
|
||||
green = t;
|
||||
blue = p;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
red = q;
|
||||
green = get_color( src, value_t() );
|
||||
blue = p;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
red = p;
|
||||
green = get_color( src, value_t() );
|
||||
blue = t;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 3:
|
||||
{
|
||||
red = p;
|
||||
green = q;
|
||||
blue = get_color( src, value_t() );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
red = t;
|
||||
green = p;
|
||||
blue = get_color( src, value_t() );
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 5:
|
||||
{
|
||||
red = get_color( src, value_t() );
|
||||
green = p;
|
||||
blue = q;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
get_color(dst,red_t()) =
|
||||
channel_convert<typename color_element_type< P2, red_t >::type>( red );
|
||||
get_color(dst,green_t())=
|
||||
channel_convert<typename color_element_type< P2, green_t >::type>( green );
|
||||
get_color(dst,blue_t()) =
|
||||
channel_convert<typename color_element_type< P2, blue_t >::type>( blue );
|
||||
}
|
||||
};
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif // GIL_HSV_H
|
||||
@@ -0,0 +1,255 @@
|
||||
// Copyright 2008 Chung-Lin Wen.
|
||||
// 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 GIL_LAB_H
|
||||
#define GIL_LAB_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Support for CIE Lab color space
|
||||
/// \author Chung-Lin Wen \n
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/cast.hpp>
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \addtogroup ColorNameModel
|
||||
/// \{
|
||||
namespace lab_color_space
|
||||
{
|
||||
/// \brief Luminance
|
||||
struct luminance_t {};
|
||||
/// \brief a Color Component
|
||||
struct a_color_opponent_t {};
|
||||
/// \brief b Color Component
|
||||
struct b_color_opponent_t {};
|
||||
}
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
typedef mpl::vector3< lab_color_space::luminance_t
|
||||
, lab_color_space::a_color_opponent_t
|
||||
, lab_color_space::b_color_opponent_t
|
||||
> lab_t;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
typedef layout<lab_t> lab_layout_t;
|
||||
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS( 32f, lab );
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to LAB
|
||||
template <>
|
||||
struct default_color_converter_impl< rgb_t, lab_t >
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst ) const
|
||||
{
|
||||
using namespace lab_color_space;
|
||||
|
||||
// only bits32f for lab is supported
|
||||
bits32f temp_red = channel_convert<bits32f>( get_color( src, red_t() ));
|
||||
bits32f temp_green = channel_convert<bits32f>( get_color( src, green_t() ));
|
||||
bits32f temp_blue = channel_convert<bits32f>( get_color( src, blue_t() ));
|
||||
|
||||
// first, transfer to xyz color space
|
||||
bits32f normalized_r = temp_red / 255.f;
|
||||
bits32f normalized_g = temp_green / 255.f;
|
||||
bits32f normalized_b = temp_blue / 255.f;
|
||||
|
||||
if( normalized_r > 0.04045f )
|
||||
{
|
||||
normalized_r = pow( (( normalized_r + 0.055f ) / 1.055f ), 2.4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_r /= 12.92f;
|
||||
}
|
||||
|
||||
if( normalized_g > 0.04045f )
|
||||
{
|
||||
normalized_g = pow((( normalized_g + 0.055f ) / 1.055f ), 2.4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_g /= 12.92f;
|
||||
}
|
||||
|
||||
if( normalized_b > 0.04045f )
|
||||
{
|
||||
normalized_b = pow( (( normalized_b + 0.055f ) / 1.055f ), 2.4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_b /= 12.92f;
|
||||
}
|
||||
|
||||
normalized_r *= 100.f;
|
||||
normalized_g *= 100.f;
|
||||
normalized_b *= 100.f;
|
||||
|
||||
bits32f x, y, z;
|
||||
x = normalized_r * 0.4124f + normalized_g * 0.3576f + normalized_b * 0.1805f;
|
||||
y = normalized_r * 0.2126f + normalized_g * 0.7152f + normalized_b * 0.0722f;
|
||||
z = normalized_r * 0.0193f + normalized_g * 0.1192f + normalized_b * 0.9505f;
|
||||
|
||||
// then, transfer to lab color space
|
||||
bits32f ref_x = 95.047f;
|
||||
bits32f ref_y = 100.000f;
|
||||
bits32f ref_z = 108.883f;
|
||||
bits32f normalized_x = x / ref_x;
|
||||
bits32f normalized_y = y / ref_y;
|
||||
bits32f normalized_z = z / ref_z;
|
||||
|
||||
if( normalized_x > 0.008856f )
|
||||
{
|
||||
normalized_x = pow( normalized_x, 0.333f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_x = (7.787f * normalized_x) + ( 16.f/116.f );
|
||||
}
|
||||
|
||||
if( normalized_y > 0.008856f )
|
||||
{
|
||||
normalized_y = pow( normalized_y, 0.333f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_y = (7.787f * normalized_y) + ( 16.f/116.f );
|
||||
}
|
||||
|
||||
if( normalized_z > 0.008856f )
|
||||
{
|
||||
normalized_z = pow( normalized_z, 0.333f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_z = ( 7.787f * normalized_z ) + ( 16.f/116.f );
|
||||
}
|
||||
|
||||
bits32f luminance, a_color_opponent, b_color_opponent;
|
||||
luminance = ( 116.f * normalized_y ) - 16.f;
|
||||
a_color_opponent = 500.f * ( normalized_x - normalized_y );
|
||||
b_color_opponent = 200.f * ( normalized_y - normalized_z );
|
||||
|
||||
get_color( dst, luminance_t() ) = luminance;
|
||||
get_color( dst, a_color_opponent_t() ) = a_color_opponent;
|
||||
get_color( dst, b_color_opponent_t() ) = b_color_opponent;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief LAB to RGB
|
||||
template <>
|
||||
struct default_color_converter_impl<lab_t,rgb_t>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst) const
|
||||
{
|
||||
using namespace lab_color_space;
|
||||
|
||||
bits32f luminance = get_color( src, luminance_t() );
|
||||
bits32f a_color_opponent = get_color( src, a_color_opponent_t() );
|
||||
bits32f b_color_opponent = get_color( src, b_color_opponent_t() );
|
||||
|
||||
// first, transfer to xyz color space
|
||||
bits32f normalized_y = ( luminance + 16.f ) / 116.f;
|
||||
bits32f normalized_x = ( a_color_opponent / 500.f ) + normalized_y;
|
||||
bits32f normalized_z = normalized_y - ( b_color_opponent / 200.f );
|
||||
|
||||
if( pow( normalized_y, 3.f ) > 0.008856f )
|
||||
{
|
||||
normalized_y = pow( normalized_y, 3.f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_y = ( normalized_y - 16.f / 116.f ) / 7.787f;
|
||||
}
|
||||
|
||||
if( pow( normalized_x, 3.f ) > 0.008856f )
|
||||
{
|
||||
normalized_x = pow( normalized_x, 3.f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_x = ( normalized_x - 16.f / 116.f ) / 7.787f;
|
||||
}
|
||||
|
||||
if( pow( normalized_z, 3.f ) > 0.008856f )
|
||||
{
|
||||
normalized_z = pow( normalized_z, 3.f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_z = ( normalized_z - 16.f / 116.f ) / 7.787f;
|
||||
}
|
||||
|
||||
bits32f reference_x = 95.047f;
|
||||
bits32f reference_y = 100.000f;
|
||||
bits32f reference_z = 108.883f;
|
||||
bits32f x, y, z;
|
||||
x = reference_x * normalized_x;
|
||||
y = reference_y * normalized_y;
|
||||
z = reference_z * normalized_z;
|
||||
|
||||
// then, transfer to rgb color space
|
||||
normalized_x = x / 100.f;
|
||||
normalized_y = y / 100.f;
|
||||
normalized_z = z / 100.f;
|
||||
|
||||
bits32f result_r = normalized_x * 3.2406f + normalized_y * -1.5372f + normalized_z * -0.4986f;
|
||||
bits32f result_g = normalized_x * -0.9689f + normalized_y * 1.8758f + normalized_z * 0.0415f;
|
||||
bits32f result_b = normalized_x * 0.0557f + normalized_y * -0.2040f + normalized_z * 1.0570f;
|
||||
|
||||
if( result_r > 0.0031308f )
|
||||
{
|
||||
result_r = 1.055f * pow( result_r, 1.f/2.4f ) - 0.055f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_r = 12.92f * result_r;
|
||||
}
|
||||
|
||||
if( result_g > 0.0031308f )
|
||||
{
|
||||
result_g = 1.055f * pow( result_g, 1.f/2.4f ) - 0.055f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_g = 12.92f * result_g;
|
||||
}
|
||||
|
||||
if( result_b > 0.0031308f )
|
||||
{
|
||||
result_b = 1.055f * pow( result_b, 1.f/2.4f ) - 0.055f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_b = 12.92f * result_b;
|
||||
}
|
||||
|
||||
bits32f red, green, blue;
|
||||
red = result_r * 255.f;
|
||||
green = result_g * 255.f;
|
||||
blue = result_b * 255.f;
|
||||
|
||||
get_color(dst,red_t()) =
|
||||
channel_convert<typename color_element_type<P2, red_t>::type>( red );
|
||||
get_color(dst,green_t())=
|
||||
channel_convert<typename color_element_type<P2, green_t>::type>( green );
|
||||
get_color(dst,blue_t()) =
|
||||
channel_convert<typename color_element_type<P2, blue_t>::type>( blue );
|
||||
}
|
||||
};
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif // GIL_LAB_H
|
||||
@@ -0,0 +1,173 @@
|
||||
// Copyright 2008 Chung-Lin Wen.
|
||||
// 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 GIL_XYZ_H
|
||||
#define GIL_XYZ_H
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
/// \brief Support for CIE XYZ color space
|
||||
/// \author Chung-Lin Wen \n
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <boost/cast.hpp>
|
||||
#include <boost/gil/gil_all.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \addtogroup ColorNameModel
|
||||
/// \{
|
||||
namespace xyz_color_space
|
||||
{
|
||||
/// \brief x Color Component
|
||||
struct x_t {};
|
||||
/// \brief y Color Component
|
||||
struct y_t {};
|
||||
/// \brief z Color Component
|
||||
struct z_t {};
|
||||
}
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
typedef mpl::vector3< xyz_color_space::x_t
|
||||
, xyz_color_space::y_t
|
||||
, xyz_color_space::z_t
|
||||
> xyz_t;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
typedef layout<xyz_t> xyz_layout_t;
|
||||
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS( 32f, xyz );
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to XYZ
|
||||
template <>
|
||||
struct default_color_converter_impl< rgb_t, xyz_t >
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst ) const
|
||||
{
|
||||
using namespace xyz_color_space;
|
||||
|
||||
// only bits32f for xyz is supported
|
||||
bits32f temp_red = channel_convert<bits32f>( get_color( src, red_t() ));
|
||||
bits32f temp_green = channel_convert<bits32f>( get_color( src, green_t() ));
|
||||
bits32f temp_blue = channel_convert<bits32f>( get_color( src, blue_t() ));
|
||||
|
||||
bits32f normalized_r = temp_red / 255.f;
|
||||
bits32f normalized_g = temp_green / 255.f;
|
||||
bits32f normalized_b = temp_blue / 255.f;
|
||||
|
||||
if( normalized_r > 0.04045f )
|
||||
{
|
||||
normalized_r = pow((( normalized_r + 0.055f ) / 1.055f ), 2.4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_r /= 12.92f;
|
||||
}
|
||||
|
||||
if( normalized_g > 0.04045f )
|
||||
{
|
||||
normalized_g = pow((( normalized_g + 0.055f ) / 1.055f ), 2.4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_g /= 12.92f;
|
||||
}
|
||||
|
||||
if( normalized_b > 0.04045f )
|
||||
{
|
||||
normalized_b = pow((( normalized_b + 0.055f ) / 1.055f ), 2.4f );
|
||||
}
|
||||
else
|
||||
{
|
||||
normalized_b /= 12.92f;
|
||||
}
|
||||
|
||||
normalized_r *= 100.f;
|
||||
normalized_g *= 100.f;
|
||||
normalized_b *= 100.f;
|
||||
|
||||
bits32f x, y, z;
|
||||
x = normalized_r * 0.4124f + normalized_g * 0.3576f + normalized_b * 0.1805f;
|
||||
y = normalized_r * 0.2126f + normalized_g * 0.7152f + normalized_b * 0.0722f;
|
||||
z = normalized_r * 0.0193f + normalized_g * 0.1192f + normalized_b * 0.9505f;
|
||||
|
||||
get_color( dst, x_t() ) = x;
|
||||
get_color( dst, y_t() ) = y;
|
||||
get_color( dst, z_t() ) = z;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief XYZ to RGB
|
||||
template <>
|
||||
struct default_color_converter_impl<xyz_t,rgb_t>
|
||||
{
|
||||
template <typename P1, typename P2>
|
||||
void operator()( const P1& src, P2& dst) const
|
||||
{
|
||||
using namespace xyz_color_space;
|
||||
|
||||
bits32f x = get_color( src, x_t() );
|
||||
bits32f y = get_color( src, y_t() );
|
||||
bits32f z = get_color( src, z_t() );
|
||||
|
||||
bits32f normalized_x = x / 100.f;
|
||||
bits32f normalized_y = y / 100.f;
|
||||
bits32f normalized_z = z / 100.f;
|
||||
|
||||
bits32f result_r = normalized_x * 3.2406f + normalized_y * -1.5372f + normalized_z * -0.4986f;
|
||||
bits32f result_g = normalized_x * -0.9689f + normalized_y * 1.8758f + normalized_z * 0.0415f;
|
||||
bits32f result_b = normalized_x * 0.0557f + normalized_y * -0.2040f + normalized_z * 1.0570f;
|
||||
|
||||
if ( result_r > 0.0031308f )
|
||||
{
|
||||
result_r = 1.055f * pow( result_r, 1.f/2.4f ) - 0.055f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_r = 12.92f * result_r;
|
||||
}
|
||||
|
||||
if ( result_g > 0.0031308f )
|
||||
{
|
||||
result_g = 1.055f * pow( result_g, 1.f/2.4f ) - 0.055f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_g = 12.92f * result_g;
|
||||
}
|
||||
|
||||
if ( result_b > 0.0031308f )
|
||||
{
|
||||
result_b = 1.055f * pow( result_b, 1.f/2.4f ) - 0.055f;
|
||||
}
|
||||
else
|
||||
{
|
||||
result_b = 12.92f * result_b;
|
||||
}
|
||||
|
||||
bits32f red, green, blue;
|
||||
red = result_r * 255.f;
|
||||
green = result_g * 255.f;
|
||||
blue = result_b * 255.f;
|
||||
|
||||
get_color(dst,red_t()) =
|
||||
channel_convert<typename color_element_type<P2, red_t>::type>( red );
|
||||
get_color(dst,green_t())=
|
||||
channel_convert<typename color_element_type<P2, green_t>::type>( green );
|
||||
get_color(dst,blue_t()) =
|
||||
channel_convert<typename color_element_type<P2, blue_t>::type>( blue );
|
||||
}
|
||||
};
|
||||
|
||||
} } // namespace boost::gil
|
||||
|
||||
#endif // GIL_XYZ_H
|
||||
+6
-1
@@ -8,10 +8,15 @@ AC_LANG_CPLUSPLUS
|
||||
# Checks for programs
|
||||
AC_PROG_CXX
|
||||
|
||||
AC_CHECK_HEADERS([Wt/WApplication],
|
||||
AC_CHECK_HEADERS([Wt/WApplication jpeglib.h],
|
||||
[],
|
||||
[AC_MSG_ERROR([Header not found or unusable !])])
|
||||
|
||||
AC_CHECK_LIB([jpeg],
|
||||
[jpeg_destroy],
|
||||
,
|
||||
[AC_MSG_ERROR([libpthread not found!])])
|
||||
|
||||
AC_CHECK_LIB([pthread],
|
||||
[pthread_create],
|
||||
,
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
#include <boost/gil/image.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
#include <boost/gil/extension/io/jpeg_io.hpp>
|
||||
#include <boost/gil/extension/numeric/sampler.hpp>
|
||||
#include <boost/gil/extension/numeric/resample.hpp>
|
||||
#include <boost/gil/extension/io_new/jpeg_all.hpp>
|
||||
|
||||
#include "CoverArt.hpp"
|
||||
|
||||
namespace CoverArt {
|
||||
|
||||
bool
|
||||
CoverArt::scale(std::size_t size)
|
||||
{
|
||||
bool res = false;
|
||||
try {
|
||||
|
||||
boost::gil::rgb8_image_t source;
|
||||
boost::gil::rgb8_image_t dest(size, size);
|
||||
|
||||
// Read source
|
||||
{
|
||||
std::istringstream iss( std::string(_data.begin(), _data.end()));
|
||||
boost::gil::read_image(iss, source, boost::gil::jpeg_tag());
|
||||
}
|
||||
|
||||
// Resize
|
||||
boost::gil::resize_view(boost::gil::const_view(source),
|
||||
boost::gil::view(dest),
|
||||
boost::gil::bilinear_sampler());
|
||||
|
||||
// Output to dest
|
||||
{
|
||||
std::ostringstream oss;
|
||||
boost::gil::write_view(oss, boost::gil::const_view(dest), boost::gil::jpeg_tag());
|
||||
|
||||
std::string output = oss.str();
|
||||
_data.assign(output.begin(), output.end());
|
||||
}
|
||||
|
||||
res = true;
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cerr << "Caught exception: " << e.what() << std::endl;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
} // namespace CoverArt
|
||||
@@ -23,6 +23,8 @@ class CoverArt
|
||||
void setMimeType(const std::string& mimeType) { _mimeType = mimeType;}
|
||||
void setData(const data_type& data) { _data = data; }
|
||||
|
||||
bool scale(std::size_t size);
|
||||
|
||||
private:
|
||||
|
||||
std::string _mimeType;
|
||||
|
||||
@@ -251,8 +251,6 @@ AudioCollectionRequestHandler::processGetTracks(const AudioCollectionRequest::Ge
|
||||
BOOST_FOREACH(Genre::pointer genre, (*it)->getGenres())
|
||||
track->add_genre_id( genre.id() );
|
||||
|
||||
// if (!(*it)->getCoverArt().empty)
|
||||
// track->set_coverart( (*it)->getCoverArt() );
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -278,10 +276,13 @@ AudioCollectionRequestHandler::processGetCoverArt(const AudioCollectionRequest::
|
||||
|
||||
std::vector<CoverArt::CoverArt> coverArts = CoverArt::Grabber::getFromRelease(release);
|
||||
|
||||
BOOST_FOREACH(const CoverArt::CoverArt& coverArt, coverArts)
|
||||
BOOST_FOREACH(CoverArt::CoverArt& coverArt, coverArts)
|
||||
{
|
||||
AudioCollectionResponse_CoverArt* cover_art = response.add_cover_art();
|
||||
|
||||
if (request.has_size())
|
||||
coverArt.scale(request.size());
|
||||
|
||||
cover_art->set_mime_type(coverArt.getMimeType());
|
||||
cover_art->set_data( std::string( coverArt.getData().begin(), coverArt.getData().end()) );
|
||||
}
|
||||
@@ -299,10 +300,21 @@ AudioCollectionRequestHandler::processGetCoverArt(const AudioCollectionRequest::
|
||||
|
||||
std::vector<CoverArt::CoverArt> coverArts = CoverArt::Grabber::getFromTrack(track);
|
||||
|
||||
BOOST_FOREACH(const CoverArt::CoverArt& coverArt, coverArts)
|
||||
BOOST_FOREACH(CoverArt::CoverArt& coverArt, coverArts)
|
||||
{
|
||||
AudioCollectionResponse_CoverArt* cover_art = response.add_cover_art();
|
||||
|
||||
if (request.has_size())
|
||||
{
|
||||
std::size_t size = request.size();
|
||||
if (size > _maxCoverArtSize || size == 0)
|
||||
size = _maxCoverArtSize;
|
||||
if (size < _minCoverArtSize)
|
||||
size = _minCoverArtSize;
|
||||
|
||||
coverArt.scale(size);
|
||||
}
|
||||
|
||||
cover_art->set_mime_type(coverArt.getMimeType());
|
||||
cover_art->set_data( std::string( coverArt.getData().begin(), coverArt.getData().end()) );
|
||||
}
|
||||
|
||||
@@ -29,6 +29,9 @@ class AudioCollectionRequestHandler
|
||||
static const std::size_t _maxListGenres = 256;
|
||||
static const std::size_t _maxListReleases = 128;
|
||||
static const std::size_t _maxListTracks = 128;
|
||||
|
||||
static const std::size_t _minCoverArtSize = 64; // in pixels, square
|
||||
static const std::size_t _maxCoverArtSize = 512; // in pixels, square
|
||||
};
|
||||
|
||||
} // namespace Remote
|
||||
|
||||
+2
-1
@@ -12,6 +12,7 @@ remote_SOURCES = \
|
||||
$(top_srcdir)/av/FormatContext.cpp \
|
||||
$(top_srcdir)/av/InputFormatContext.cpp \
|
||||
$(top_srcdir)/av/Stream.cpp \
|
||||
$(top_srcdir)/cover/CoverArt.cpp \
|
||||
$(top_srcdir)/cover/CoverArtGrabber.cpp \
|
||||
$(top_srcdir)/remote/server/Server.cpp \
|
||||
$(top_srcdir)/remote/server/RequestHandler.cpp \
|
||||
@@ -38,7 +39,7 @@ remote_SOURCES = \
|
||||
$(top_srcdir)/database/Video.cpp \
|
||||
$(top_srcdir)/database/Checksum.cpp
|
||||
|
||||
remote_CXXFLAGS=-std=c++11 -Wall -Wextra -I$(top_srcdir) -I$(top_srcdir)/remote
|
||||
remote_CXXFLAGS=-std=c++11 -Wall -Wextra -I$(top_srcdir) -I$(top_srcdir)/remote -I$(top_srcdir)/boost
|
||||
|
||||
database_integrity_SOURCES = \
|
||||
$(srcdir)/DatabaseIntegrity.cpp \
|
||||
|
||||
-1878
File diff suppressed because it is too large
Load Diff
@@ -374,6 +374,7 @@ class TestClient
|
||||
request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest::TypeGetCoverArt);
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_type( Remote::AudioCollectionRequest::GetCoverArt::TypeGetCoverArtTrack);
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_track_id( trackId );
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_size( 100 );
|
||||
sendMsg(request);
|
||||
|
||||
// Receive responses
|
||||
@@ -404,6 +405,8 @@ class TestClient
|
||||
request.mutable_audio_collection_request()->set_type( Remote::AudioCollectionRequest::TypeGetCoverArt);
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_type( Remote::AudioCollectionRequest::GetCoverArt::TypeGetCoverArtRelease);
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_release_id( releaseId );
|
||||
request.mutable_audio_collection_request()->mutable_get_cover_art()->set_size( 100 );
|
||||
|
||||
sendMsg(request);
|
||||
|
||||
// Receive responses
|
||||
@@ -715,10 +718,18 @@ int main()
|
||||
{
|
||||
BOOST_FOREACH(const ReleaseInfo& release, releases)
|
||||
{
|
||||
std::vector<CoverArt> coverArt;
|
||||
client.getCoverRelease(coverArt, release.id);
|
||||
std::vector<CoverArt> coverArts;
|
||||
client.getCoverRelease(coverArts, release.id);
|
||||
|
||||
std::cout << "Release '" << release << "', spotted " << coverArt.size() << " covers!" << std::endl;
|
||||
BOOST_FOREACH(const CoverArt coverArt, coverArts)
|
||||
{
|
||||
std::ostringstream oss; oss << release.name << ".jpeg";
|
||||
std::ofstream out(oss.str().c_str());
|
||||
BOOST_FOREACH(unsigned char c, coverArt.data)
|
||||
out.put(c);
|
||||
}
|
||||
|
||||
std::cout << "Release '" << release << "', spotted " << coverArts.size() << " covers!" << std::endl;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const TrackInfo& track, tracks)
|
||||
|
||||
Reference in New Issue
Block a user