Added boost header

This commit is contained in:
Christophe Riccio
2012-01-08 01:26:07 +00:00
parent 9c3faaca40
commit c7d752cdf8
8946 changed files with 1732316 additions and 0 deletions

View File

@@ -0,0 +1,173 @@
/*
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 GIL_DYNAMICIMAGE_ALGORITHM_HPP
#define GIL_DYNAMICIMAGE_ALGORITHM_HPP
#include "../../algorithm.hpp"
#include "any_image.hpp"
#include <boost/bind.hpp>
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Some basic STL-style algorithms when applied to runtime type specified image views
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on September 24, 2006
///
////////////////////////////////////////////////////////////////////////////////////////
namespace boost { namespace gil {
namespace detail {
struct equal_pixels_fn : public binary_operation_obj<equal_pixels_fn,bool> {
template <typename V1, typename V2>
GIL_FORCEINLINE bool apply_compatible(const V1& v1, const V2& v2) const {
return equal_pixels(v1,v2);
}
};
} // namespace detail
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename View2> // Model MutableImageViewConcept
bool equal_pixels(const any_image_view<Types1>& src, const View2& dst) {
return apply_operation(src,boost::bind(detail::equal_pixels_fn(), _1, dst));
}
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
template <typename View1, // Model ImageViewConcept
typename Types2> // Model MPL Random Access Container of models of MutableImageViewConcept
bool equal_pixels(const View1& src, const any_image_view<Types2>& dst) {
return apply_operation(dst,boost::bind(detail::equal_pixels_fn(), src, _1));
}
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename Types2> // Model MPL Random Access Container of models of MutableImageViewConcept
bool equal_pixels(const any_image_view<Types1>& src, const any_image_view<Types2>& dst) {
return apply_operation(src,dst,detail::equal_pixels_fn());
}
namespace detail {
struct copy_pixels_fn : public binary_operation_obj<copy_pixels_fn> {
template <typename View1, typename View2>
GIL_FORCEINLINE void apply_compatible(const View1& src, const View2& dst) const {
copy_pixels(src,dst);
}
};
}
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename View2> // Model MutableImageViewConcept
void copy_pixels(const any_image_view<Types1>& src, const View2& dst) {
apply_operation(src,boost::bind(detail::copy_pixels_fn(), _1, dst));
}
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
template <typename View1, // Model ImageViewConcept
typename Types2> // Model MPL Random Access Container of models of MutableImageViewConcept
void copy_pixels(const View1& src, const any_image_view<Types2>& dst) {
apply_operation(dst,boost::bind(detail::copy_pixels_fn(), src, _1));
}
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename Types2> // Model MPL Random Access Container of models of MutableImageViewConcept
void copy_pixels(const any_image_view<Types1>& src, const any_image_view<Types2>& dst) {
apply_operation(src,dst,detail::copy_pixels_fn());
}
//forward declaration for default_color_converter (see full definition in color_convert.hpp)
struct default_color_converter;
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename View2, // Model MutableImageViewConcept
typename CC> // Model ColorConverterConcept
void copy_and_convert_pixels(const any_image_view<Types1>& src, const View2& dst, CC cc) {
apply_operation(src,boost::bind(detail::copy_and_convert_pixels_fn<CC>(cc), _1, dst));
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename View2> // Model MutableImageViewConcept
void copy_and_convert_pixels(const any_image_view<Types1>& src, const View2& dst) {
apply_operation(src,boost::bind(detail::copy_and_convert_pixels_fn<default_color_converter>(), _1, dst));
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
template <typename View1, // Model ImageViewConcept
typename Types2, // Model MPL Random Access Container of models of MutableImageViewConcept
typename CC> // Model ColorConverterConcept
void copy_and_convert_pixels(const View1& src, const any_image_view<Types2>& dst, CC cc) {
apply_operation(dst,boost::bind(detail::copy_and_convert_pixels_fn<CC>(cc), src, _1));
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
template <typename View1, // Model ImageViewConcept
typename Types2> // Model MPL Random Access Container of models of MutableImageViewConcept
void copy_and_convert_pixels(const View1& src, const any_image_view<Types2>& dst) {
apply_operation(dst,boost::bind(detail::copy_and_convert_pixels_fn<default_color_converter>(), src, _1));
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename Types2, // Model MPL Random Access Container of models of MutableImageViewConcept
typename CC> // Model ColorConverterConcept
void copy_and_convert_pixels(const any_image_view<Types1>& src, const any_image_view<Types2>& dst, CC cc) {
apply_operation(src,dst,detail::copy_and_convert_pixels_fn<CC>(cc));
}
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
template <typename Types1, // Model MPL Random Access Container of models of ImageViewConcept
typename Types2> // Model MPL Random Access Container of models of MutableImageViewConcept
void copy_and_convert_pixels(const any_image_view<Types1>& src, const any_image_view<Types2>& dst) {
apply_operation(src,dst,detail::copy_and_convert_pixels_fn<default_color_converter>());
}
namespace detail {
template <bool COMPATIBLE> struct fill_pixels_fn1 {
template <typename V, typename Value> static void apply(const V& src, const Value& val) { fill_pixels(src,val); }
};
// copy_pixels invoked on incompatible images
template <> struct fill_pixels_fn1<false> {
template <typename V, typename Value> static void apply(const V& src, const Value& val) { throw std::bad_cast();}
};
template <typename Value>
struct fill_pixels_fn {
fill_pixels_fn(const Value& val) : _val(val) {}
typedef void result_type;
template <typename V> result_type operator()(const V& img_view) const {
fill_pixels_fn1<pixels_are_compatible<typename V::value_type, Value>::value>::apply(img_view,_val);
}
Value _val;
};
}
/// \ingroup ImageViewSTLAlgorithmsFillPixels
/// \brief fill_pixels for any image view. The pixel to fill with must be compatible with the current view
template <typename Types, // Model MPL Random Access Container of models of MutableImageViewConcept
typename Value>
void fill_pixels(const any_image_view<Types>& img_view, const Value& val) {
apply_operation(img_view,detail::fill_pixels_fn<Value>(val));
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,125 @@
/*
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 GIL_DYNAMICIMAGE_ANY_IMAGE_HPP
#define GIL_DYNAMICIMAGE_ANY_IMAGE_HPP
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Support for run-time instantiated images and image views
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
///
///
////////////////////////////////////////////////////////////////////////////////////////
#include "any_image_view.hpp"
#include "../../image.hpp"
//#ifdef _MSC_VER
//#pragma warning(push)
//#pragma warning(disable : 4244) // conversion from 'std::ptrdiff_t' to 'int', possible loss of data. even if we static-assert the two types are the same (on visual studio 8)
//#endif
namespace boost { namespace gil {
namespace detail {
template <typename T> struct get_view_t { typedef typename T::view_t type; };
template <typename Images> struct images_get_views_t : public mpl::transform<Images, get_view_t<mpl::_1> > {};
template <typename T> struct get_const_view_t { typedef typename T::const_view_t type; };
template <typename Images> struct images_get_const_views_t : public mpl::transform<Images, get_const_view_t<mpl::_1> > {};
struct recreate_image_fnobj {
typedef void result_type;
const point2<std::ptrdiff_t>& _dimensions;
unsigned _alignment;
recreate_image_fnobj(const point2<std::ptrdiff_t>& dims, unsigned alignment) : _dimensions(dims), _alignment(alignment) {}
template <typename Image> result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); }
};
template <typename AnyView> // Models AnyViewConcept
struct any_image_get_view {
typedef AnyView result_type;
template <typename Image> result_type operator()( Image& img) const { return result_type(view(img)); }
};
template <typename AnyConstView> // Models AnyConstViewConcept
struct any_image_get_const_view {
typedef AnyConstView result_type;
template <typename Image> result_type operator()(const Image& img) const { return result_type(const_view(img)); }
};
}
////////////////////////////////////////////////////////////////////////////////////////
/// \ingroup ImageModel
/// \brief Represents a run-time specified image. Note it does NOT model ImageConcept
///
/// Represents an image whose type (color space, layout, planar/interleaved organization, etc) can be specified at run time.
/// It is the runtime equivalent of \p image.
/// Some of the requirements of ImageConcept, such as the \p value_type typedef cannot be fulfilled, since the language does not allow runtime type specification.
/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image does not fully model ImageConcept.
/// In particular, its \p view and \p const_view methods return \p any_image_view, which does not fully model ImageViewConcept. See \p any_image_view for more.
////////////////////////////////////////////////////////////////////////////////////////
template <typename ImageTypes>
class any_image : public variant<ImageTypes> {
typedef variant<ImageTypes> parent_t;
public:
typedef any_image_view<typename detail::images_get_const_views_t<ImageTypes>::type> const_view_t;
typedef any_image_view<typename detail::images_get_views_t<ImageTypes>::type> view_t;
typedef std::ptrdiff_t x_coord_t;
typedef std::ptrdiff_t y_coord_t;
typedef point2<std::ptrdiff_t> point_t;
any_image() : parent_t() {}
template <typename T> explicit any_image(const T& obj) : parent_t(obj) {}
template <typename T> explicit any_image(T& obj, bool do_swap) : parent_t(obj,do_swap) {}
any_image(const any_image& v) : parent_t((const parent_t&)v) {}
template <typename T> any_image& operator=(const T& obj) { parent_t::operator=(obj); return *this; }
any_image& operator=(const any_image& v) { parent_t::operator=((const parent_t&)v); return *this;}
void recreate(const point_t& dims, unsigned alignment=1) { apply_operation(*this,detail::recreate_image_fnobj(dims,alignment)); }
void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1) { recreate(point2<std::ptrdiff_t>(width,height),alignment); }
std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); }
point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); }
x_coord_t width() const { return dimensions().x; }
y_coord_t height() const { return dimensions().y; }
};
///@{
/// \name view, const_view
/// \brief Get an image view from a run-time instantiated image
/// \ingroup ImageModel
/// \brief Returns the non-constant-pixel view of any image. The returned view is any view.
template <typename Types> GIL_FORCEINLINE // Models ImageVectorConcept
typename any_image<Types>::view_t view(any_image<Types>& anyImage) {
return apply_operation(anyImage, detail::any_image_get_view<typename any_image<Types>::view_t>());
}
/// \brief Returns the constant-pixel view of any image. The returned view is any view.
template <typename Types> GIL_FORCEINLINE // Models ImageVectorConcept
typename any_image<Types>::const_view_t const_view(const any_image<Types>& anyImage) {
return apply_operation(anyImage, detail::any_image_get_const_view<typename any_image<Types>::const_view_t>());
}
///@}
} } // namespace boost::gil
//#ifdef _MSC_VER
//#pragma warning(pop)
//#endif
#endif

View File

@@ -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 GIL_DYNAMICIMAGE_ANY_IMAGEVIEW_HPP
#define GIL_DYNAMICIMAGE_ANY_IMAGEVIEW_HPP
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Support for run-time instantiated image view
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
///
///
////////////////////////////////////////////////////////////////////////////////////////
#include "variant.hpp"
#include "../../image_view.hpp"
#include "../../image.hpp"
namespace boost { namespace gil {
namespace detail {
template <typename View> struct get_const_t { typedef typename View::const_t type; };
template <typename Views> struct views_get_const_t : public mpl::transform<Views, get_const_t<mpl::_1> > {};
}
template <typename View> struct dynamic_xy_step_type;
template <typename View> struct dynamic_xy_step_transposed_type;
namespace detail {
struct any_type_get_num_channels { // works for both image_view and image
typedef int result_type;
template <typename T> result_type operator()(const T& v) const { return num_channels<T>::value; }
};
struct any_type_get_dimensions { // works for both image_view and image
typedef point2<std::ptrdiff_t> result_type;
template <typename T> result_type operator()(const T& v) const { return v.dimensions(); }
};
}
////////////////////////////////////////////////////////////////////////////////////////
/// CLASS any_image_view
///
/// \ingroup ImageViewModel
/// \brief Represents a run-time specified image view. Models HasDynamicXStepTypeConcept, HasDynamicYStepTypeConcept, Note that this class does NOT model ImageViewConcept
///
/// Represents a view whose type (color space, layout, planar/interleaved organization, etc) can be specified at run time.
/// It is the runtime equivalent of \p image_view.
/// Some of the requirements of ImageViewConcept, such as the \p value_type typedef cannot be fulfilled, since the language does not allow runtime type specification.
/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image_view does not fully model ImageViewConcept.
/// However, many algorithms provide overloads taking runtime specified views and thus in many cases \p any_image_view can be used in places taking a view.
///
/// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p apply_operation(runtime_view, algorithm_fn);
////////////////////////////////////////////////////////////////////////////////////////
template <typename ImageViewTypes>
class any_image_view : public variant<ImageViewTypes> {
typedef variant<ImageViewTypes> parent_t;
public:
typedef any_image_view<typename detail::views_get_const_t<ImageViewTypes>::type> const_t;
typedef std::ptrdiff_t x_coord_t;
typedef std::ptrdiff_t y_coord_t;
typedef point2<std::ptrdiff_t> point_t;
any_image_view() : parent_t() {}
template <typename T> explicit any_image_view(const T& obj) : parent_t(obj) {}
any_image_view(const any_image_view& v) : parent_t((const parent_t&)v) {}
template <typename T> any_image_view& operator=(const T& obj) { parent_t::operator=(obj); return *this; }
any_image_view& operator=(const any_image_view& v) { parent_t::operator=((const parent_t&)v); return *this;}
std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); }
point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); }
x_coord_t width() const { return dimensions().x; }
y_coord_t height() const { return dimensions().y; }
};
/////////////////////////////
// HasDynamicXStepTypeConcept
/////////////////////////////
template <typename IVTypes>
struct dynamic_x_step_type<any_image_view<IVTypes> > {
typedef any_image_view<typename mpl::transform<IVTypes, dynamic_x_step_type<mpl::_1> >::type> type;
};
/////////////////////////////
// HasDynamicYStepTypeConcept
/////////////////////////////
template <typename IVTypes>
struct dynamic_y_step_type<any_image_view<IVTypes> > {
typedef any_image_view<typename mpl::transform<IVTypes, dynamic_y_step_type<mpl::_1> >::type> type;
};
template <typename IVTypes>
struct dynamic_xy_step_type<any_image_view<IVTypes> > {
typedef any_image_view<typename mpl::transform<IVTypes, dynamic_xy_step_type<mpl::_1> >::type> type;
};
template <typename IVTypes>
struct dynamic_xy_step_transposed_type<any_image_view<IVTypes> > {
typedef any_image_view<typename mpl::transform<IVTypes, dynamic_xy_step_transposed_type<mpl::_1> >::type> type;
};
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,61 @@
/*
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 GIL_APPLY_OPERATION_HPP
#define GIL_APPLY_OPERATION_HPP
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Implements apply_operation for variants. Optionally performs type reduction
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on May 4, 2006
///
////////////////////////////////////////////////////////////////////////////////////////
#include "apply_operation_base.hpp"
#include "variant.hpp"
#ifndef GIL_REDUCE_CODE_BLOAT
namespace boost { namespace gil {
/// \ingroup Variant
/// \brief Invokes a generic mutable operation (represented as a unary function object) on a variant
template <typename Types, typename UnaryOp> GIL_FORCEINLINE
typename UnaryOp::result_type apply_operation(variant<Types>& arg, UnaryOp op) {
return apply_operation_base<Types>(arg._bits, arg._index ,op);
}
/// \ingroup Variant
/// \brief Invokes a generic constant operation (represented as a unary function object) on a variant
template <typename Types, typename UnaryOp> GIL_FORCEINLINE
typename UnaryOp::result_type apply_operation(const variant<Types>& arg, UnaryOp op) {
return apply_operation_basec<Types>(arg._bits, arg._index ,op);
}
/// \ingroup Variant
/// \brief Invokes a generic constant operation (represented as a binary function object) on two variants
template <typename Types1, typename Types2, typename BinaryOp> GIL_FORCEINLINE
typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op) {
return apply_operation_base<Types1,Types2>(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
}
} } // namespace boost::gil
#else
#include "reduce.hpp"
#endif
#endif

View File

@@ -0,0 +1,185 @@
/*
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 GIL_APPLY_OPERATION_BASE_HPP
#define GIL_APPLY_OPERATION_BASE_HPP
#include "../../gil_config.hpp"
#include "../../utilities.hpp"
#include <boost/mpl/begin.hpp>
#include <boost/mpl/next.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/size.hpp>
#include <boost/preprocessor/repeat.hpp>
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Given an object with run-time specified type (denoted as an array of Bits, dynamic index, and a static set of Types) and a generic operation,
/// casts the object to its appropriate type and applies the operation
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on November 6, 2007
///
////////////////////////////////////////////////////////////////////////////////////////
namespace boost { namespace gil {
/*
GENERATE_APPLY_FWD_OPS generates for every N functions that look like this (for N==2):
template <> struct apply_operation_fwd_fn<3> {
template <typename Types, typename Bits, typename UnaryOp>
typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const {
typedef typename mpl::begin<Types>::type T0;
typedef typename mpl::next<T0>::type T1;
typedef typename mpl::next<T1>::type T2;
switch (index) {
case 0: return op(reinterpret_cast<typename mpl::deref<T0>::type&>(bits));
case 1: return op(reinterpret_cast<typename mpl::deref<T1>::type&>(bits));
case 2: return op(reinterpret_cast<typename mpl::deref<T2>::type&>(bits));
}
throw;
}
template <typename Types, typename Bits, typename UnaryOp>
typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const {
typedef typename mpl::begin<Types>::type T0;
typedef typename mpl::next<T0>::type T1;
typedef typename mpl::next<T1>::type T2;
switch (index) {
case 0: return op(reinterpret_cast<const typename mpl::deref<T0>::type&>(bits));
case 1: return op(reinterpret_cast<const typename mpl::deref<T1>::type&>(bits));
case 2: return op(reinterpret_cast<const typename mpl::deref<T2>::type&>(bits));
}
throw;
}
};
*/
#define GIL_FWD_TYPEDEFS(z, N, text) T##N; typedef typename mpl::next<T##N>::type
#define GIL_FWD_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast<typename mpl::deref<T##N>::type*>(&bits));
#define GIL_FWD_CONST_CASE(z, N, SUM) case N: return op(*gil_reinterpret_cast_c<const typename mpl::deref<T##N>::type*>(&bits));
#define GIL_FWD_CASE_WITH_INFO(z, N, SUM) case N: return op(*gil_reinterpret_cast<typename mpl::deref<T##N>::type*>(&bits), info);
#define GIL_FWD_CONST_CASE_WITH_INFO(z, N, SUM) case N: return op(*gil_reinterpret_cast_c<const typename mpl::deref<T##N>::type*>(&bits), info);
#define GIL_APPLY_FWD_OP(z, N, text) \
template <> struct apply_operation_fwd_fn<BOOST_PP_ADD(N,1)> { \
template <typename Types, typename Bits, typename UnaryOp> \
typename UnaryOp::result_type apply(Bits& bits, std::size_t index, UnaryOp op) const { \
typedef typename mpl::begin<Types>::type \
BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
T##N; \
switch (index) { \
BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE, BOOST_PP_EMPTY) \
} \
throw; \
} \
template <typename Types, typename Bits, typename UnaryOp> \
typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, UnaryOp op) const { \
typedef typename mpl::begin<Types>::type \
BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
T##N; \
switch (index) { \
BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE,BOOST_PP_EMPTY) \
} \
throw; \
} \
template <typename Types, typename Info, typename Bits, typename UnaryOp> \
typename UnaryOp::result_type apply(Bits& bits, std::size_t index, const Info& info, UnaryOp op) const { \
typedef typename mpl::begin<Types>::type \
BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
T##N; \
switch (index) { \
BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CASE_WITH_INFO, BOOST_PP_EMPTY) \
} \
throw; \
} \
template <typename Types, typename Bits, typename Info, typename UnaryOp> \
typename UnaryOp::result_type applyc(const Bits& bits, std::size_t index, const Info& info, UnaryOp op) const { \
typedef typename mpl::begin<Types>::type \
BOOST_PP_REPEAT(N, GIL_FWD_TYPEDEFS, BOOST_PP_EMPTY) \
T##N; \
switch (index) { \
BOOST_PP_REPEAT(BOOST_PP_ADD(N,1), GIL_FWD_CONST_CASE_WITH_INFO,BOOST_PP_EMPTY) \
} \
throw; \
} \
};
#define GIL_GENERATE_APPLY_FWD_OPS(N) BOOST_PP_REPEAT(N, GIL_APPLY_FWD_OP, BOOST_PP_EMPTY)
namespace detail {
template <std::size_t N> struct apply_operation_fwd_fn {};
// Create specializations of apply_operation_fn for each N 0..100
GIL_GENERATE_APPLY_FWD_OPS(99)
} // namespace detail
// unary application
template <typename Types, typename Bits, typename Op>
typename Op::result_type GIL_FORCEINLINE apply_operation_basec(const Bits& bits, std::size_t index, Op op) {
return detail::apply_operation_fwd_fn<mpl::size<Types>::value>().template applyc<Types>(bits,index,op);
}
// unary application
template <typename Types, typename Bits, typename Op>
typename Op::result_type GIL_FORCEINLINE apply_operation_base( Bits& bits, std::size_t index, Op op) {
return detail::apply_operation_fwd_fn<mpl::size<Types>::value>().template apply<Types>(bits,index,op);
}
namespace detail {
template <typename T2, typename Op>
struct reduce_bind1 {
const T2& _t2;
Op& _op;
typedef typename Op::result_type result_type;
reduce_bind1(const T2& t2, Op& op) : _t2(t2), _op(op) {}
template <typename T1> GIL_FORCEINLINE result_type operator()(const T1& t1) { return _op(t1, _t2); }
};
template <typename Types1, typename Bits1, typename Op>
struct reduce_bind2 {
const Bits1& _bits1;
std::size_t _index1;
Op& _op;
typedef typename Op::result_type result_type;
reduce_bind2(const Bits1& bits1, std::size_t index1, Op& op) : _bits1(bits1), _index1(index1), _op(op) {}
template <typename T2> GIL_FORCEINLINE result_type operator()(const T2& t2) {
return apply_operation_basec<Types1>(_bits1, _index1, reduce_bind1<T2,Op>(t2, _op));
}
};
} // namespace detail
// Binary application by applying on each dimension separately
template <typename Types1, typename Types2, typename Bits1, typename Bits2, typename Op>
static typename Op::result_type GIL_FORCEINLINE apply_operation_base(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
return apply_operation_basec<Types2>(bits2,index2,detail::reduce_bind2<Types1,Bits1,Op>(bits1,index1,op));
}
#undef GIL_FWD_TYPEDEFS
#undef GIL_FWD_CASE
#undef GIL_FWD_CONST_CASE
#undef GIL_APPLY_FWD_OP
#undef GIL_GENERATE_APPLY_FWD_OPS
#undef BHS
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,130 @@
/*
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 GIL_DYNAMIC_AT_C_HPP
#define GIL_DYNAMIC_AT_C_HPP
#include "../../gil_config.hpp"
#include <cassert>
#include <stdexcept>
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Constructs for static-to-dynamic integer convesion
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on May 4, 2006
///
////////////////////////////////////////////////////////////////////////////////////////
namespace boost { namespace gil {
#define GIL_AT_C_VALUE(z, N, text) mpl::at_c<IntTypes,S+N>::type::value,
#define GIL_DYNAMIC_AT_C_LIMIT 226 // size of the maximum vector to handle
#define GIL_AT_C_LOOKUP(z, NUM, text) \
template<std::size_t S> \
struct at_c_fn<S,NUM> { \
template <typename IntTypes, typename ValueType> inline \
static ValueType apply(std::size_t index) { \
static ValueType table[] = { \
BOOST_PP_REPEAT(NUM, GIL_AT_C_VALUE, BOOST_PP_EMPTY) \
}; \
return table[index]; \
} \
};
namespace detail {
namespace at_c {
template <std::size_t START, std::size_t NUM> struct at_c_fn;
BOOST_PP_REPEAT(GIL_DYNAMIC_AT_C_LIMIT, GIL_AT_C_LOOKUP, BOOST_PP_EMPTY)
template <std::size_t QUOT> struct at_c_impl;
template <>
struct at_c_impl<0> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
return at_c_fn<0,mpl::size<IntTypes>::value>::template apply<IntTypes,ValueType>(index);
}
};
template <>
struct at_c_impl<1> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
const std::size_t SIZE=mpl::size<IntTypes>::value;
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
};
throw;
}
};
template <>
struct at_c_impl<2> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
const std::size_t SIZE=mpl::size<IntTypes>::value;
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
case 2: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*2,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*2);
};
throw;
}
};
template <>
struct at_c_impl<3> {
template <typename IntTypes, typename ValueType> inline
static ValueType apply(std::size_t index) {
const std::size_t SIZE=mpl::size<IntTypes>::value;
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
case 2: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*2,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*2);
case 3: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*3,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*3);
};
throw;
}
};
}
}
////////////////////////////////////////////////////////////////////////////////////
///
/// \brief Given an MPL Random Access Sequence and a dynamic index n, returns the value of the n-th element
/// It constructs a lookup table at compile time
///
////////////////////////////////////////////////////////////////////////////////////
template <typename IntTypes, typename ValueType> inline
ValueType at_c(std::size_t index) {
const std::size_t Size=mpl::size<IntTypes>::value;
return detail::at_c::at_c_impl<Size/GIL_DYNAMIC_AT_C_LIMIT>::template apply<IntTypes,ValueType>(index);
}
#undef GIL_AT_C_VALUE
#undef GIL_DYNAMIC_AT_C_LIMIT
#undef GIL_AT_C_LOOKUP
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,32 @@
/*
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 GIL_DYNAMICIMAGE_ALL_HPP
#define GIL_DYNAMICIMAGE_ALL_HPP
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Includes all of the GIL dynamic image extension files, for convenience
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on May 8, 2006
///
////////////////////////////////////////////////////////////////////////////////////////
#include "../../gil_all.hpp"
#include "algorithm.hpp"
#include "any_image.hpp"
#include "apply_operation.hpp"
#include "variant.hpp"
#include "image_view_factory.hpp"
#endif

View File

@@ -0,0 +1,217 @@
/*
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 GIL_DYNAMICIMAGE_IMAGE_VIEWS_HPP
#define GIL_DYNAMICIMAGE_IMAGE_VIEWS_HPP
/*!
/// \file
/// \brief Methods for constructing any image views from other any image views
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on January 31, 2007
/// Extends image view factory to runtime type-specified views (any_image_view)
*/
#include "any_image_view.hpp"
#include "../../image_view_factory.hpp"
namespace boost { namespace gil {
namespace detail {
template <typename Result> struct flipped_up_down_view_fn {
typedef Result result_type;
template <typename View> result_type operator()(const View& src) const { return result_type(flipped_up_down_view(src)); }
};
template <typename Result> struct flipped_left_right_view_fn {
typedef Result result_type;
template <typename View> result_type operator()(const View& src) const { return result_type(flipped_left_right_view(src)); }
};
template <typename Result> struct rotated90cw_view_fn {
typedef Result result_type;
template <typename View> result_type operator()(const View& src) const { return result_type(rotated90cw_view(src)); }
};
template <typename Result> struct rotated90ccw_view_fn {
typedef Result result_type;
template <typename View> result_type operator()(const View& src) const { return result_type(rotated90ccw_view(src)); }
};
template <typename Result> struct tranposed_view_fn {
typedef Result result_type;
template <typename View> result_type operator()(const View& src) const { return result_type(tranposed_view(src)); }
};
template <typename Result> struct rotated180_view_fn {
typedef Result result_type;
template <typename View> result_type operator()(const View& src) const { return result_type(rotated180_view(src)); }
};
template <typename Result> struct subimage_view_fn {
typedef Result result_type;
subimage_view_fn(const point2<std::ptrdiff_t>& topleft, const point2<std::ptrdiff_t>& dimensions) : _topleft(topleft), _size2(dimensions) {}
point2<std::ptrdiff_t> _topleft,_size2;
template <typename View> result_type operator()(const View& src) const { return result_type(subimage_view(src,_topleft,_size2)); }
};
template <typename Result> struct subsampled_view_fn {
typedef Result result_type;
subsampled_view_fn(const point2<std::ptrdiff_t>& step) : _step(step) {}
point2<std::ptrdiff_t> _step;
template <typename View> result_type operator()(const View& src) const { return result_type(subsampled_view(src,_step)); }
};
template <typename Result> struct nth_channel_view_fn {
typedef Result result_type;
nth_channel_view_fn(int n) : _n(n) {}
int _n;
template <typename View> result_type operator()(const View& src) const { return result_type(nth_channel_view(src,_n)); }
};
template <typename DstP, typename Result, typename CC = default_color_converter> struct color_converted_view_fn {
typedef Result result_type;
color_converted_view_fn(CC cc = CC()): _cc(cc) {}
template <typename View> result_type operator()(const View& src) const { return result_type(color_converted_view<DstP>(src, _cc)); }
private:
CC _cc;
};
} // namespace detail
/// \ingroup ImageViewTransformationsFlipUD
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_y_step_type<any_image_view<ViewTypes> >::type flipped_up_down_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::flipped_up_down_view_fn<typename dynamic_y_step_type<any_image_view<ViewTypes> >::type>());
}
/// \ingroup ImageViewTransformationsFlipLR
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_x_step_type<any_image_view<ViewTypes> >::type flipped_left_right_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::flipped_left_right_view_fn<typename dynamic_x_step_type<any_image_view<ViewTypes> >::type>());
}
/// \ingroup ImageViewTransformationsTransposed
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type transposed_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::tranposed_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
}
/// \ingroup ImageViewTransformations90CW
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type rotated90cw_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::rotated90cw_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
}
/// \ingroup ImageViewTransformations90CCW
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type rotated90ccw_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::rotated90ccw_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
}
/// \ingroup ImageViewTransformations180
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type rotated180_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::rotated180_view_fn<typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type>());
}
/// \ingroup ImageViewTransformationsSubimage
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
any_image_view<ViewTypes> subimage_view(const any_image_view<ViewTypes>& src, const point2<std::ptrdiff_t>& topleft, const point2<std::ptrdiff_t>& dimensions) {
return apply_operation(src,detail::subimage_view_fn<any_image_view<ViewTypes> >(topleft,dimensions));
}
/// \ingroup ImageViewTransformationsSubimage
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
any_image_view<ViewTypes> subimage_view(const any_image_view<ViewTypes>& src, int xMin, int yMin, int width, int height) {
return apply_operation(src,detail::subimage_view_fn<any_image_view<ViewTypes> >(point2<std::ptrdiff_t>(xMin,yMin),point2<std::ptrdiff_t>(width,height)));
}
/// \ingroup ImageViewTransformationsSubsampled
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type subsampled_view(const any_image_view<ViewTypes>& src, const point2<std::ptrdiff_t>& step) {
return apply_operation(src,detail::subsampled_view_fn<typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type>(step));
}
/// \ingroup ImageViewTransformationsSubsampled
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type subsampled_view(const any_image_view<ViewTypes>& src, int xStep, int yStep) {
return apply_operation(src,detail::subsampled_view_fn<typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type>(point2<std::ptrdiff_t>(xStep,yStep)));
}
namespace detail {
template <typename View> struct get_nthchannel_type { typedef typename nth_channel_view_type<View>::type type; };
template <typename Views> struct views_get_nthchannel_type : public mpl::transform<Views, get_nthchannel_type<mpl::_1> > {};
}
/// \ingroup ImageViewTransformationsNthChannel
/// \brief Given a runtime source image view, returns the type of a runtime image view over a single channel of the source view
template <typename ViewTypes>
struct nth_channel_view_type<any_image_view<ViewTypes> > {
typedef any_image_view<typename detail::views_get_nthchannel_type<ViewTypes>::type> type;
};
/// \ingroup ImageViewTransformationsNthChannel
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename nth_channel_view_type<any_image_view<ViewTypes> >::type nth_channel_view(const any_image_view<ViewTypes>& src, int n) {
return apply_operation(src,detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes> >::type>(n));
}
namespace detail {
template <typename View, typename DstP, typename CC> struct get_ccv_type : public color_converted_view_type<View, DstP, CC> {};
template <typename Views, typename DstP, typename CC> struct views_get_ccv_type : public mpl::transform<Views, get_ccv_type<mpl::_1,DstP,CC> > {};
}
/// \ingroup ImageViewTransformationsColorConvert
/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with user specified color converter
template <typename ViewTypes, typename DstP, typename CC>
struct color_converted_view_type<any_image_view<ViewTypes>,DstP,CC> {
typedef any_image_view<typename detail::views_get_ccv_type<ViewTypes, DstP, CC>::type> type;
};
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with user defined color-converter
template <typename DstP, typename ViewTypes, typename CC> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type color_converted_view(const any_image_view<ViewTypes>& src,CC cc) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
}
/// \ingroup ImageViewTransformationsColorConvert
/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with the default coor converter
template <typename ViewTypes, typename DstP>
struct color_converted_view_type<any_image_view<ViewTypes>,DstP> {
typedef any_image_view<typename detail::views_get_ccv_type<ViewTypes, DstP, default_color_converter>::type> type;
};
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with the default color-converter
template <typename DstP, typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type color_converted_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type >());
}
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with user defined color-converter
/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
template <typename DstP, typename ViewTypes, typename CC> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type any_color_converted_view(const any_image_view<ViewTypes>& src,CC cc) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
}
/// \ingroup ImageViewTransformationsColorConvert
/// \brief overload of generic color_converted_view with the default color-converter
/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
template <typename DstP, typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type any_color_converted_view(const any_image_view<ViewTypes>& src) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type >());
}
/// \}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,789 @@
/*
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 GIL_REDUCE_HPP
#define GIL_REDUCE_HPP
#include <boost/mpl/insert_range.hpp>
#include <boost/mpl/range_c.hpp>
#include <boost/mpl/vector_c.hpp>
#include <boost/mpl/back.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/long.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/insert.hpp>
#include <boost/mpl/transform.hpp>
#include "../../metafunctions.hpp"
#include "../../typedefs.hpp"
#include "dynamic_at_c.hpp"
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Constructs for static-to-dynamic integer convesion
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on May 4, 2006
///
////////////////////////////////////////////////////////////////////////////////////////
#ifdef GIL_REDUCE_CODE_BLOAT
// Max number of cases in the cross-expension of binary operation for it to be reduced as unary
#define GIL_BINARY_REDUCE_LIMIT 226
namespace boost { namespace mpl {
///////////////////////////////////////////////////////
/// Mapping vector - represents the mapping of one type vector to another
/// It is not a full-blown MPL Random Access Type sequence; just has at_c and size implemented
///
/// SrcTypes, DstTypes: MPL Random Access Type Sequences
///
/// Implements size and at_c to behave as if this is an MPL vector of integers
///////////////////////////////////////////////////////
template <typename SrcTypes, typename DstTypes>
struct mapping_vector {};
template <typename SrcTypes, typename DstTypes, long K>
struct at_c<mapping_vector<SrcTypes,DstTypes>, K> {
static const std::size_t value=size<DstTypes>::value - order<DstTypes, typename at_c<SrcTypes,K>::type>::type::value +1;
typedef size_t<value> type;
};
template <typename SrcTypes, typename DstTypes>
struct size<mapping_vector<SrcTypes,DstTypes> > {
typedef typename size<SrcTypes>::type type;
static const std::size_t value=type::value;
};
///////////////////////////////////////////////////////
/// copy_to_vector - copies a sequence (mpl::set) to vector.
///
/// Temporary solution because I couldn't get mpl::copy to do this.
/// This is what I tried:
/// mpl::copy<SET, mpl::back_inserter<mpl::vector<> > >::type;
/// It works when SET is mpl::vector, but not when SET is mpl::set...
///////////////////////////////////////////////////////
namespace detail {
template <typename SFirst, std::size_t NLeft>
struct copy_to_vector_impl {
private:
typedef typename deref<SFirst>::type T;
typedef typename next<SFirst>::type next;
typedef typename copy_to_vector_impl<next, NLeft-1>::type rest;
public:
typedef typename push_front<rest, T>::type type;
};
template <typename SFirst>
struct copy_to_vector_impl<SFirst,1> {
typedef vector<typename deref<SFirst>::type> type;
};
}
template <typename Src>
struct copy_to_vector {
typedef typename detail::copy_to_vector_impl<typename begin<Src>::type, size<Src>::value>::type type;
};
template <>
struct copy_to_vector<set<> > {
typedef vector0<> type;
};
} } // boost::mpl
namespace boost { namespace gil {
///////////////////////////////////////////////////////
///
/// unary_reduce, binary_reduce - given an MPL Random Access Sequence,
/// dynamically specified index to that container, the bits of an instance of the corresponding type and
/// a generic operation, invokes the operation on the given type
///
///////////////////////////////////////////////////////
///////////////////////////////////////////////////////
///
/// \brief Unary reduce.
///
/// Given a set of types and an operation, reduces each type in the set (to reduced_t), then removes duplicates (to unique_t)
/// To apply the operation, first constructs a lookup table that maps each element from Types to its place in unique_t and uses it to map
/// the index to anther index (in map_index). Then invokes apply_operation_base on the unique types with the new index.
///
///////////////////////////////////////////////////////
template <typename Types, typename Op>
struct unary_reduce_impl {
typedef typename mpl::transform<Types, detail::reduce<Op, mpl::_1> >::type reduced_t;
typedef typename mpl::copy<reduced_t, mpl::inserter<mpl::set<>, mpl::insert<mpl::_1,mpl::_2> > >::type unique_t;
static const bool is_single=mpl::size<unique_t>::value==1;
};
template <typename Types, typename Op, bool IsSingle=unary_reduce_impl<Types,Op>::is_single>
struct unary_reduce : public unary_reduce_impl<Types,Op> {
typedef typename unary_reduce_impl<Types,Op>::reduced_t reduced_t;
typedef typename unary_reduce_impl<Types,Op>::unique_t unique_t;
static unsigned short inline map_index(std::size_t index) {
typedef typename mpl::mapping_vector<reduced_t, unique_t> indices_t;
return gil::at_c<indices_t, unsigned short>(index);
}
template <typename Bits> GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
return apply_operation_basec<unique_t>(bits,map_index(index),op);
}
template <typename Bits> GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
return apply_operation_base<unique_t>(bits,map_index(index),op);
}
};
template <typename Types, typename Op>
struct unary_reduce<Types,Op,true> : public unary_reduce_impl<Types,Op> {
typedef typename unary_reduce_impl<Types,Op>::unique_t unique_t;
static unsigned short inline map_index(std::size_t index) { return 0; }
template <typename Bits> GIL_FORCEINLINE static typename Op::result_type applyc(const Bits& bits, std::size_t index, Op op) {
return op(*gil_reinterpret_cast_c<const typename mpl::front<unique_t>::type*>(&bits));
}
template <typename Bits> GIL_FORCEINLINE static typename Op::result_type apply(Bits& bits, std::size_t index, Op op) {
return op(*gil_reinterpret_cast<typename mpl::front<unique_t>::type*>(&bits));
}
};
///////////////////////////////////////////////////////
///
/// \brief Binary reduce.
///
/// Given two sets of types, Types1 and Types2, first performs unary reduction on each. Then checks if the product of their sizes is above
/// the GIL_BINARY_REDUCE_LIMIT limit. If so, the operation is too complex to be binary-reduced and uses a specialization of binary_reduce_impl
/// to simply call the binary apply_operation_base (which performs two nested 1D apply operations)
/// If the operation is not too complex, uses the other specialization of binary_reduce_impl to create a cross-product of the input types
/// and performs unary reduction on the result (bin_reduced_t). To apply the binary operation, it simply invokes a unary apply_operation_base
/// on the reduced cross-product types
///
///////////////////////////////////////////////////////
namespace detail {
struct pair_generator {
template <typename Vec2> struct apply {
typedef std::pair<const typename mpl::at_c<Vec2,0>::type*, const typename mpl::at_c<Vec2,1>::type*> type;
};
};
// When the types are not too large, applies reduce on their cross product
template <typename Unary1, typename Unary2, typename Op, bool IsComplex>
struct binary_reduce_impl {
//private:
typedef typename mpl::copy_to_vector<typename Unary1::unique_t>::type vec1_types;
typedef typename mpl::copy_to_vector<typename Unary2::unique_t>::type vec2_types;
typedef mpl::cross_vector<mpl::vector2<vec1_types, vec2_types>, pair_generator> BIN_TYPES;
typedef unary_reduce<BIN_TYPES,Op> bin_reduced_t;
static unsigned short inline map_index(std::size_t index1, std::size_t index2) {
unsigned short r1=Unary1::map_index(index1);
unsigned short r2=Unary2::map_index(index2);
return bin_reduced_t::map_index(r2*mpl::size<vec1_types>::value + r1);
}
public:
typedef typename bin_reduced_t::unique_t unique_t;
template <typename Bits1, typename Bits2>
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
std::pair<const void*,const void*> pr(&bits1, &bits2);
return apply_operation_basec<unique_t>(pr, map_index(index1,index2),op);
}
};
// When the types are large performs a double-dispatch. Binary reduction is not done.
template <typename Unary1, typename Unary2, typename Op>
struct binary_reduce_impl<Unary1,Unary2,Op,true> {
template <typename Bits1, typename Bits2>
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
return apply_operation_base<Unary1::unique_t,Unary2::unique_t>(bits1, index1, bits2, index2, op);
}
};
}
template <typename Types1, typename Types2, typename Op>
struct binary_reduce {
//private:
typedef unary_reduce<Types1,Op> unary1_t;
typedef unary_reduce<Types2,Op> unary2_t;
static const std::size_t CROSS_SIZE = mpl::size<typename unary1_t::unique_t>::value *
mpl::size<typename unary2_t::unique_t>::value;
typedef detail::binary_reduce_impl<unary1_t,unary2_t,Op, (CROSS_SIZE>GIL_BINARY_REDUCE_LIMIT)> impl;
public:
template <typename Bits1, typename Bits2>
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
return impl::apply(bits1,index1,bits2,index2,op);
}
};
template <typename Types, typename UnaryOp>
GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(variant<Types>& arg, UnaryOp op) {
return unary_reduce<Types,UnaryOp>::template apply(arg._bits, arg._index ,op);
}
template <typename Types, typename UnaryOp>
GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(const variant<Types>& arg, UnaryOp op) {
return unary_reduce<Types,UnaryOp>::template applyc(arg._bits, arg._index ,op);
}
template <typename Types1, typename Types2, typename BinaryOp>
GIL_FORCEINLINE typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op) {
return binary_reduce<Types1,Types2,BinaryOp>::template apply(arg1._bits, arg1._index, arg2._bits, arg2._index, op);
}
#undef GIL_BINARY_REDUCE_LIMIT
} } // namespace gil
namespace boost { namespace mpl {
///////////////////////////////////////////////////////
/// \brief Represents the virtual cross-product of the types generated from VecOfVecs.
/// \ingroup CrossVector
/// INPUT:
/// VecOfVecs - a vector of vector types. For example [ [A1,A2,A3], [B1,B2], [C1,C2,C3,C4] ]
/// Each element must be a non-empty mpl vector
/// TypeGen - a metafunction that generates a type from a vector of types, each of which can be
/// selected from the corresponding vector in VecOfVecs. For example, [A1, B2, C4]
///
/// Represents the virtual cross-product of the types generated from VecOfVecs.
/// For example, [ TypeGen[A1,B1,C1], TypeGen[A2,B1,C1], TypeGen[A3,B1,C1],
/// TypeGen[A1,B2,C1], TypeGen[A2,B2,C1], TypeGen[A3,B2,C1],
/// TypeGen[A1,B1,C2], TypeGen[A2,B1,C2], TypeGen[A3,B1,C2], ... ]
///
/// Models an immutable MPL Random Access Sequence
/// Traversal, random-access, etc, is defined, but mutable operations,
/// such as push_back and pop_front are not supported
///////////////////////////////////////////////////////
template <typename VecOfVecs, typename TypeGen>
struct cross_vector {};
/// \brief Iterator of cross_vector
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct cross_iterator {
typedef mpl::random_access_iterator_tag category;
};
///////////////////////////////////////////////////////
/// Implementation of the iterator functions of cross vector
///////////////////////////////////////////////////////
/// \brief Dereferences a cross-vector iterator
/// \ingroup CrossVectorIterator
/// Creates a vector of the sizes of each type vector in VecOfVecs, then uses it as a basis
/// to represent the iterator's position K as a vector of indices. Extracts the corresponding type of
/// each input vector and passes the element types to the type generation function, which returns the dereferenced type
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct deref<cross_iterator<VecOfVecs,TypeGen,K> > {
private:
typedef typename detail::select_subvector_c<VecOfVecs, K>::type DerefTypes;
public:
typedef typename TypeGen::template apply<DerefTypes>::type type;
};
/// \brief Increments a cross-vector iterator.
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct next<cross_iterator<VecOfVecs,TypeGen,K> > {
typedef cross_iterator<VecOfVecs,TypeGen,K+1> type;
};
/// \brief Decrements a cross-vector iterator.
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K>
struct prior<cross_iterator<VecOfVecs,TypeGen,K> > {
typedef cross_iterator<VecOfVecs,TypeGen,K-1> type;
};
/// \brief Advances a cross-vector iterator.
/// \ingroup CrossVectorIterator
template <typename VecOfVecs, typename TypeGen, std::size_t K, typename Distance>
struct advance<cross_iterator<VecOfVecs,TypeGen,K>, Distance > {
typedef cross_iterator<VecOfVecs,TypeGen,K+Distance::value> type;
};
/// \brief Computes the distance between two cross-vector iterator-s.
/// \ingroup CrossVectorIterator
// (shortened the names of the template arguments - otherwise doxygen cannot parse this...)
template <typename VecOfVecs, typename TypeGen, std::size_t K1, std::size_t K2>
struct distance<cross_iterator<VecOfVecs,TypeGen,K1>, cross_iterator<VecOfVecs,TypeGen,K2> > {
typedef size_t<K2-K1> type;
};
///////////////////////////////////////////////////////
/// Implementation of cross vector
///////////////////////////////////////////////////////
/// \brief Computes the size of a cross vector as the product of the sizes of all vectors in VecOfVecs
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct size<cross_vector<VecOfVecs,TypeGen> > {
typedef typename fold<VecOfVecs, size_t<1>, times<_1, size<_2> > >::type type;
static const std::size_t value=type::value;
};
/// \brief Determines whether a cross vector is empty
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct empty<cross_vector<VecOfVecs,TypeGen> > {
typedef typename empty<VecOfVecs>::type type;
};
/// \brief Returns the K-th element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen, typename K>
struct at<cross_vector<VecOfVecs,TypeGen>, K> {
private:
typedef cross_iterator<VecOfVecs,TypeGen,K::value> KthIterator;
public:
typedef typename deref<KthIterator>::type type;
};
/// \brief Returns an iterator to the first element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct begin<cross_vector<VecOfVecs,TypeGen> > {
typedef cross_iterator<VecOfVecs,TypeGen,0> type;
};
/// \brief Returns an iterator to the last element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct end<cross_vector<VecOfVecs,TypeGen> > {
private:
typedef cross_vector<VecOfVecs,TypeGen> this_t;
public:
typedef cross_iterator<VecOfVecs,TypeGen,size<this_t>::value> type;
};
/// \brief Returns the first element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct front<cross_vector<VecOfVecs,TypeGen> > {
private:
typedef cross_vector<VecOfVecs,TypeGen> this_t;
public:
typedef typename deref<typename begin<this_t>::type>::type type;
};
/// \brief Returns the last element of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen>
struct back<cross_vector<VecOfVecs,TypeGen> > {
private:
typedef cross_vector<VecOfVecs,TypeGen> this_t;
typedef typename size<this_t>::type size;
typedef typename minus<size, size_t<1> >::type last_index;
public:
typedef typename at<this_t, last_index>::type type;
};
/// \brief Transforms the elements of a cross vector
/// \ingroup CrossVector
template <typename VecOfVecs, typename TypeGen, typename OPP>
struct transform<cross_vector<VecOfVecs,TypeGen>, OPP > {
typedef typename lambda<OPP>::type Op;
struct adapter {
template <typename Elements>
struct apply {
typedef typename TypeGen::template apply<Elements>::type orig_t;
typedef typename Op::template apply<orig_t>::type type;
};
};
typedef cross_vector<VecOfVecs, adapter > type;
};
} } // boost::mpl
namespace boost { namespace gil {
template <typename Types, typename T> struct type_to_index;
template <typename V> struct view_is_basic;
struct rgb_t;
struct lab_t;
struct hsb_t;
struct cmyk_t;
struct rgba_t;
struct error_t;
namespace detail {
////////////////////////////////////////////////////////
////
//// Generic reduce operation
////
////////////////////////////////////////////////////////
template <typename Op, typename T>
struct reduce {
typedef T type;
};
////////////////////////////////////////////////////////
////
//// Unary reduce_view operation. Splits into basic and non-basic views.
//// Algorithm-specific reduce should specialize for basic views
////
////////////////////////////////////////////////////////
template <typename Op, typename View, bool IsBasic>
struct reduce_view_basic {
typedef View type;
};
template <typename Op, typename Loc>
struct reduce<Op, image_view<Loc> >
: public reduce_view_basic<Op,image_view<Loc>,view_is_basic<image_view<Loc> >::value> {};
////////////////////////////////////////////////////////
////
//// Unary reduce_image operation. Splits into basic and non-basic images.
//// Algorithm-specific reduce should specialize for basic images
////
////////////////////////////////////////////////////////
template <typename Op, typename Img, bool IsBasic>
struct reduce_image_basic {
typedef Img type;
};
template <typename Op, typename V, typename Alloc>
struct reduce<Op, image<V,Alloc> > : public reduce_image_basic<Op,image<V,Alloc>,image_is_basic<image<V,Alloc> >::value > {};
////////////////////////////////////////////////////////
////
//// Binary reduce_view operation. Splits into basic and non-basic views.
//// Algorithm-specific reduce should specialize for basic views
////
////////////////////////////////////////////////////////
template <typename Op, typename V1, typename V2, bool AreBasic>
struct reduce_views_basic {
typedef std::pair<const V1*, const V2*> type;
};
template <typename Op, typename L1, typename L2>
struct reduce<Op, std::pair<const image_view<L1>*, const image_view<L2>*> >
: public reduce_views_basic<Op,image_view<L1>,image_view<L2>,
mpl::and_<view_is_basic<image_view<L1> >, view_is_basic<image_view<L2> > >::value >
{};
////////////////////////////////////////////////////////
////
//// Color space unary reduce operation. Reduce a color space to a base with the same number of channels
////
////////////////////////////////////////////////////////
template <typename Cs>
struct reduce_color_space {
typedef Cs type;
};
template <> struct reduce_color_space<lab_t> { typedef rgb_t type; };
template <> struct reduce_color_space<hsb_t> { typedef rgb_t type; };
template <> struct reduce_color_space<cmyk_t> { typedef rgba_t type; };
/*
////////////////////////////////////////////////////////
////
//// Color space binary reduce operation. Given a source and destination color spaces,
//// returns a reduced source and destination color spaces that have the same mapping of channels
////
//// Precondition: The two color spaces must be compatible (i.e. must have the same set of channels)
////////////////////////////////////////////////////////
template <typename Vec, int Basis, int VecSize>
struct type_vec_to_integer_impl {
typedef typename mpl::back<Vec>::type last;
typedef typename mpl::pop_back<Vec>::type rest;
static const int value = type_vec_to_integer_impl<rest, Basis, VecSize-1>::value * Basis + last::value;
};
template <typename Vec, int Basis>
struct type_vec_to_integer_impl<Vec,Basis,0> {
static const int value=0;
};
template <typename Vec, int Basis=10>
struct type_vec_to_integer {
static const int value = type_vec_to_integer_impl<Vec,Basis, mpl::size<Vec>::value>::value;
};
// Given two color spaces and the mapping of the channels between them, returns the reduced pair of color spaces
// The default version performs no reduction
template <typename SrcColorSpace, typename DstColorSpace, int Mapping>
struct reduce_color_spaces_impl {
typedef SrcColorSpace first_t;
typedef DstColorSpace second_t;
};
// 012: RGB-RGB, bgr-bgr, lab-lab, hsb-hsb
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,12> {
typedef rgb_t first_t;
typedef rgb_t second_t;
};
// 210: RGB-bgr, bgr-RGB
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,210> {
typedef rgb_t first_t;
typedef bgr_t second_t;
};
// 0123: RGBA-RGBA, bgra-bgra, argb-argb, abgr-abgr cmyk-cmyk
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,123> {
typedef rgba_t first_t;
typedef rgba_t second_t;
};
// 3210: RGBA-abgr, bgra-argb, argb-bgra, abgr-RGBA
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3210> {
typedef rgba_t first_t;
typedef abgr_t second_t;
};
// 1230: RGBA-argb, bgra-abgr
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,1230> {
typedef rgba_t first_t;
typedef argb_t second_t;
};
// 2103: RGBA-bgra, bgra-RGBA (uses subclass to ensure that base color space is not reduced to derived)
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,2103> {
typedef rgba_t first_t;
typedef bgra_t second_t;
};
// 3012: argb-RGBA, abgr-bgra
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3012> {
typedef argb_t first_t;
typedef rgba_t second_t;
};
// 0321: argb-abgr, abgr-argb
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,321> {
typedef argb_t first_t;
typedef abgr_t second_t;
};
template <typename SrcColorSpace, typename DstColorSpace>
struct reduce_color_spaces {
typedef typename channel_order<SrcColorSpace>::type src_order_t;
typedef typename channel_order<DstColorSpace>::type dst_order_t;
typedef typename mpl::transform<src_order_t, type_to_index<dst_order_t,mpl::_1> >::type mapping;
static const int mapping_val = type_vec_to_integer<mapping>::value;
typedef typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::first_t _first_t;
typedef typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::second_t _second_t;
typedef typename mpl::and_<color_space_is_base<DstColorSpace>, mpl::not_< color_space_is_base<_second_t> > > swap_t;
public:
typedef typename mpl::if_<swap_t, _second_t, _first_t>::type first_t;
typedef typename mpl::if_<swap_t, _first_t, _second_t>::type second_t;
};
*/
// TODO: Use the old code for reduce_color_spaces above to do color layout reduction
template <typename SrcLayout, typename DstLayout>
struct reduce_color_layouts {
typedef SrcLayout first_t;
typedef DstLayout second_t;
};
////////////////////////////////////////////////////////
////
//// Reduce for copy_pixels
////
////////////////////////////////////////////////////////
struct copy_pixels_fn;
/*
// 1D reduce for copy_pixels reduces the channel to mutable and the color space to its base with same dimensions
template <typename View>
struct reduce_view_basic<copy_pixels_fn,View,true> {
private:
typedef typename reduce_color_space<typename View::color_space_t>::type Cs; // reduce the color space
typedef layout<Cs, typename View::channel_mapping_t> layout_t;
public:
typedef typename derived_view_type<View, use_default, layout_t, use_default, use_default, mpl::true_>::type type;
};
*/
// Incompatible views cannot be used in copy_pixels - will throw std::bad_cast
template <typename V1, typename V2, bool Compatible>
struct reduce_copy_pixop_compat {
typedef error_t type;
};
// For compatible basic views, reduce their color spaces based on their channel mapping.
// Make the source immutable and the destination mutable (they should already be that way)
template <typename V1, typename V2>
struct reduce_copy_pixop_compat<V1,V2,true> {
typedef layout<typename V1::color_space_t, typename V1::channel_mapping_t> layout1;
typedef layout<typename V2::color_space_t, typename V2::channel_mapping_t> layout2;
typedef typename reduce_color_layouts<layout1,layout2>::first_t L1;
typedef typename reduce_color_layouts<layout1,layout2>::second_t L2;
typedef typename derived_view_type<V1, use_default, L1, use_default, use_default, use_default, mpl::false_>::type DV1;
typedef typename derived_view_type<V2, use_default, L2, use_default, use_default, use_default, mpl::true_ >::type DV2;
typedef std::pair<const DV1*, const DV2*> type;
};
// The general 2D version branches into compatible and incompatible views
template <typename V1, typename V2>
struct reduce_views_basic<copy_pixels_fn, V1, V2, true>
: public reduce_copy_pixop_compat<V1, V2, mpl::and_<views_are_compatible<V1,V2>, view_is_mutable<V2> >::value > {
};
////////////////////////////////////////////////////////
////
//// Reduce for variant destructor (basic views have no destructor)
////
////////////////////////////////////////////////////////
struct destructor_op;
template <typename View> struct reduce_view_basic<destructor_op,View,true> { typedef gray8_view_t type; };
////////////////////////////////////////////////////////
////
//// Reduce for get_dimensions (basic views and images have the same structure and the dimensions are contained at the beginning)
////
////////////////////////////////////////////////////////
struct any_type_get_dimensions;
template <typename View> struct reduce_view_basic<any_type_get_dimensions,View,true> { typedef gray8_view_t type; };
template <typename Img> struct reduce_image_basic<any_type_get_dimensions,Img,true> { typedef gray8_image_t type; };
////////////////////////////////////////////////////////
////
//// Reduce for get_num_channels (only color space matters)
////
////////////////////////////////////////////////////////
struct any_type_get_num_channels;
template <typename View> struct reduce_view_basic<any_type_get_num_channels,View,true> {
typedef typename View::color_space_t::base Cs;
typedef typename view_type<bits8,typename reduce_color_space<Cs>::type>::type type;
};
template <typename Img> struct reduce_image_basic<any_type_get_num_channels,Img,true> {
typedef typename Img::color_space_t::base Cs;
typedef typename image_type<bits8,typename reduce_color_space<Cs>::type>::type type;
};
////////////////////////////////////////////////////////
////
//// Reduce for resample_pixels (same as copy_pixels)
////
////////////////////////////////////////////////////////
template <typename Sampler, typename MapFn> struct resample_pixels_fn;
template <typename S, typename M, typename V, bool IsBasic>
struct reduce_view_basic<resample_pixels_fn<S,M>, V, IsBasic> : public reduce_view_basic<copy_pixels_fn, V, IsBasic> {};
template <typename S, typename M, typename V1, typename V2, bool IsBasic>
struct reduce_views_basic<resample_pixels_fn<S,M>, V1, V2, IsBasic> : public reduce_views_basic<copy_pixels_fn, V1, V2, IsBasic> {};
////////////////////////////////////////////////////////
////
//// Reduce for copy_and_convert_pixels
//// (the only reduction could be made when views are compatible and have the same mapping, planarity and stepness)
////
////////////////////////////////////////////////////////
template <typename CC> class copy_and_convert_pixels_fn;
// the only thing for 1D reduce is making them all mutable...
template <typename CC, typename View, bool IsBasic>
struct reduce_view_basic<copy_and_convert_pixels_fn<CC>, View, IsBasic>
: public derived_view_type<View, use_default, use_default, use_default, use_default, mpl::true_> {
};
// For 2D reduce, if they have the same channels and color spaces (i.e. the same pixels) then copy_and_convert is just copy.
// In this case, reduce their common color space. In general make the first immutable and the second mutable
template <typename CC, typename V1, typename V2, bool AreBasic>
struct reduce_views_basic<copy_and_convert_pixels_fn<CC>, V1, V2, AreBasic> {
typedef is_same<typename V1::pixel_t, typename V2::pixel_t> Same;
typedef reduce_color_space<typename V1::color_space_t::base> CsR;
typedef typename mpl::if_<Same, typename CsR::type, typename V1::color_space_t>::type Cs1;
typedef typename mpl::if_<Same, typename CsR::type, typename V2::color_space_t>::type Cs2;
typedef typename derived_view_type<V1, use_default, layout<Cs1, typename V1::channel_mapping_t>, use_default, use_default, mpl::false_>::type DV1;
typedef typename derived_view_type<V2, use_default, layout<Cs2, typename V2::channel_mapping_t>, use_default, use_default, mpl::true_ >::type DV2;
typedef std::pair<const DV1*, const DV2*> type;
};
//integral_image_generator
//resize_clobber_image_fnobj
//image_default_construct_fnobj
//fill_converted_pixels_fn
//bind(gil::detail::copy_pixels_fn(), _1, dst)
//bind(gil::detail::copy_pixels_fn(), src,_1)
//bind(detail::copy_and_convert_pixels_fn(), _1, dst)
//bind(detail::copy_and_convert_pixels_fn(), src, _1)
//gil::detail::fill_pixels_fn<Value>(val)
//detail::copy_construct_in_place_fn<base_t>
//detail::equal_to_fn<typename variant<Types>::base_t>
//detail::any_image_get_view<typename any_image<Types>::view_t>
//detail::any_image_get_const_view<typename any_image<Types>::view_t>
//detail::flipped_up_down_view_fn<any_image_view<ViewTypes> >
//detail::flipped_left_right_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::tranposed_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::rotated90cw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::rotated90ccw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::rotated180_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::subimage_view_fn<any_image_view<ViewTypes> >
//detail::subsampled_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
//detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes> >
//detail::color_converted_view_fn<DstP,typename color_convert_view_type<any_image_view<ViewTypes>, DstP>::type >
}
} } // namespace boost::gil
#endif // GIL_REDUCE_CODE_BLOAT
#endif

View File

@@ -0,0 +1,197 @@
/*
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 GIL_DYNAMICIMAGE_VARIANT_HPP
#define GIL_DYNAMICIMAGE_VARIANT_HPP
////////////////////////////////////////////////////////////////////////////////////////
/// \file
/// \brief Support for run-time instantiated types
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on September 18, 2007
///
////////////////////////////////////////////////////////////////////////////////////////
#include "../../gil_config.hpp"
#include "../../utilities.hpp"
#include <cstddef>
#include <cassert>
#include <algorithm>
#include <typeinfo>
#include <boost/bind.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/sizeof.hpp>
#include <boost/mpl/max.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/fold.hpp>
namespace boost { namespace gil {
namespace detail {
template <typename Types, typename T> struct type_to_index;
template <typename Op, typename T> struct reduce;
struct destructor_op {
typedef void result_type;
template <typename T> result_type operator()(const T& t) const { t.~T(); }
};
template <typename T, typename Bits> void copy_construct_in_place(const T& t, Bits& bits);
template <typename Bits> struct copy_construct_in_place_fn;
}
/**
\brief Represents a concrete instance of a run-time specified type from a set of types
\class variant
\ingroup Variant
A concept is typically modeled by a collection of different types. They may be instantiations
of a templated type with different template parameters or even completely unrelated types.
We call the type with which the concept is instantiated in a given place in the code "the concrete type".
The concrete type must be chosen at compile time, which sometimes is a severe limitation.
Consider, for example, having an image concept modeled by an image class templated over the color space.
It would be difficult to write a function that reads an image from file preserving its native color space, since the
type of the return value is only available at run time. It would be difficult to store images of different color
spaces in the same container or apply operations on them uniformly.
The variant class addresses this deficiency. It allows for run-time instantiation of a class from a given set of allowed classes
specified at compile time. For example, the set of allowed classes may include 8-bit and 16-bit RGB and CMYK images. Such a variant
can be constructed with rgb8_image_t and then assigned a cmyk16_image_t.
The variant has a templated constructor, which allows us to construct it with any concrete type instantiation. It can also perform a generic
operation on the concrete type via a call to apply_operation. The operation must be provided as a function object whose application
operator has a single parameter which can be instantiated with any of the allowed types of the variant.
variant breaks down the instantiated type into a non-templated underlying base type and a unique instantiation
type identifier. In the most common implementation the concrete instantiation in stored 'in-place' - in 'bits_t'.
bits_t contains sufficient space to fit the largest of the instantiated objects.
GIL's variant is similar to boost::variant in spirit (hence we borrow the name from there) but it differs in several ways from the current boost
implementation. Most notably, it does not take a variable number of template parameters but a single parameter defining the type enumeration. As
such it can be used more effectively in generic code.
The Types parameter specifies the set of allowable types. It models MPL Random Access Container
*/
template <typename Types> // models MPL Random Access Container
class variant {
// size in bytes of the largest type in Types
static const std::size_t MAX_SIZE = mpl::fold<Types, mpl::size_t<0>, mpl::max<mpl::_1, mpl::sizeof_<mpl::_2> > >::type::value;
static const std::size_t NUM_TYPES = mpl::size<Types>::value;
public:
typedef Types types_t;
typedef struct { char data[MAX_SIZE]; } base_t; // empty space equal to the size of the largest type in Types
// Default constructor - default construct the first type
variant() : _index(0) { new(&_bits) typename mpl::at_c<Types,0>::type(); }
virtual ~variant() { apply_operation(*this, detail::destructor_op()); }
// Throws std::bad_cast if T is not in Types
template <typename T> explicit variant(const T& obj){ _index=type_id<T>(); if (_index==NUM_TYPES) throw std::bad_cast(); detail::copy_construct_in_place(obj, _bits); }
// When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call
template <typename T> explicit variant(T& obj, bool do_swap);
template <typename T> variant& operator=(const T& obj) { variant tmp(obj); swap(*this,tmp); return *this; }
variant& operator=(const variant& v) { variant tmp(v ); swap(*this,tmp); return *this; }
variant(const variant& v) : _index(v._index) { apply_operation(v, detail::copy_construct_in_place_fn<base_t>(_bits)); }
template <typename T> void move_in(T& obj) { variant tmp(obj, true); swap(*this,tmp); }
template <typename TS> friend bool operator==(const variant<TS>& x, const variant<TS>& y);
template <typename TS> friend bool operator!=(const variant<TS>& x, const variant<TS>& y);
template <typename T> static bool has_type() { return type_id<T>()!=NUM_TYPES; }
template <typename T> const T& _dynamic_cast() const { if (!current_type_is<T>()) throw std::bad_cast(); return *gil_reinterpret_cast_c<const T*>(&_bits); }
template <typename T> T& _dynamic_cast() { if (!current_type_is<T>()) throw std::bad_cast(); return *gil_reinterpret_cast < T*>(&_bits); }
template <typename T> bool current_type_is() const { return type_id<T>()==_index; }
base_t bits() const { return _bits; }
std::size_t index() const { return _index; }
private:
template <typename T> static std::size_t type_id() { return detail::type_to_index<Types,T>::value; }
template <typename Cs> friend void swap(variant<Cs>& x, variant<Cs>& y);
template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(variant<Types2>& var, UnaryOp op);
template <typename Types2, typename UnaryOp> friend typename UnaryOp::result_type apply_operation(const variant<Types2>& var, UnaryOp op);
template <typename Types1, typename Types2, typename BinaryOp> friend typename BinaryOp::result_type apply_operation(const variant<Types1>& arg1, const variant<Types2>& arg2, BinaryOp op);
base_t _bits;
std::size_t _index;
};
namespace detail {
template <typename T, typename Bits>
void copy_construct_in_place(const T& t, Bits& bits) {
T& b=*gil_reinterpret_cast<T*>(&bits);
new(&b)T(t); // default-construct
}
template <typename Bits>
struct copy_construct_in_place_fn {
typedef void result_type;
Bits& _dst;
copy_construct_in_place_fn(Bits& dst) : _dst(dst) {}
template <typename T> void operator()(const T& src) const { copy_construct_in_place(src,_dst); }
};
template <typename Bits>
struct equal_to_fn {
const Bits& _dst;
equal_to_fn(const Bits& dst) : _dst(dst) {}
typedef bool result_type;
template <typename T> result_type operator()(const T& x) const {
return x==*gil_reinterpret_cast_c<const T*>(&_dst);
}
};
}
// When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call
template <typename Types>
template <typename T> variant<Types>::variant(T& obj, bool do_swap) {
_index=type_id<T>();
if (_index==NUM_TYPES) throw std::bad_cast();
if (do_swap) {
new(&_bits) T(); // default construct
swap(obj, *gil_reinterpret_cast<T*>(&_bits));
} else
detail::copy_construct_in_place(const_cast<const T&>(obj), _bits);
}
template <typename Types>
void swap(variant<Types>& x, variant<Types>& y) {
std::swap(x._bits,y._bits);
std::swap(x._index, y._index);
}
template <typename Types>
inline bool operator==(const variant<Types>& x, const variant<Types>& y) {
return x._index==y._index && apply_operation(x,detail::equal_to_fn<typename variant<Types>::base_t>(y._bits));
}
template <typename C>
inline bool operator!=(const variant<C>& x, const variant<C>& y) {
return !(x==y);
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,80 @@
/*
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 GIL_DYNAMIC_IO_H
#define GIL_DYNAMIC_IO_H
/// \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 "../../gil_config.hpp"
#include "io_error.hpp"
#include "../dynamic_image/any_image.hpp"
namespace boost { namespace gil {
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>
void apply(const View& view,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());}
};
} // 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

View File

@@ -0,0 +1,51 @@
/*
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 GIL_IO_ERROR_H
#define GIL_IO_ERROR_H
/// \file
/// \brief Handle input-output errors
/// \author Lubomir Bourdev and Hailin Jin \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated on May 30, 2006
#include <ios>
#include "../../gil_config.hpp"
#include <boost/shared_ptr.hpp>
namespace boost { namespace gil {
inline void io_error(const char* descr) { throw std::ios_base::failure(descr); }
inline void io_error_if(bool expr, const char* descr="") { if (expr) io_error(descr); }
namespace detail {
class file_mgr {
protected:
shared_ptr<FILE> _fp;
struct null_deleter { void operator()(void const*) const {} };
file_mgr(FILE* file) : _fp(file, null_deleter()) {}
file_mgr(const char* filename, const char* flags) {
FILE* fp;
io_error_if((fp=fopen(filename,flags))==NULL, "file_mgr: failed to open file");
_fp=shared_ptr<FILE>(fp,fclose);
}
public:
FILE* get() { return _fp.get(); }
};
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,130 @@
/*
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 GIL_JPEG_DYNAMIC_IO_H
#define GIL_JPEG_DYNAMIC_IO_H
/// \file
/// \brief Support for reading and writing JPEG files
/// Requires libjpeg
///
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated June 10, 2006
#include <stdio.h>
#include <string>
#include <boost/mpl/bool.hpp>
#include <boost/shared_ptr.hpp>
#include "../dynamic_image/dynamic_image_all.hpp"
#include "io_error.hpp"
#include "jpeg_io.hpp"
#include "jpeg_io_private.hpp"
#include "dynamic_io.hpp"
namespace boost { namespace gil {
namespace detail {
struct jpeg_write_is_supported {
template<typename View> struct apply
: public mpl::bool_<jpeg_write_support<View>::is_supported> {};
};
class jpeg_writer_dynamic : public jpeg_writer {
int _quality;
public:
jpeg_writer_dynamic(FILE* file, int quality=100) : jpeg_writer(file) , _quality(quality) {}
jpeg_writer_dynamic(const char* filename, int quality=100) : jpeg_writer(filename), _quality(quality) {}
template <typename Views>
void write_view(const any_image_view<Views>& runtime_view) {
dynamic_io_fnobj<jpeg_write_is_supported, jpeg_writer> op(this);
apply_operation(runtime_view,op);
}
};
class jpeg_type_format_checker {
J_COLOR_SPACE _color_type;
public:
jpeg_type_format_checker(J_COLOR_SPACE color_type_in) :
_color_type(color_type_in) {}
template <typename Image>
bool apply() {
return jpeg_read_support<typename Image::view_t>::color_type==_color_type;
}
};
struct jpeg_read_is_supported {
template<typename View> struct apply
: public mpl::bool_<jpeg_read_support<View>::is_supported> {};
};
class jpeg_reader_dynamic : public jpeg_reader {
public:
jpeg_reader_dynamic(FILE* file) : jpeg_reader(file) {}
jpeg_reader_dynamic(const char* filename) : jpeg_reader(filename){}
template <typename Images>
void read_image(any_image<Images>& im) {
if (!construct_matched(im,detail::jpeg_type_format_checker(_cinfo.out_color_space))) {
io_error("jpeg_reader_dynamic::read_image(): no matching image type between those of the given any_image and that of the file");
} else {
im.recreate(get_dimensions());
dynamic_io_fnobj<jpeg_read_is_supported, jpeg_reader> op(this);
apply_operation(view(im),op);
}
}
};
} // namespace detail
/// \ingroup JPEG_IO
/// \brief reads a JPEG image into a run-time instantiated image
/// Opens the given JPEG file name, selects the first type in Images whose color space and channel are compatible to those of the image file
/// and creates a new image of that type with the dimensions specified by the image file.
/// Throws std::ios_base::failure if none of the types in Images are compatible with the type on disk.
template <typename Images>
inline void jpeg_read_image(const char* filename,any_image<Images>& im) {
detail::jpeg_reader_dynamic m(filename);
m.read_image(im);
}
/// \ingroup JPEG_IO
/// \brief reads a JPEG image into a run-time instantiated image
template <typename Images>
inline void jpeg_read_image(const std::string& filename,any_image<Images>& im) {
jpeg_read_image(filename.c_str(),im);
}
/// \ingroup JPEG_IO
/// \brief Saves the currently instantiated view to a jpeg file specified by the given jpeg image file name.
/// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension
/// or if it fails to create the file.
template <typename Views>
inline void jpeg_write_view(const char* filename,const any_image_view<Views>& runtime_view) {
detail::jpeg_writer_dynamic m(filename);
m.write_view(runtime_view);
}
/// \ingroup JPEG_IO
/// \brief Saves the currently instantiated view to a jpeg file specified by the given jpeg image file name.
template <typename Views>
inline void jpeg_write_view(const std::string& filename,const any_image_view<Views>& runtime_view) {
jpeg_write_view(filename.c_str(),runtime_view);
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,202 @@
/*
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 GIL_JPEG_IO_H
#define GIL_JPEG_IO_H
/// \file
/// \brief Support for reading and writing JPEG files
/// Requires libjpeg
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated September 24, 2006
#include <cstdio>
#include <algorithm>
#include <string>
#include <boost/static_assert.hpp>
#include <boost/shared_ptr.hpp>
extern "C" {
#include <jpeglib.h>
}
#include "io_error.hpp"
#include "jpeg_io_private.hpp"
namespace boost { namespace gil {
/// \ingroup JPEG_IO
/// \brief Determines whether the given view type is supported for reading
template <typename View>
struct jpeg_read_support {
BOOST_STATIC_CONSTANT(bool,is_supported=
(detail::jpeg_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::is_supported));
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=
(detail::jpeg_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type));
BOOST_STATIC_CONSTANT(bool, value=is_supported);
};
/// \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
inline point2<std::ptrdiff_t> jpeg_read_dimensions(const char* filename) {
detail::jpeg_reader m(filename);
return m.get_dimensions();
}
/// \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
inline point2<std::ptrdiff_t> jpeg_read_dimensions(const std::string& filename) {
return jpeg_read_dimensions(filename.c_str());
}
/// \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 View>
inline void jpeg_read_view(const char* filename,const View& view) {
BOOST_STATIC_ASSERT(jpeg_read_support<View>::is_supported);
detail::jpeg_reader m(filename);
m.apply(view);
}
/// \ingroup JPEG_IO
/// \brief Loads the image specified by the given jpeg image file name into the given view.
template <typename View>
inline void jpeg_read_view(const std::string& filename,const View& view) {
jpeg_read_view(filename.c_str(),view);
}
/// \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 Image>
inline void jpeg_read_image(const char* filename,Image& im) {
BOOST_STATIC_ASSERT(jpeg_read_support<typename Image::view_t>::is_supported);
detail::jpeg_reader m(filename);
m.read_image(im);
}
/// \ingroup JPEG_IO
/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it.
template <typename Image>
inline void jpeg_read_image(const std::string& filename,Image& im) {
jpeg_read_image(filename.c_str(),im);
}
/// \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 View,typename CC>
inline void jpeg_read_and_convert_view(const char* filename,const View& view,CC cc) {
detail::jpeg_reader_color_convert<CC> m(filename,cc);
m.apply(view);
}
/// \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 View>
inline void jpeg_read_and_convert_view(const char* filename,const View& view) {
detail::jpeg_reader_color_convert<default_color_converter> m(filename,default_color_converter());
m.apply(view);
}
/// \ingroup JPEG_IO
/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view.
template <typename View,typename CC>
inline void jpeg_read_and_convert_view(const std::string& filename,const View& view,CC cc) {
jpeg_read_and_convert_view(filename.c_str(),view);
}
/// \ingroup JPEG_IO
/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view.
template <typename View>
inline void jpeg_read_and_convert_view(const std::string& filename,const View& view) {
jpeg_read_and_convert_view(filename.c_str(),view);
}
/// \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 Image,typename CC>
inline void jpeg_read_and_convert_image(const char* filename,Image& im,CC cc) {
detail::jpeg_reader_color_convert<CC> m(filename,cc);
m.read_image(im);
}
/// \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 Image>
inline void jpeg_read_and_convert_image(const char* filename,Image& im) {
detail::jpeg_reader_color_convert<default_color_converter> m(filename,default_color_converter());
m.read_image(im);
}
/// \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.
template <typename Image,typename CC>
inline void jpeg_read_and_convert_image(const std::string& filename,Image& im,CC cc) {
jpeg_read_and_convert_image(filename.c_str(),im);
}
/// \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.
template <typename Image>
inline void jpeg_read_and_convert_image(const std::string& filename,Image& im) {
jpeg_read_and_convert_image(filename.c_str(),im);
}
/// \ingroup JPEG_IO
/// \brief Determines whether the given view type is supported for writing
template <typename View>
struct jpeg_write_support {
BOOST_STATIC_CONSTANT(bool,is_supported=
(detail::jpeg_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::is_supported));
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=
(detail::jpeg_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type));
BOOST_STATIC_CONSTANT(bool, value=is_supported);
};
/// \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 View>
inline void jpeg_write_view(const char* filename,const View& view,int quality=100) {
BOOST_STATIC_ASSERT(jpeg_write_support<View>::is_supported);
detail::jpeg_writer m(filename);
m.apply(view,quality);
}
/// \ingroup JPEG_IO
/// \brief Saves the view to a jpeg file specified by the given jpeg image file name.
template <typename View>
inline void jpeg_write_view(const std::string& filename,const View& view,int quality=100) {
jpeg_write_view(filename.c_str(),view,quality);
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,226 @@
/*
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 GIL_JPEG_IO_PRIVATE_H
#define GIL_JPEG_IO_PRIVATE_H
/// \file
/// \brief Internal support for reading and writing JPEG files
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated September 24, 2006
#include <stdio.h>
#include <boost/static_assert.hpp>
#include <vector>
#include "../../gil_all.hpp"
#include "io_error.hpp"
#include <jpeglib.h>
namespace boost { namespace gil {
namespace detail {
// lbourdev: What is the advantage of having channel and colorspace together? Are there cases where they are interrelated?
template <typename Channel,typename ColorSpace>
struct jpeg_read_support_private {
BOOST_STATIC_CONSTANT(bool,is_supported=false);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN);
};
template <>
struct jpeg_read_support_private<bits8,gray_t> {
BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE);
};
template <>
struct jpeg_read_support_private<bits8,rgb_t> {
BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB);
};
template <>
struct jpeg_read_support_private<bits8,cmyk_t> {
BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK);
};
template <typename Channel,typename ColorSpace>
struct jpeg_write_support_private {
BOOST_STATIC_CONSTANT(bool,is_supported=false);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_UNKNOWN);
};
template <>
struct jpeg_write_support_private<bits8,gray_t> {
BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_GRAYSCALE);
};
template <>
struct jpeg_write_support_private<bits8,rgb_t> {
BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_RGB);
};
template <>
struct jpeg_write_support_private<bits8,cmyk_t> {
BOOST_STATIC_ASSERT(BITS_IN_JSAMPLE==8);
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(J_COLOR_SPACE,color_type=JCS_CMYK);
};
class jpeg_reader : public file_mgr {
protected:
jpeg_decompress_struct _cinfo;
jpeg_error_mgr _jerr;
void init() {
_cinfo.err=jpeg_std_error(&_jerr);
jpeg_create_decompress(&_cinfo);
jpeg_stdio_src(&_cinfo,_fp.get());
jpeg_read_header(&_cinfo,TRUE);
}
public:
jpeg_reader(FILE* file) : file_mgr(file) { init(); }
jpeg_reader(const char* filename) : file_mgr(filename, "rb") { init(); }
~jpeg_reader() { jpeg_destroy_decompress(&_cinfo); }
template <typename View>
void apply(const View& view) {
jpeg_start_decompress(&_cinfo); // lbourdev: Can this return an error? You need to check and throw. Check all other library methods that can return an error state...
io_error_if(_cinfo.data_precision!=8,"jpeg_reader::apply(): this image file is not supported");
io_error_if(_cinfo.out_color_space!=jpeg_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type,
"jpeg_reader::apply(): input view type does not match the image file");
io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader::apply(): input view dimensions do not match the image file");
std::vector<pixel<bits8,layout<typename color_space_type<View>::type> > > row(view.width());
JSAMPLE* row_address=(JSAMPLE*)&row.front();
for(int y=0;y<view.height();++y) {
io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
"jpeg_reader::apply(): fail to read JPEG file");
std::copy(row.begin(),row.end(),view.row_begin(y));
}
jpeg_finish_decompress(&_cinfo);
}
template <typename Image>
void read_image(Image& im) {
im.recreate(get_dimensions());
apply(view(im));
}
point2<std::ptrdiff_t> get_dimensions() const {
return point2<std::ptrdiff_t>(_cinfo.image_width,_cinfo.image_height);
}
};
// This code will be simplified...
template <typename CC>
class jpeg_reader_color_convert : public jpeg_reader {
private:
CC _cc;
public:
jpeg_reader_color_convert(FILE* file,CC cc_in) : jpeg_reader(file),_cc(cc_in) {}
jpeg_reader_color_convert(FILE* file) : jpeg_reader(file) {}
jpeg_reader_color_convert(const char* filename,CC cc_in) : jpeg_reader(filename),_cc(cc_in) {}
jpeg_reader_color_convert(const char* filename) : jpeg_reader(filename) {}
template <typename View>
void apply(const View& view) {
jpeg_start_decompress(&_cinfo); // lbourdev: Can this return an error? You need to check and throw. Check all other library methods that can return an error state...
io_error_if(_cinfo.data_precision!=8,"jpeg_reader_color_covert::apply(): this image file is not supported");
io_error_if(view.dimensions() != get_dimensions(), "jpeg_reader_color_covert::apply(): input view dimensions don't match the image file");
switch (_cinfo.out_color_space) {
case JCS_GRAYSCALE: {
std::vector<gray8_pixel_t> row(view.width());
JSAMPLE* row_address=(JSAMPLE*)&row.front();
for(int y=0;y<view.height();++y) {
io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
"jpeg_reader_color_covert::apply(): fail to read JPEG file");
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<gray8_ref_t, typename View::value_type,CC>(_cc));
}
break;
}
case JCS_RGB: {
std::vector<rgb8_pixel_t> row(view.width());
JSAMPLE* row_address=(JSAMPLE*)&row.front();
for(int y=0;y<view.height();++y) {
io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
"jpeg_reader_color_covert::apply(): fail to read JPEG file");
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgb8_ref_t, typename View::value_type,CC>(_cc));
}
break;
}
case JCS_CMYK: {
std::vector<cmyk8_pixel_t> row(view.width());
JSAMPLE* row_address=(JSAMPLE*)&row.front();
for(int y=0;y<view.height();++y) {
io_error_if(jpeg_read_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1)!=1,
"jpeg_reader_color_covert::apply(): fail to read JPEG file");
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<cmyk8_ref_t, typename View::value_type,CC>(_cc));
}
break;
}
default:
io_error("jpeg_reader_color_covert::apply(): unknown color type");
}
jpeg_finish_decompress(&_cinfo);
}
template <typename Image>
void read_image(Image& im) {
im.recreate(get_dimensions());
apply(view(im));
}
};
class jpeg_writer : public file_mgr {
jpeg_compress_struct _cinfo;
jpeg_error_mgr _jerr;
void init() {
_cinfo.err=jpeg_std_error(&_jerr);
jpeg_create_compress(&_cinfo);
jpeg_stdio_dest(&_cinfo,_fp.get());
}
public:
jpeg_writer(FILE* file) : file_mgr(file) { init(); }
jpeg_writer(const char* filename) : file_mgr(filename, "wb") { init(); }
~jpeg_writer() { jpeg_destroy_compress(&_cinfo); }
template <typename View>
void apply(const View& view,int quality=100) {
_cinfo.image_width = (JDIMENSION)view.width();
_cinfo.image_height = (JDIMENSION)view.height();
_cinfo.input_components=num_channels<View>::value;
_cinfo.in_color_space = jpeg_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type;
jpeg_set_defaults(&_cinfo);
jpeg_set_quality(&_cinfo, quality, TRUE);
jpeg_start_compress(&_cinfo, TRUE);
std::vector<pixel<bits8,layout<typename color_space_type<View>::type> > > row(view.width());
JSAMPLE* row_address=(JSAMPLE*)&row.front();
for (int y=0;y<view.height(); ++y) {
std::copy(view.row_begin(y),view.row_end(y),row.begin());
io_error_if(jpeg_write_scanlines(&_cinfo,(JSAMPARRAY)&row_address,1) != 1,
"jpeg_writer::apply(): fail to write file");
}
jpeg_finish_compress(&_cinfo);
}
};
} // namespace detail
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,141 @@
/*
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 GIL_PNG_DYNAMIC_IO_H
#define GIL_PNG_DYNAMIC_IO_H
/// \file
/// \brief Support for reading and writing PNG files
/// Requires libpng and zlib!
///
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated June 10, 2006
//
// We are currently providing the following functions:
// template <typename Images> void png_read_image(const char*,any_image<Images>&)
// template <typename Images> void png_read_image(FILE*,any_image<Images>&,std::size_t)
// template <typename Views> void png_write_view(const char*,const any_image_view<View>&)
// template <typename Views> void png_write_view(FILE*,const any_image_view<View>&)
#include <string>
#include <stdio.h>
#include <boost/mpl/bool.hpp>
#include <boost/shared_ptr.hpp>
#include "../dynamic_image/dynamic_image_all.hpp"
#include "io_error.hpp"
#include "png_io.hpp"
#include "png_io_private.hpp"
#include "dynamic_io.hpp"
namespace boost { namespace gil {
namespace detail {
struct png_write_is_supported {
template<typename View> struct apply
: public mpl::bool_<png_write_support<View>::is_supported> {};
};
class png_writer_dynamic : public png_writer {
public:
png_writer_dynamic(FILE* file ) : png_writer(file) {}
png_writer_dynamic(const char* filename) : png_writer(filename){}
template <typename Views>
void write_view(const any_image_view<Views>& runtime_view) {
dynamic_io_fnobj<png_write_is_supported, png_writer> op(this);
apply_operation(runtime_view,op);
}
};
class png_type_format_checker {
int _bit_depth;
int _color_type;
public:
png_type_format_checker(int bit_depth_in,int color_type_in) :
_bit_depth(bit_depth_in),_color_type(color_type_in) {}
template <typename Image>
bool apply() {
return png_read_support<typename Image::view_t>::bit_depth==_bit_depth &&
png_read_support<typename Image::view_t>::color_type==_color_type;
}
};
struct png_read_is_supported {
template<typename View> struct apply
: public mpl::bool_<png_read_support<View>::is_supported> {};
};
class png_reader_dynamic : public png_reader {
public:
png_reader_dynamic(FILE* file) : png_reader(file) {}
png_reader_dynamic(const char* filename) : png_reader(filename){}
template <typename Images>
void read_image(any_image<Images>& im) {
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
png_get_IHDR(_png_ptr, _info_ptr,
&width, &height,&bit_depth,&color_type,&interlace_type,
NULL, NULL);
if (!construct_matched(im,png_type_format_checker(bit_depth,color_type))) {
io_error("png_reader_dynamic::read_image(): no matching image type between those of the given any_image and that of the file");
} else {
im.recreate(width,height);
dynamic_io_fnobj<png_read_is_supported, png_reader> op(this);
apply_operation(view(im),op);
}
}
};
} // namespace detail
/// \ingroup PNG_IO
/// \brief reads a PNG image into a run-time instantiated image
/// Opens the given png file name, selects the first type in Images whose color space and channel are compatible to those of the image file
/// and creates a new image of that type with the dimensions specified by the image file.
/// Throws std::ios_base::failure if none of the types in Images are compatible with the type on disk.
template <typename Images>
inline void png_read_image(const char* filename,any_image<Images>& im) {
detail::png_reader_dynamic m(filename);
m.read_image(im);
}
/// \ingroup PNG_IO
/// \brief reads a PNG image into a run-time instantiated image
template <typename Images>
inline void png_read_image(const std::string& filename,any_image<Images>& im) {
png_read_image(filename.c_str(),im);
}
/// \ingroup PNG_IO
/// \brief Saves the currently instantiated view to a png file specified by the given png image file name.
/// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension
/// or if it fails to create the file.
template <typename Views>
inline void png_write_view(const char* filename,const any_image_view<Views>& runtime_view) {
detail::png_writer_dynamic m(filename);
m.write_view(runtime_view);
}
/// \ingroup PNG_IO
/// \brief Saves the currently instantiated view to a png file specified by the given png image file name.
template <typename Views>
inline void png_write_view(const std::string& filename,const any_image_view<Views>& runtime_view) {
png_write_view(filename.c_str(),runtime_view);
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,214 @@
/*
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 GIL_PNG_IO_H
#define GIL_PNG_IO_H
/// \file
/// \brief Support for reading and writing PNG files
/// Requires libpng and zlib!
//
// We are currently providing the following functions:
// point2<std::ptrdiff_t> png_read_dimensions(const char*)
// template <typename View> void png_read_view(const char*,const View&)
// template <typename View> void png_read_image(const char*,image<View>&)
// template <typename View> void png_write_view(const char*,const View&)
// template <typename View> struct png_read_support;
// template <typename View> struct png_write_support;
//
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated September 24, 2006
#include <stdio.h>
#include <string>
extern "C" {
#include "png.h"
}
#include <boost/static_assert.hpp>
#include "../../gil_config.hpp"
#include "../../utilities.hpp"
#include "io_error.hpp"
#include "png_io_private.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
inline point2<std::ptrdiff_t> png_read_dimensions(const char *filename) {
detail::png_reader m(filename);
return m.get_dimensions();
}
/// \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
inline point2<std::ptrdiff_t> png_read_dimensions(const std::string& filename) {
return png_read_dimensions(filename.c_str());
}
/// \ingroup PNG_IO
/// \brief Determines whether the given view type is supported for reading
template <typename View>
struct png_read_support {
BOOST_STATIC_CONSTANT(bool,is_supported=
(detail::png_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::is_supported));
BOOST_STATIC_CONSTANT(int,bit_depth=
(detail::png_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth));
BOOST_STATIC_CONSTANT(int,color_type=
(detail::png_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type));
BOOST_STATIC_CONSTANT(bool, value=is_supported);
};
/// \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 View>
inline void png_read_view(const char* filename,const View& view) {
BOOST_STATIC_ASSERT(png_read_support<View>::is_supported);
detail::png_reader m(filename);
m.apply(view);
}
/// \ingroup PNG_IO
/// \brief Loads the image specified by the given png image file name into the given view.
template <typename View>
inline void png_read_view(const std::string& filename,const View& view) {
png_read_view(filename.c_str(),view);
}
/// \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 Image>
inline void png_read_image(const char* filename,Image& im) {
BOOST_STATIC_ASSERT(png_read_support<typename Image::view_t>::is_supported);
detail::png_reader m(filename);
m.read_image(im);
}
/// \ingroup PNG_IO
/// \brief Allocates a new image whose dimensions are determined by the given png image file, and loads the pixels into it.
template <typename Image>
inline void png_read_image(const std::string& filename,Image& im) {
png_read_image(filename.c_str(),im);
}
/// \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 View,typename CC>
inline void png_read_and_convert_view(const char* filename,const View& view,CC cc) {
detail::png_reader_color_convert<CC> m(filename,cc);
m.apply(view);
}
/// \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 View>
inline void png_read_and_convert_view(const char* filename,const View& view) {
detail::png_reader_color_convert<default_color_converter> m(filename,default_color_converter());
m.apply(view);
}
/// \ingroup PNG_IO
/// \brief Loads the image specified by the given png image file name and color-converts it into the given view.
template <typename View,typename CC>
inline void png_read_and_convert_view(const std::string& filename,const View& view,CC cc) {
png_read_and_convert_view(filename.c_str(),view,cc);
}
/// \ingroup PNG_IO
/// \brief Loads the image specified by the given png image file name and color-converts it into the given view.
template <typename View>
inline void png_read_and_convert_view(const std::string& filename,const View& view) {
png_read_and_convert_view(filename.c_str(),view);
}
/// \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 Image,typename CC>
inline void png_read_and_convert_image(const char* filename,Image& im,CC cc) {
detail::png_reader_color_convert<CC> m(filename,cc);
m.read_image(im);
}
/// \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 Image>
inline void png_read_and_convert_image(const char* filename,Image& im) {
detail::png_reader_color_convert<default_color_converter> m(filename,default_color_converter());
m.read_image(im);
}
/// \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.
template <typename Image,typename CC>
inline void png_read_and_convert_image(const std::string& filename,Image& im,CC cc) {
png_read_and_convert_image(filename.c_str(),im,cc);
}
/// \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.
template <typename Image>
inline void png_read_and_convert_image(const std::string& filename,Image& im) {
png_read_and_convert_image(filename.c_str(),im);
}
/// \ingroup PNG_IO
/// \brief Determines whether the given view type is supported for writing
template <typename View>
struct png_write_support {
BOOST_STATIC_CONSTANT(bool,is_supported=
(detail::png_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::is_supported));
BOOST_STATIC_CONSTANT(int,bit_depth=
(detail::png_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth));
BOOST_STATIC_CONSTANT(int,color_type=
(detail::png_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type));
BOOST_STATIC_CONSTANT(bool, value=is_supported);
};
/// \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 View>
inline void png_write_view(const char* filename,const View& view) {
BOOST_STATIC_ASSERT(png_write_support<View>::is_supported);
detail::png_writer m(filename);
m.apply(view);
}
/// \ingroup PNG_IO
/// \brief Saves the view to a png file specified by the given png image file name.
template <typename View>
inline void png_write_view(const std::string& filename,const View& view) {
png_write_view(filename.c_str(),view);
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,360 @@
/*
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://stlab.adobe.com/gil for most recent version including documentation.
*/
/*************************************************************************************************/
#ifndef GIL_PNG_IO_PRIVATE_H
#define GIL_PNG_IO_PRIVATE_H
/// \file
/// \brief Internal support for reading and writing PNG files
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated August 14, 2007
#include <algorithm>
#include <vector>
#include <boost/static_assert.hpp>
#include "../../gil_all.hpp"
#include "io_error.hpp"
#include <png.h>
namespace boost { namespace gil {
namespace detail {
static const std::size_t PNG_BYTES_TO_CHECK = 4;
// lbourdev: These can be greatly simplified, for example:
template <typename Cs> struct png_color_type {BOOST_STATIC_CONSTANT(int,color_type=0);};
template<> struct png_color_type<gray_t> { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY); };
template<> struct png_color_type<rgb_t> { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB); };
template<> struct png_color_type<rgba_t> { BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA); };
template <typename Channel,typename ColorSpace> struct png_is_supported {BOOST_STATIC_CONSTANT(bool,value=false);};
template <> struct png_is_supported<bits8,gray_t> {BOOST_STATIC_CONSTANT(bool,value=true);};
template <> struct png_is_supported<bits8,rgb_t> {BOOST_STATIC_CONSTANT(bool,value=true);};
template <> struct png_is_supported<bits8,rgba_t> {BOOST_STATIC_CONSTANT(bool,value=true);};
template <> struct png_is_supported<bits16,gray_t> {BOOST_STATIC_CONSTANT(bool,value=true);};
template <> struct png_is_supported<bits16,rgb_t> {BOOST_STATIC_CONSTANT(bool,value=true);};
template <> struct png_is_supported<bits16,rgba_t> {BOOST_STATIC_CONSTANT(bool,value=true);};
template <typename Channel> struct png_bit_depth {BOOST_STATIC_CONSTANT(int,bit_depth=sizeof(Channel)*8);};
template <typename Channel,typename ColorSpace>
struct png_read_support_private {
BOOST_STATIC_CONSTANT(bool,is_supported=false);
BOOST_STATIC_CONSTANT(int,bit_depth=0);
BOOST_STATIC_CONSTANT(int,color_type=0);
};
template <>
struct png_read_support_private<bits8,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY);
};
template <>
struct png_read_support_private<bits8,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB);
};
template <>
struct png_read_support_private<bits8,rgba_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA);
};
template <>
struct png_read_support_private<bits16,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY);
};
template <>
struct png_read_support_private<bits16,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB);
};
template <>
struct png_read_support_private<bits16,rgba_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA);
};
template <typename Channel,typename ColorSpace>
struct png_write_support_private {
BOOST_STATIC_CONSTANT(bool,is_supported=false);
BOOST_STATIC_CONSTANT(int,bit_depth=0);
BOOST_STATIC_CONSTANT(int,color_type=0);
};
template <>
struct png_write_support_private<bits8,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY);
};
template <>
struct png_write_support_private<bits8,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB);
};
template <>
struct png_write_support_private<bits8,rgba_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA);
};
template <>
struct png_write_support_private<bits16,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_GRAY);
};
template <>
struct png_write_support_private<bits16,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGB);
};
template <>
struct png_write_support_private<bits16,rgba_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PNG_COLOR_TYPE_RGBA);
};
class png_reader : public file_mgr {
protected:
png_structp _png_ptr;
png_infop _info_ptr;
void init() {
char buf[PNG_BYTES_TO_CHECK];
// read in some of the signature bytes
io_error_if(fread(buf, 1, PNG_BYTES_TO_CHECK, get()) != detail::PNG_BYTES_TO_CHECK,
"png_check_validity: fail to read file");
// compare the first PNG_BYTES_TO_CHECK bytes of the signature.
io_error_if(png_sig_cmp((png_bytep)buf, (png_size_t)0, detail::PNG_BYTES_TO_CHECK)!=0,
"png_check_validity: invalid png file");
_png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
io_error_if(_png_ptr==NULL,"png_get_file_size: fail to call png_create_write_struct()");
// allocate/initialize the image information data
_info_ptr = png_create_info_struct(_png_ptr);
if (_info_ptr == NULL) {
png_destroy_read_struct(&_png_ptr,NULL,NULL);
io_error("png_get_file_size: fail to call png_create_info_struct()");
}
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_get_file_size: fail to call setjmp()");
}
png_init_io(_png_ptr, get());
png_set_sig_bytes(_png_ptr,PNG_BYTES_TO_CHECK);
png_read_info(_png_ptr, _info_ptr);
if (little_endian() && png_get_bit_depth(_png_ptr,_info_ptr)>8)
png_set_swap(_png_ptr);
}
public:
png_reader(FILE* file ) : file_mgr(file) { init(); }
png_reader(const char* filename) : file_mgr(filename, "rb") { init(); }
~png_reader() {
png_destroy_read_struct(&_png_ptr,&_info_ptr,NULL);
}
point2<std::ptrdiff_t> get_dimensions() {
return point2<std::ptrdiff_t>(png_get_image_width(_png_ptr,_info_ptr),
png_get_image_height(_png_ptr,_info_ptr));
}
template <typename View>
void apply(const View& view) {
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
png_get_IHDR(_png_ptr, _info_ptr,
&width, &height,&bit_depth,&color_type,&interlace_type,
NULL, NULL);
io_error_if(((png_uint_32)view.width()!=width || (png_uint_32)view.height()!= height),
"png_read_view: input view size does not match PNG file size");
if(png_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth!=bit_depth ||
png_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type!=color_type)
io_error("png_read_view: input view type is incompatible with the image type");
std::vector<pixel<typename channel_type<View>::type,
layout<typename color_space_type<View>::type> > > row(width);
for(png_uint_32 y=0;y<height;++y) {
png_read_row(_png_ptr,(png_bytep)&row.front(),NULL);
std::copy(row.begin(),row.end(),view.row_begin(y));
}
png_read_end(_png_ptr,NULL);
}
template <typename Image>
void read_image(Image& im) {
im.recreate(get_dimensions());
apply(view(im));
}
};
// This code will be simplified...
template <typename CC>
class png_reader_color_convert : public png_reader {
private:
CC _cc;
public:
png_reader_color_convert(FILE* file ,CC cc_in) : png_reader(file),_cc(cc_in) {}
png_reader_color_convert(FILE* file ) : png_reader(file) {}
png_reader_color_convert(const char* filename,CC cc_in) : png_reader(filename),_cc(cc_in) {}
png_reader_color_convert(const char* filename) : png_reader(filename) {}
template <typename View>
void apply(const View& view) {
png_uint_32 width, height;
int bit_depth, color_type, interlace_type;
png_get_IHDR(_png_ptr, _info_ptr,
&width, &height,&bit_depth,&color_type,&interlace_type,
int_p_NULL, int_p_NULL);
io_error_if(((png_uint_32)view.width()!=width || (png_uint_32)view.height()!= height),
"png_reader_color_convert::apply(): input view size does not match PNG file size");
switch (color_type) {
case PNG_COLOR_TYPE_GRAY:
switch (bit_depth) {
case 8: {
std::vector<gray8_pixel_t> row(width);
for(png_uint_32 y=0;y<height;++y) {
png_read_row(_png_ptr,(png_bytep)&row.front(),NULL);
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<gray8_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
case 16: {
std::vector<gray16_pixel_t> row(width);
for(png_uint_32 y=0;y<height;++y) {
png_read_row(_png_ptr,(png_bytep)&row.front(),NULL);
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<gray16_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth");
}
break;
case PNG_COLOR_TYPE_RGB:
switch (bit_depth) {
case 8: {
std::vector<rgb8_pixel_t> row(width);
for(png_uint_32 y=0;y<height;++y) {
png_read_row(_png_ptr,(png_bytep)&row.front(),NULL);
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgb8_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
case 16: {
std::vector<rgb16_pixel_t> row(width);
for(png_uint_32 y=0;y<height;++y) {
png_read_row(_png_ptr,(png_bytep)&row.front(),NULL);
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgb16_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth");
}
break;
case PNG_COLOR_TYPE_RGBA:
switch (bit_depth) {
case 8: {
std::vector<rgba8_pixel_t> row(width);
for(png_uint_32 y=0;y<height;++y) {
png_read_row(_png_ptr,(png_bytep)&row.front(),NULL);
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgba8_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
case 16: {
std::vector<rgba16_pixel_t> row(width);
for(png_uint_32 y=0;y<height;++y) {
png_read_row(_png_ptr,(png_bytep)&row.front(),NULL);
std::transform(row.begin(),row.end(),view.row_begin(y),color_convert_deref_fn<rgba16_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
default: io_error("png_reader_color_convert::apply(): unknown combination of color type and bit depth");
}
break;
default: io_error("png_reader_color_convert::apply(): unknown color type");
}
png_read_end(_png_ptr,NULL);
}
template <typename Image>
void read_image(Image& im) {
im.recreate(get_dimensions());
apply(view(im));
}
};
class png_writer : public file_mgr {
protected:
png_structp _png_ptr;
png_infop _info_ptr;
void init() {
_png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,NULL,NULL,NULL);
io_error_if(!_png_ptr,"png_write_initialize: fail to call png_create_write_struct()");
_info_ptr = png_create_info_struct(_png_ptr);
if (!_info_ptr) {
png_destroy_write_struct(&_png_ptr,NULL);
io_error("png_write_initialize: fail to call png_create_info_struct()");
}
if (setjmp(png_jmpbuf(_png_ptr))) {
png_destroy_write_struct(&_png_ptr, &_info_ptr);
io_error("png_write_initialize: fail to call setjmp(png_jmpbuf())");
}
png_init_io(_png_ptr,get());
}
public:
png_writer(FILE* file ) : file_mgr(file) { init(); }
png_writer(const char* filename) : file_mgr(filename, "wb") { init(); }
~png_writer() {
png_destroy_write_struct(&_png_ptr,&_info_ptr);
}
template <typename View>
void apply(const View& view) {
png_set_IHDR(_png_ptr, _info_ptr, view.width(), view.height(),
png_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth,
png_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type,
PNG_INTERLACE_NONE,
PNG_COMPRESSION_TYPE_DEFAULT,PNG_FILTER_TYPE_DEFAULT);
png_write_info(_png_ptr,_info_ptr);
if (little_endian() &&
png_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth>8)
png_set_swap(_png_ptr);
std::vector<pixel<typename channel_type<View>::type,
layout<typename color_space_type<View>::type> > > row(view.width());
for(int y=0;y<view.height();++y) {
std::copy(view.row_begin(y),view.row_end(y),row.begin());
png_write_row(_png_ptr,(png_bytep)&row.front());
}
png_write_end(_png_ptr,_info_ptr);
}
};
} // namespace detail
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,135 @@
/*
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 GIL_TIFF_DYNAMIC_IO_H
#define GIL_TIFF_DYNAMIC_IO_H
/// \file
/// \brief Support for reading and writing TIFF files
/// Requires libtiff!
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated June 10, 2006
//
// We are currently providing the following functions:
// template <typename Images> void tiff_read_image(const char*,any_image<Images>)
// template <typename Views> void tiff_write_view(const char*,any_image_view<Views>)
//
#include <string>
#include <boost/mpl/bool.hpp>
#include "../dynamic_image/dynamic_image_all.hpp"
#include "io_error.hpp"
#include "tiff_io.hpp"
#include "dynamic_io.hpp"
namespace boost { namespace gil {
namespace detail {
struct tiff_write_is_supported {
template<typename View> struct apply
: public mpl::bool_<tiff_write_support<View>::is_supported> {};
};
class tiff_writer_dynamic : public tiff_writer {
public:
typedef void result_type;
tiff_writer_dynamic(const char* filename) : tiff_writer(filename) {}
template <typename Views>
void write_view(const any_image_view<Views>& runtime_view) {
dynamic_io_fnobj<tiff_write_is_supported, tiff_writer> op(this);
apply_operation(runtime_view,op);
}
};
class tiff_type_format_checker {
int _bit_depth;
int _color_type;
public:
tiff_type_format_checker(int bit_depth_in,int color_type_in) :
_bit_depth(bit_depth_in),_color_type(color_type_in) {}
template <typename Image>
bool apply() {
return tiff_read_support<typename Image::view_t>::bit_depth==_bit_depth &&
tiff_read_support<typename Image::view_t>::color_type==_color_type;
}
};
struct tiff_read_is_supported {
template<typename View> struct apply
: public mpl::bool_<tiff_read_support<View>::is_supported> {};
};
class tiff_reader_dynamic : public tiff_reader {
public:
tiff_reader_dynamic(const char* filename) : tiff_reader(filename) {}
template <typename Images>
void read_image(any_image<Images>& im) {
int width,height;
unsigned short bps,photometric;
TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH,&width);
TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&height);
TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps);
TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric);
if (!construct_matched(im,tiff_type_format_checker(bps,photometric))) {
io_error("tiff_reader_dynamic::read_image(): no matching image type between those of the given any_image and that of the file");
} else {
im.recreate(width,height);
dynamic_io_fnobj<tiff_read_is_supported, tiff_reader> op(this);
apply_operation(view(im),op);
}
}
};
} // namespace detail
/// \ingroup TIFF_IO
/// \brief reads a TIFF image into a run-time instantiated image
/// Opens the given tiff file name, selects the first type in Images whose color space and channel are compatible to those of the image file
/// and creates a new image of that type with the dimensions specified by the image file.
/// Throws std::ios_base::failure if none of the types in Images are compatible with the type on disk.
template <typename Images>
inline void tiff_read_image(const char* filename,any_image<Images>& im) {
detail::tiff_reader_dynamic m(filename);
m.read_image(im);
}
/// \ingroup TIFF_IO
/// \brief reads a TIFF image into a run-time instantiated image
template <typename Images>
inline void tiff_read_image(const std::string& filename,any_image<Images>& im) {
tiff_read_image(filename.c_str(),im);
}
/// \ingroup TIFF_IO
/// \brief Saves the currently instantiated view to a tiff file specified by the given tiff image file name.
/// Throws std::ios_base::failure if the currently instantiated view type is not supported for writing by the I/O extension
/// or if it fails to create the file.
template <typename Views>
inline void tiff_write_view(const char* filename,const any_image_view<Views>& runtime_view) {
detail::tiff_writer_dynamic m(filename);
m.write_view(runtime_view);
}
/// \ingroup TIFF_IO
/// \brief Saves the currently instantiated view to a tiff file specified by the given tiff image file name.
template <typename Views>
inline void tiff_write_view(const std::string& filename,const any_image_view<Views>& runtime_view) {
tiff_write_view(filename.c_str(),runtime_view);
}
} } // namespace boost::gil
#endif

View File

@@ -0,0 +1,511 @@
/*
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 GIL_TIFF_IO_H
#define GIL_TIFF_IO_H
/// \file
/// \brief Support for reading and writing TIFF files
/// Requires libtiff!
/// \author Hailin Jin and Lubomir Bourdev \n
/// Adobe Systems Incorporated
/// \date 2005-2007 \n Last updated September 24, 2006
#include <vector>
#include <string>
#include <algorithm>
#include <boost/static_assert.hpp>
#include <tiffio.h>
#include "../../gil_all.hpp"
#include "io_error.hpp"
namespace boost { namespace gil {
namespace detail {
template <typename Channel,typename ColorSpace>
struct tiff_read_support_private {
BOOST_STATIC_CONSTANT(bool,is_supported=false);
BOOST_STATIC_CONSTANT(int,bit_depth=0);
BOOST_STATIC_CONSTANT(int,color_type=0);
};
template <>
struct tiff_read_support_private<bits8,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
};
template <>
struct tiff_read_support_private<bits8,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
};
template <>
struct tiff_read_support_private<bits16,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
};
template <>
struct tiff_read_support_private<bits16,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
};
template <>
struct tiff_read_support_private<bits32f,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=32);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
};
template <>
struct tiff_read_support_private<bits32f,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=32);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
};
template <typename Channel,typename ColorSpace>
struct tiff_write_support_private {
BOOST_STATIC_CONSTANT(bool,is_supported=false);
BOOST_STATIC_CONSTANT(int,bit_depth=0);
BOOST_STATIC_CONSTANT(int,color_type=0);
};
template <>
struct tiff_write_support_private<bits8,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
};
template <>
struct tiff_write_support_private<bits8,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=8);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
};
template <>
struct tiff_write_support_private<bits16,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
};
template <>
struct tiff_write_support_private<bits16,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=16);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
};
template <>
struct tiff_write_support_private<bits32f,gray_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=32);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_MINISBLACK);
};
template <>
struct tiff_write_support_private<bits32f,rgb_t> {
BOOST_STATIC_CONSTANT(bool,is_supported=true);
BOOST_STATIC_CONSTANT(int,bit_depth=32);
BOOST_STATIC_CONSTANT(int,color_type=PHOTOMETRIC_RGB);
};
class tiff_reader {
protected:
TIFF *_tp;
public:
tiff_reader(const char* filename,tdir_t dirnum=0) {
io_error_if((_tp=TIFFOpen(filename,"r"))==NULL,
"tiff_reader: fail to open file");
if(dirnum>0) {
io_error_if(TIFFSetDirectory(_tp,dirnum)!=1,
"tiff_reader: fail to set directory");
}
}
~tiff_reader() { TIFFClose(_tp); }
template <typename View>
void apply(const View& view) {
unsigned short bps,photometric;
point2<std::ptrdiff_t> dims=get_dimensions();
io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1);
io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1);
io_error_if(dims!=view.dimensions(),
"tiff_read_view: input view size does not match TIFF file size");
io_error_if(tiff_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth!=bps ||
tiff_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type!=photometric,
"tiff_read_view: input view type is incompatible with the image type");
std::size_t element_size=sizeof(pixel<typename channel_type<View>::type,
layout<typename color_space_type<View>::type> >);
std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
(std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
std::vector<pixel<typename channel_type<View>::type,
layout<typename color_space_type<View>::type> > > row(size_to_allocate);
for (int y=0;y<view.height();++y) {
io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
std::copy(row.begin(),row.begin()+view.width(),view.row_begin(y));
}
}
point2<std::ptrdiff_t> get_dimensions() {
int w,h;
io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGEWIDTH, &w)!=1);
io_error_if(TIFFGetField(_tp,TIFFTAG_IMAGELENGTH,&h)!=1);
return point2<std::ptrdiff_t>(w,h);
}
template <typename Image>
void read_image(Image& im) {
im.recreate(get_dimensions());
apply(view(im));
}
};
// This code will be simplified...
template <typename CC>
class tiff_reader_color_convert : public tiff_reader {
private:
CC _cc;
public:
tiff_reader_color_convert(const char* filename,tdir_t dirnum=0) :
tiff_reader(filename,dirnum) {}
tiff_reader_color_convert(const char* filename,CC cc_in,tdir_t dirnum=0) :
tiff_reader(filename,dirnum),_cc(cc_in) {}
template <typename View>
void apply(const View& view) {
point2<std::ptrdiff_t> dims=get_dimensions();
unsigned short bps,photometric;
io_error_if(TIFFGetField(_tp,TIFFTAG_BITSPERSAMPLE,&bps)!=1);
io_error_if(TIFFGetField(_tp,TIFFTAG_PHOTOMETRIC,&photometric)!=1);
io_error_if(dims!=view.dimensions(),
"tiff_reader_color_convert::apply(): input view size does not match TIFF file size");
switch (photometric) {
case PHOTOMETRIC_MINISBLACK: {
switch (bps) {
case 8: {
std::size_t element_size=sizeof(gray8_pixel_t);
std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
(std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
std::vector<gray8_pixel_t> row(size_to_allocate);
for (int y=0;y<view.height();++y) {
io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
color_convert_deref_fn<gray8_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
case 16: {
std::size_t element_size=sizeof(gray16_pixel_t);
std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
(std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
std::vector<gray16_pixel_t> row(size_to_allocate);
for (int y=0;y<view.height();++y) {
io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
color_convert_deref_fn<gray16_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
case 32: {
std::size_t element_size=sizeof(gray32f_pixel_t);
std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
(std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
std::vector<gray32f_pixel_t> row(size_to_allocate);
for (int y=0;y<view.height();++y) {
io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
color_convert_deref_fn<gray32f_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
default:
io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth");
}
break;
}
case PHOTOMETRIC_RGB: {
switch (bps) {
case 8: {
std::size_t element_size=sizeof(rgb8_pixel_t);
std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
(std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
std::vector<rgb8_pixel_t> row(size_to_allocate);
for (int y=0;y<view.height();++y) {
io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
color_convert_deref_fn<rgb8_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
case 16: {
std::size_t element_size=sizeof(rgb16_pixel_t);
std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
(std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
std::vector<rgb16_pixel_t> row(size_to_allocate);
for (int y=0;y<view.height();++y) {
io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
color_convert_deref_fn<rgb16_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
case 32: {
std::size_t element_size=sizeof(rgb32f_pixel_t);
std::size_t size_to_allocate = (std::max)((std::size_t)view.width(),
(std::size_t)(TIFFScanlineSize(_tp)+element_size-1)/element_size);
std::vector<rgb32f_pixel_t> row(size_to_allocate);
for (int y=0;y<view.height();++y) {
io_error_if(TIFFReadScanline(_tp,&row.front(), y)!=1);
std::transform(row.begin(),row.begin()+view.width(),view.row_begin(y),
color_convert_deref_fn<rgb32f_ref_t,typename View::value_type,CC>(_cc));
}
break;
}
default:
io_error("tiff_reader_color_convert::apply(): unknown combination of color type and bit depth");
}
break;
}
default: {
// reads an image in incompatible format via TIFFReadRGBAImage
rgba8_image_t rgbaImg(dims);
io_error_if(!TIFFReadRGBAImage(_tp, dims.x, dims.y, (uint32*)&gil::view(rgbaImg)(0,0), 0),
"tiff_reader_color_convert::unsupported image format");
copy_and_convert_pixels(flipped_up_down_view(const_view(rgbaImg)), view, _cc);
}
}
}
template <typename Image>
void read_image(Image& im) {
im.recreate(get_dimensions());
apply(view(im));
}
};
class tiff_writer {
protected:
TIFF* _tp;
public:
tiff_writer(const char *filename) {
io_error_if((_tp=TIFFOpen(filename,"w"))==NULL,
"tiff_writer: fail to open file");
}
~tiff_writer() {TIFFClose(_tp);}
template <typename View>
void apply(const View& view) {
io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGELENGTH, view.height())!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_IMAGEWIDTH, view.width())!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_PHOTOMETRIC, tiff_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type)!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_RESOLUTIONUNIT, RESUNIT_NONE)!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT)!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_SAMPLESPERPIXEL,num_channels<View>::value)!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_BITSPERSAMPLE, tiff_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth)!=1);
io_error_if(TIFFSetField(_tp,TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(_tp, 0))!=1);
std::vector<pixel<typename channel_type<View>::type,
layout<typename color_space_type<View>::type> > > row(view.width());
for (int y=0;y<view.height();++y) {
std::copy(view.row_begin(y),view.row_end(y),row.begin());
io_error_if(TIFFWriteScanline(_tp,&row.front(),y,0)!=1,
"tiff_write_view: fail to write file");
}
}
};
} // namespace detail
/// \ingroup TIFF_IO
/// \brief Determines whether the given view type is supported for reading
template <typename View>
struct tiff_read_support {
BOOST_STATIC_CONSTANT(bool,is_supported=
(detail::tiff_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::is_supported));
BOOST_STATIC_CONSTANT(int,bit_depth=
(detail::tiff_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth));
BOOST_STATIC_CONSTANT(int,color_type=
(detail::tiff_read_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type));
};
/// \ingroup TIFF_IO
/// \brief Returns the number of directories in the TIFF file
inline int tiff_get_directory_count(const char* filename) {
TIFF *tif;
io_error_if((tif=TIFFOpen(filename,"r"))==NULL,
"tiff_get_count: fail to open file");
int dircount = 0;
do {
dircount++;
} while (TIFFReadDirectory(tif));
TIFFClose(tif);
return dircount;
}
/// \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
inline point2<std::ptrdiff_t> tiff_read_dimensions(const char* filename,tdir_t dirnum=0) {
detail::tiff_reader m(filename,dirnum);
return m.get_dimensions();
}
/// \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
inline point2<std::ptrdiff_t> tiff_read_dimensions(const std::string& filename,tdir_t dirnum=0) {
return tiff_read_dimensions(filename.c_str(),dirnum);
}
/// \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 View>
inline void tiff_read_view(const char* filename,const View& view,tdir_t dirnum=0) {
BOOST_STATIC_ASSERT(tiff_read_support<View>::is_supported);
detail::tiff_reader m(filename,dirnum);
m.apply(view);
}
/// \ingroup TIFF_IO
/// \brief Loads the image specified by the given tiff image file name into the given view.
template <typename View>
inline void tiff_read_view(const std::string& filename,const View& view,tdir_t dirnum=0) {
tiff_read_view(filename.c_str(),view,dirnum);
}
/// \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 Image>
void tiff_read_image(const char* filename,Image& im,tdir_t dirnum=0) {
BOOST_STATIC_ASSERT(tiff_read_support<typename Image::view_t>::is_supported);
detail::tiff_reader m(filename,dirnum);
m.read_image(im);
}
/// \ingroup TIFF_IO
/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, and loads the pixels into it.
template <typename Image>
inline void tiff_read_image(const std::string& filename,Image& im,tdir_t dirnum=0) {
tiff_read_image(filename.c_str(),im,dirnum);
}
/// \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 View,typename CC>
inline void tiff_read_and_convert_view(const char* filename,const View& view,CC cc,tdir_t dirnum=0) {
detail::tiff_reader_color_convert<CC> m(filename,cc,dirnum);
m.apply(view);
}
/// \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 View>
inline void tiff_read_and_convert_view(const char* filename,const View& view,tdir_t dirnum=0) {
detail::tiff_reader_color_convert<default_color_converter> m(filename,default_color_converter(),dirnum);
m.apply(view);
}
/// \ingroup TIFF_IO
/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
template <typename View,typename CC>
inline void tiff_read_and_convert_view(const std::string& filename,const View& view,CC cc,tdir_t dirnum=0) {
tiff_read_and_convert_view(filename.c_str(),view,cc,dirnum);
}
/// \ingroup TIFF_IO
/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
template <typename View>
inline void tiff_read_and_convert_view(const std::string& filename,const View& view,tdir_t dirnum=0) {
tiff_read_and_convert_view(filename.c_str(),view,dirnum);
}
/// \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 Image,typename CC>
void tiff_read_and_convert_image(const char* filename,Image& im,CC cc,tdir_t dirnum=0) {
detail::tiff_reader_color_convert<CC> m(filename,cc,dirnum);
m.read_image(im);
}
/// \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 Image>
void tiff_read_and_convert_image(const char* filename,Image& im,tdir_t dirnum=0) {
detail::tiff_reader_color_convert<default_color_converter> m(filename,default_color_converter(),dirnum);
m.read_image(im);
}
/// \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.
template <typename Image,typename CC>
inline void tiff_read_and_convert_image(const std::string& filename,Image& im,CC cc,tdir_t dirnum=0) {
tiff_read_and_convert_image(filename.c_str(),im,cc,dirnum);
}
/// \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.
template <typename Image>
inline void tiff_read_and_convert_image(const std::string& filename,Image& im,tdir_t dirnum=0) {
tiff_read_and_convert_image(filename.c_str(),im,dirnum);
}
/// \ingroup TIFF_IO
/// \brief Determines whether the given view type is supported for writing
template <typename View>
struct tiff_write_support {
BOOST_STATIC_CONSTANT(bool,is_supported=
(detail::tiff_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::is_supported));
BOOST_STATIC_CONSTANT(int,bit_depth=
(detail::tiff_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::bit_depth));
BOOST_STATIC_CONSTANT(int,color_type=
(detail::tiff_write_support_private<typename channel_type<View>::type,
typename color_space_type<View>::type>::color_type));
BOOST_STATIC_CONSTANT(bool, value=is_supported);
};
/// \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 View>
inline void tiff_write_view(const char* filename,const View& view) {
BOOST_STATIC_ASSERT(tiff_write_support<View>::is_supported);
detail::tiff_writer m(filename);
m.apply(view);
}
/// \ingroup TIFF_IO
/// \brief Saves the view to a tiff file specified by the given tiff image file name.
template <typename View>
inline void tiff_write_view(const std::string& filename,const View& view) {
tiff_write_view(filename.c_str(),view);
}
} } // namespace boost::gil
#endif