summaryrefslogtreecommitdiff
path: root/boost/gil/extension
diff options
context:
space:
mode:
Diffstat (limited to 'boost/gil/extension')
-rw-r--r--boost/gil/extension/dynamic_image/algorithm.hpp6
-rw-r--r--boost/gil/extension/dynamic_image/any_image.hpp19
-rw-r--r--boost/gil/extension/dynamic_image/any_image_view.hpp8
-rw-r--r--boost/gil/extension/dynamic_image/apply_operation.hpp6
-rw-r--r--boost/gil/extension/dynamic_image/apply_operation_base.hpp14
-rw-r--r--boost/gil/extension/dynamic_image/image_view_factory.hpp4
-rw-r--r--boost/gil/extension/dynamic_image/reduce.hpp20
-rw-r--r--boost/gil/extension/dynamic_image/variant.hpp16
-rw-r--r--boost/gil/extension/io/bmp.hpp25
-rw-r--r--boost/gil/extension/io/bmp/detail/is_allowed.hpp92
-rw-r--r--boost/gil/extension/io/bmp/detail/read.hpp758
-rw-r--r--boost/gil/extension/io/bmp/detail/reader_backend.hpp258
-rw-r--r--boost/gil/extension/io/bmp/detail/scanline_read.hpp425
-rw-r--r--boost/gil/extension/io/bmp/detail/supported_types.hpp150
-rw-r--r--boost/gil/extension/io/bmp/detail/write.hpp230
-rw-r--r--boost/gil/extension/io/bmp/detail/writer_backend.hpp66
-rw-r--r--boost/gil/extension/io/bmp/old.hpp181
-rw-r--r--boost/gil/extension/io/bmp/read.hpp43
-rw-r--r--boost/gil/extension/io/bmp/tags.hpp170
-rw-r--r--boost/gil/extension/io/bmp/write.hpp31
-rw-r--r--boost/gil/extension/io/io_error.hpp51
-rw-r--r--boost/gil/extension/io/jpeg.hpp25
-rw-r--r--boost/gil/extension/io/jpeg/detail/base.hpp46
-rw-r--r--boost/gil/extension/io/jpeg/detail/is_allowed.hpp54
-rw-r--r--boost/gil/extension/io/jpeg/detail/read.hpp331
-rw-r--r--boost/gil/extension/io/jpeg/detail/reader_backend.hpp329
-rw-r--r--boost/gil/extension/io/jpeg/detail/scanline_read.hpp163
-rw-r--r--boost/gil/extension/io/jpeg/detail/supported_types.hpp121
-rw-r--r--boost/gil/extension/io/jpeg/detail/write.hpp194
-rw-r--r--boost/gil/extension/io/jpeg/detail/writer_backend.hpp203
-rw-r--r--boost/gil/extension/io/jpeg/old.hpp182
-rw-r--r--boost/gil/extension/io/jpeg/read.hpp43
-rw-r--r--boost/gil/extension/io/jpeg/tags.hpp244
-rw-r--r--boost/gil/extension/io/jpeg/write.hpp31
-rw-r--r--boost/gil/extension/io/jpeg_dynamic_io.hpp130
-rw-r--r--boost/gil/extension/io/jpeg_io.hpp202
-rw-r--r--boost/gil/extension/io/jpeg_io_private.hpp226
-rw-r--r--boost/gil/extension/io/png.hpp25
-rw-r--r--boost/gil/extension/io/png/detail/base.hpp109
-rw-r--r--boost/gil/extension/io/png/detail/is_allowed.hpp55
-rw-r--r--boost/gil/extension/io/png/detail/read.hpp444
-rw-r--r--boost/gil/extension/io/png/detail/reader_backend.hpp698
-rw-r--r--boost/gil/extension/io/png/detail/scanline_read.hpp181
-rw-r--r--boost/gil/extension/io/png/detail/supported_types.hpp366
-rw-r--r--boost/gil/extension/io/png/detail/write.hpp242
-rw-r--r--boost/gil/extension/io/png/detail/writer_backend.hpp516
-rw-r--r--boost/gil/extension/io/png/old.hpp179
-rw-r--r--boost/gil/extension/io/png/read.hpp43
-rw-r--r--boost/gil/extension/io/png/tags.hpp844
-rw-r--r--boost/gil/extension/io/png/write.hpp31
-rw-r--r--boost/gil/extension/io/png_dynamic_io.hpp141
-rw-r--r--boost/gil/extension/io/png_io.hpp214
-rw-r--r--boost/gil/extension/io/png_io_private.hpp360
-rw-r--r--boost/gil/extension/io/pnm.hpp25
-rw-r--r--boost/gil/extension/io/pnm/detail/is_allowed.hpp60
-rw-r--r--boost/gil/extension/io/pnm/detail/read.hpp465
-rw-r--r--boost/gil/extension/io/pnm/detail/reader_backend.hpp192
-rw-r--r--boost/gil/extension/io/pnm/detail/scanline_read.hpp259
-rw-r--r--boost/gil/extension/io/pnm/detail/supported_types.hpp146
-rw-r--r--boost/gil/extension/io/pnm/detail/write.hpp268
-rw-r--r--boost/gil/extension/io/pnm/detail/writer_backend.hpp66
-rw-r--r--boost/gil/extension/io/pnm/old.hpp181
-rw-r--r--boost/gil/extension/io/pnm/read.hpp41
-rw-r--r--boost/gil/extension/io/pnm/tags.hpp106
-rw-r--r--boost/gil/extension/io/pnm/write.hpp31
-rw-r--r--boost/gil/extension/io/raw.hpp24
-rw-r--r--boost/gil/extension/io/raw/detail/device.hpp143
-rw-r--r--boost/gil/extension/io/raw/detail/is_allowed.hpp57
-rw-r--r--boost/gil/extension/io/raw/detail/read.hpp259
-rw-r--r--boost/gil/extension/io/raw/detail/reader_backend.hpp151
-rw-r--r--boost/gil/extension/io/raw/detail/supported_types.hpp84
-rw-r--r--boost/gil/extension/io/raw/read.hpp40
-rw-r--r--boost/gil/extension/io/raw/tags.hpp216
-rw-r--r--boost/gil/extension/io/targa.hpp25
-rw-r--r--boost/gil/extension/io/targa/detail/is_allowed.hpp64
-rw-r--r--boost/gil/extension/io/targa/detail/read.hpp417
-rw-r--r--boost/gil/extension/io/targa/detail/reader_backend.hpp175
-rw-r--r--boost/gil/extension/io/targa/detail/scanline_read.hpp167
-rw-r--r--boost/gil/extension/io/targa/detail/supported_types.hpp110
-rw-r--r--boost/gil/extension/io/targa/detail/write.hpp197
-rw-r--r--boost/gil/extension/io/targa/detail/writer_backend.hpp66
-rw-r--r--boost/gil/extension/io/targa/old.hpp181
-rw-r--r--boost/gil/extension/io/targa/read.hpp41
-rw-r--r--boost/gil/extension/io/targa/tags.hpp177
-rw-r--r--boost/gil/extension/io/targa/write.hpp31
-rw-r--r--boost/gil/extension/io/tiff.hpp25
-rw-r--r--boost/gil/extension/io/tiff/detail/device.hpp489
-rw-r--r--boost/gil/extension/io/tiff/detail/is_allowed.hpp226
-rw-r--r--boost/gil/extension/io/tiff/detail/log.hpp77
-rw-r--r--boost/gil/extension/io/tiff/detail/read.hpp801
-rw-r--r--boost/gil/extension/io/tiff/detail/reader_backend.hpp173
-rw-r--r--boost/gil/extension/io/tiff/detail/scanline_read.hpp465
-rw-r--r--boost/gil/extension/io/tiff/detail/supported_types.hpp62
-rw-r--r--boost/gil/extension/io/tiff/detail/write.hpp463
-rw-r--r--boost/gil/extension/io/tiff/detail/writer_backend.hpp145
-rw-r--r--boost/gil/extension/io/tiff/old.hpp180
-rw-r--r--boost/gil/extension/io/tiff/read.hpp43
-rw-r--r--boost/gil/extension/io/tiff/tags.hpp359
-rw-r--r--boost/gil/extension/io/tiff/write.hpp32
-rw-r--r--boost/gil/extension/io/tiff_dynamic_io.hpp135
-rw-r--r--boost/gil/extension/io/tiff_io.hpp511
-rw-r--r--boost/gil/extension/numeric/affine.hpp93
-rw-r--r--boost/gil/extension/numeric/algorithm.hpp158
-rw-r--r--boost/gil/extension/numeric/channel_numeric_operations.hpp159
-rw-r--r--boost/gil/extension/numeric/convolve.hpp219
-rw-r--r--boost/gil/extension/numeric/kernel.hpp104
-rw-r--r--boost/gil/extension/numeric/pixel_numeric_operations.hpp182
-rw-r--r--boost/gil/extension/numeric/resample.hpp145
-rw-r--r--boost/gil/extension/numeric/sampler.hpp200
-rw-r--r--boost/gil/extension/toolbox/color_converters.hpp25
-rw-r--r--boost/gil/extension/toolbox/color_converters/gray_to_rgba.hpp49
-rw-r--r--boost/gil/extension/toolbox/color_converters/rgb_to_luminance.hpp43
-rw-r--r--boost/gil/extension/toolbox/color_spaces.hpp29
-rw-r--r--boost/gil/extension/toolbox/color_spaces/cmyka.hpp86
-rw-r--r--boost/gil/extension/toolbox/color_spaces/gray_alpha.hpp104
-rw-r--r--boost/gil/extension/toolbox/color_spaces/hsl.hpp268
-rw-r--r--boost/gil/extension/toolbox/color_spaces/hsv.hpp237
-rw-r--r--boost/gil/extension/toolbox/color_spaces/lab.hpp178
-rw-r--r--boost/gil/extension/toolbox/color_spaces/xyz.hpp157
-rw-r--r--boost/gil/extension/toolbox/color_spaces/ycbcr.hpp253
-rw-r--r--boost/gil/extension/toolbox/dynamic_images.hpp (renamed from boost/gil/extension/io/dynamic_io.hpp)74
-rw-r--r--boost/gil/extension/toolbox/image_types.hpp24
-rw-r--r--boost/gil/extension/toolbox/image_types/indexed_image.hpp392
-rw-r--r--boost/gil/extension/toolbox/image_types/subchroma_image.hpp577
-rw-r--r--boost/gil/extension/toolbox/metafunctions.hpp31
-rw-r--r--boost/gil/extension/toolbox/metafunctions/channel_type.hpp111
-rw-r--r--boost/gil/extension/toolbox/metafunctions/channel_view.hpp79
-rw-r--r--boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp73
-rw-r--r--boost/gil/extension/toolbox/metafunctions/get_pixel_type.hpp46
-rw-r--r--boost/gil/extension/toolbox/metafunctions/gil_extensions.hpp42
-rw-r--r--boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp47
-rw-r--r--boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp93
-rw-r--r--boost/gil/extension/toolbox/metafunctions/is_similar.hpp43
-rw-r--r--boost/gil/extension/toolbox/metafunctions/pixel_bit_size.hpp55
-rw-r--r--boost/gil/extension/toolbox/toolbox.hpp29
135 files changed, 20584 insertions, 2017 deletions
diff --git a/boost/gil/extension/dynamic_image/algorithm.hpp b/boost/gil/extension/dynamic_image/algorithm.hpp
index dffd399918..abd5776b0e 100644
--- a/boost/gil/extension/dynamic_image/algorithm.hpp
+++ b/boost/gil/extension/dynamic_image/algorithm.hpp
@@ -30,7 +30,7 @@ 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 {
+ BOOST_FORCEINLINE bool apply_compatible(const V1& v1, const V2& v2) const {
return equal_pixels(v1,v2);
}
};
@@ -60,7 +60,7 @@ bool equal_pixels(const any_image_view<Types1>& src, const any_image_view<Types2
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 {
+ BOOST_FORCEINLINE void apply_compatible(const View1& src, const View2& dst) const {
copy_pixels(src,dst);
}
};
@@ -144,7 +144,7 @@ template <bool COMPATIBLE> struct fill_pixels_fn1 {
// 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 V, typename Value> static void apply(const V&, const Value&) { throw std::bad_cast();}
};
template <typename Value>
diff --git a/boost/gil/extension/dynamic_image/any_image.hpp b/boost/gil/extension/dynamic_image/any_image.hpp
index dde831994a..3c4445ff10 100644
--- a/boost/gil/extension/dynamic_image/any_image.hpp
+++ b/boost/gil/extension/dynamic_image/any_image.hpp
@@ -29,6 +29,11 @@
//#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
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
namespace boost { namespace gil {
namespace detail {
@@ -84,9 +89,11 @@ public:
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 Types> any_image(const any_image<Types>& v) : parent_t((const variant<Types>&)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;}
+ 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;}
+ template <typename Types> any_image& operator=(const any_image<Types>& v) { parent_t::operator=((const variant<Types>&)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); }
@@ -104,13 +111,13 @@ public:
/// \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
+template <typename Types> BOOST_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
+template <typename Types> BOOST_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>());
}
@@ -118,6 +125,10 @@ typename any_image<Types>::const_view_t const_view(const any_image<Types>& anyIm
} } // namespace boost::gil
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
//#ifdef _MSC_VER
//#pragma warning(pop)
//#endif
diff --git a/boost/gil/extension/dynamic_image/any_image_view.hpp b/boost/gil/extension/dynamic_image/any_image_view.hpp
index 1b1d5503fc..a99e8baaea 100644
--- a/boost/gil/extension/dynamic_image/any_image_view.hpp
+++ b/boost/gil/extension/dynamic_image/any_image_view.hpp
@@ -38,7 +38,7 @@ 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; }
+ template <typename T> result_type operator()(const T&) 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;
@@ -72,9 +72,11 @@ public:
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 Types> any_image_view(const any_image_view<Types>& v) : parent_t((const variant<Types>&)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;}
+ 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;}
+ template <typename Types> any_image_view& operator=(const any_image_view<Types>& v) { parent_t::operator=((const variant<Types>&)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()); }
diff --git a/boost/gil/extension/dynamic_image/apply_operation.hpp b/boost/gil/extension/dynamic_image/apply_operation.hpp
index ed2571391e..beb79bad77 100644
--- a/boost/gil/extension/dynamic_image/apply_operation.hpp
+++ b/boost/gil/extension/dynamic_image/apply_operation.hpp
@@ -31,21 +31,21 @@ 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
+template <typename Types, typename UnaryOp> BOOST_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
+template <typename Types, typename UnaryOp> BOOST_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
+template <typename Types1, typename Types2, typename BinaryOp> BOOST_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);
}
diff --git a/boost/gil/extension/dynamic_image/apply_operation_base.hpp b/boost/gil/extension/dynamic_image/apply_operation_base.hpp
index 3b55de6e03..2204a93b01 100644
--- a/boost/gil/extension/dynamic_image/apply_operation_base.hpp
+++ b/boost/gil/extension/dynamic_image/apply_operation_base.hpp
@@ -127,13 +127,13 @@ GIL_GENERATE_APPLY_FWD_OPS(99)
// 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) {
+typename Op::result_type BOOST_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) {
+typename Op::result_type BOOST_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);
}
@@ -141,26 +141,26 @@ namespace detail {
template <typename T2, typename Op>
struct reduce_bind1 {
const T2& _t2;
- Op& _op;
+ 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 T1> BOOST_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;
+ 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) {
+ template <typename T2> BOOST_FORCEINLINE result_type operator()(const T2& t2) {
return apply_operation_basec<Types1>(_bits1, _index1, reduce_bind1<T2,Op>(t2, _op));
}
};
@@ -168,7 +168,7 @@ 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) {
+static typename Op::result_type BOOST_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));
}
diff --git a/boost/gil/extension/dynamic_image/image_view_factory.hpp b/boost/gil/extension/dynamic_image/image_view_factory.hpp
index fe82ef1c6b..69ac4f681d 100644
--- a/boost/gil/extension/dynamic_image/image_view_factory.hpp
+++ b/boost/gil/extension/dynamic_image/image_view_factory.hpp
@@ -175,7 +175,7 @@ struct color_converted_view_type<any_image_view<ViewTypes>,DstP,CC> {
/// \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) {
+typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type color_converted_view(const any_image_view<ViewTypes>& src, CC) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
}
@@ -198,7 +198,7 @@ typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type color_
/// \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) {
+typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type any_color_converted_view(const any_image_view<ViewTypes>& src, CC) {
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
}
diff --git a/boost/gil/extension/dynamic_image/reduce.hpp b/boost/gil/extension/dynamic_image/reduce.hpp
index ea8623deed..6e86faa991 100644
--- a/boost/gil/extension/dynamic_image/reduce.hpp
+++ b/boost/gil/extension/dynamic_image/reduce.hpp
@@ -59,7 +59,7 @@ 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;
+ static const std::size_t value=size<DstTypes>::value - order<DstTypes, typename gil::at_c<SrcTypes,K>::type>::type::value +1;
typedef size_t<value> type;
};
@@ -147,11 +147,11 @@ struct unary_reduce : public unary_reduce_impl<Types,Op> {
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) {
+ template <typename Bits> BOOST_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) {
+ template <typename Bits> BOOST_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);
}
};
@@ -161,11 +161,11 @@ 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) {
+ template <typename Bits> BOOST_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) {
+ template <typename Bits> BOOST_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));
}
};
@@ -245,17 +245,17 @@ public:
};
template <typename Types, typename UnaryOp>
-GIL_FORCEINLINE typename UnaryOp::result_type apply_operation(variant<Types>& arg, UnaryOp op) {
+BOOST_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) {
+BOOST_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) {
+BOOST_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);
}
@@ -699,11 +699,11 @@ namespace detail {
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;
+ typedef typename view_type<uint8_t,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;
+ typedef typename image_type<uint8_t,typename reduce_color_space<Cs>::type>::type type;
};
////////////////////////////////////////////////////////
diff --git a/boost/gil/extension/dynamic_image/variant.hpp b/boost/gil/extension/dynamic_image/variant.hpp
index 24460ca6bf..1ab53b549d 100644
--- a/boost/gil/extension/dynamic_image/variant.hpp
+++ b/boost/gil/extension/dynamic_image/variant.hpp
@@ -29,7 +29,8 @@
#include <algorithm>
#include <typeinfo>
#include <boost/bind.hpp>
-
+#include <boost/utility/enable_if.hpp>
+#include <boost/mpl/bool.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/sizeof.hpp>
@@ -48,6 +49,7 @@ namespace detail {
};
template <typename T, typename Bits> void copy_construct_in_place(const T& t, Bits& bits);
template <typename Bits> struct copy_construct_in_place_fn;
+ template <typename Types> struct type_to_index_fn;
}
/**
\brief Represents a concrete instance of a run-time specified type from a set of types
@@ -100,6 +102,11 @@ public:
// 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); }
+ template <typename Types2> explicit variant(const variant<Types2>& obj) : _index(apply_operation(obj,detail::type_to_index_fn<Types>())) {
+ if (_index==NUM_TYPES) throw std::bad_cast();
+ apply_operation(obj, detail::copy_construct_in_place_fn<base_t>(_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);
@@ -161,6 +168,13 @@ namespace detail {
return x==*gil_reinterpret_cast_c<const T*>(&_dst);
}
};
+
+ template <typename Types>
+ struct type_to_index_fn {
+ typedef std::size_t result_type;
+
+ template <typename T> result_type operator()(const T&) const { return detail::type_to_index<Types,T>::value; }
+ };
}
// When doSwap is true, swaps obj with the contents of the variant. obj will contain default-constructed instance after the call
diff --git a/boost/gil/extension/io/bmp.hpp b/boost/gil/extension/io/bmp.hpp
new file mode 100644
index 0000000000..d9242dde0c
--- /dev/null
+++ b/boost/gil/extension/io/bmp.hpp
@@ -0,0 +1,25 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/bmp/read.hpp>
+#include <boost/gil/extension/io/bmp/write.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/bmp/detail/is_allowed.hpp b/boost/gil/extension/io/bmp/detail/is_allowed.hpp
new file mode 100644
index 0000000000..fab24d58d7
--- /dev/null
+++ b/boost/gil/extension/io/bmp/detail/is_allowed.hpp
@@ -0,0 +1,92 @@
+/*
+ Copyright 2009 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_IS_ALLOWED_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_IS_ALLOWED_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil { namespace detail {
+
+template< typename View >
+bool is_allowed( const image_read_info< bmp_tag >& info
+ , mpl::true_ // is read_and_no_convert
+ )
+{
+ bmp_bits_per_pixel::type src_bits_per_pixel = 0;
+
+ switch( info._bits_per_pixel )
+ {
+ case 1:
+ case 4:
+ case 8:
+ {
+ if( info._header_size == bmp_header_size::_win32_info_size
+ && info._compression != bmp_compression::_rle8
+ && info._compression != bmp_compression::_rle4
+ )
+ {
+ src_bits_per_pixel = 32;
+ }
+ else
+ {
+ src_bits_per_pixel = 24;
+ }
+
+ break;
+ }
+
+ case 15:
+ case 16:
+ {
+ src_bits_per_pixel = 24;
+
+ break;
+ }
+
+ case 24:
+ case 32:
+ {
+ src_bits_per_pixel = info._bits_per_pixel;
+
+ break;
+ }
+ default:
+ {
+ io_error( "Pixel size not supported." );
+ }
+ }
+
+ typedef typename channel_traits< typename element_type< typename View::value_type >::type >::value_type channel_t;
+ bmp_bits_per_pixel::type dst_bits_per_pixel = detail::unsigned_integral_num_bits< channel_t >::value
+ * num_channels< View >::value;
+
+ return ( dst_bits_per_pixel == src_bits_per_pixel );
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< bmp_tag >& /* info */
+ , mpl::false_ // is read_and_convert
+ )
+{
+ return true;
+}
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/detail/read.hpp b/boost/gil/extension/io/bmp/detail/read.hpp
new file mode 100644
index 0000000000..09e5652885
--- /dev/null
+++ b/boost/gil/extension/io/bmp/detail/read.hpp
@@ -0,0 +1,758 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/mpl/and.hpp>
+#include <boost/type_traits/is_same.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/bmp/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/bmp/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// BMP Reader
+///
+template< typename Device
+ , typename ConversionPolicy
+ >
+class reader< Device
+ , bmp_tag
+ , ConversionPolicy
+ >
+ : public reader_base< bmp_tag
+ , ConversionPolicy
+ >
+ , public reader_backend< Device
+ , bmp_tag
+ >
+{
+private:
+
+ typedef reader< Device
+ , bmp_tag
+ , ConversionPolicy
+ > this_t;
+
+ typedef typename ConversionPolicy::color_converter_type cc_t;
+
+public:
+
+ typedef reader_backend< Device, bmp_tag > backend_t;
+
+public:
+
+ //
+ // Constructor
+ //
+ reader( const Device& io_dev
+ , const image_read_settings< bmp_tag >& settings
+ )
+ : backend_t( io_dev
+ , settings
+ )
+ , _pitch( 0 )
+ {}
+
+ //
+ // Constructor
+ //
+ reader( const Device& io_dev
+ , const ConversionPolicy& cc
+ , const image_read_settings< bmp_tag >& settings
+ )
+ : reader_base< bmp_tag
+ , ConversionPolicy
+ >( cc )
+ , backend_t( io_dev
+ , settings
+ )
+ , _pitch( 0 )
+ {}
+
+
+ /// Read image.
+ template< typename View >
+ void apply( const View& dst_view )
+ {
+ if( this->_info._valid == false )
+ {
+ io_error( "Image header was not read." );
+ }
+
+ typedef typename is_same< ConversionPolicy
+ , detail::read_and_no_convert
+ >::type is_read_and_convert_t;
+
+ io_error_if( !detail::is_allowed< View >( this->_info
+ , is_read_and_convert_t()
+ )
+ , "Image types aren't compatible."
+ );
+
+ // the row pitch must be multiple 4 bytes
+ if( this->_info._bits_per_pixel < 8 )
+ {
+ _pitch = static_cast<long>((( this->_info._width * this->_info._bits_per_pixel ) + 7 ) >> 3 );
+ }
+ else
+ {
+ _pitch = static_cast<long>( this->_info._width * (( this->_info._bits_per_pixel + 7 ) >> 3 ));
+ }
+
+ _pitch = (_pitch + 3) & ~3;
+
+ switch( this->_info._bits_per_pixel )
+ {
+ case 1:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+
+ read_palette_image< gray1_image_t::view_t
+ , detail::mirror_bits< byte_vector_t
+ , mpl::true_
+ >
+ > ( dst_view );
+ break;
+ }
+
+ case 4:
+ {
+ switch ( this->_info._compression )
+ {
+ case bmp_compression::_rle4:
+ {
+ ///@todo How can we determine that?
+ this->_scanline_length = 0;
+
+ read_palette_image_rle( dst_view );
+
+ break;
+ }
+
+ case bmp_compression::_rgb:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+
+ read_palette_image< gray4_image_t::view_t
+ , detail::swap_half_bytes< byte_vector_t
+ , mpl::true_
+ >
+ > ( dst_view );
+ break;
+ }
+
+ default:
+ {
+ io_error( "Unsupported compression mode in BMP file." );
+ break;
+ }
+ }
+ break;
+ }
+
+ case 8:
+ {
+ switch ( this->_info._compression )
+ {
+ case bmp_compression::_rle8:
+ {
+ ///@todo How can we determine that?
+ this->_scanline_length = 0;
+
+ read_palette_image_rle( dst_view );
+ break;
+ }
+
+ case bmp_compression::_rgb:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+
+ read_palette_image< gray8_image_t::view_t
+ , detail::do_nothing< std::vector< gray8_pixel_t > >
+ > ( dst_view );
+ break;
+ }
+
+ default:
+ {
+ io_error( "Unsupported compression mode in BMP file." );
+ break;
+ }
+ }
+
+ break;
+ }
+
+ case 15: case 16:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgb8_view_t >::value + 3 ) & ~3;
+
+ read_data_15( dst_view );
+
+ break;
+ }
+
+ case 24:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgb8_view_t >::value + 3 ) & ~3;
+
+ read_data< bgr8_view_t >( dst_view );
+
+ break;
+ }
+
+ case 32:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+
+ read_data< bgra8_view_t >( dst_view );
+
+ break;
+ }
+ }
+ }
+
+private:
+
+ long get_offset( std::ptrdiff_t pos )
+ {
+ if( this->_info._height > 0 )
+ {
+ // the image is upside down
+ return static_cast<long>( ( this->_info._offset
+ + ( this->_info._height - 1 - pos ) * _pitch
+ ));
+ }
+ else
+ {
+ return static_cast<long>( ( this->_info._offset
+ + pos * _pitch
+ ));
+ }
+ }
+
+ template< typename View_Src
+ , typename Byte_Manipulator
+ , typename View_Dst
+ >
+ void read_palette_image( const View_Dst& view )
+ {
+ this->read_palette();
+
+ typedef detail::row_buffer_helper_view< View_Src > rh_t;
+ typedef typename rh_t::iterator_t it_t;
+
+ rh_t rh( _pitch, true );
+
+ // we have to swap bits
+ Byte_Manipulator byte_manipulator;
+
+ for( std::ptrdiff_t y = 0
+ ; y < this->_settings._dim.y
+ ; ++y
+ )
+ {
+ this->_io_dev.seek( get_offset( y + this->_settings._top_left.y ));
+
+ this->_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
+ , _pitch
+ );
+
+ byte_manipulator( rh.buffer() );
+
+ typename View_Dst::x_iterator dst_it = view.row_begin( y );
+
+ it_t it = rh.begin() + this->_settings._top_left.x;
+ it_t end = it + this->_settings._dim.x;
+
+ for( ; it != end; ++it, ++dst_it )
+ {
+ unsigned char c = get_color( *it, gray_color_t() );
+ *dst_it = this->_palette[ c ];
+ }
+ }
+ }
+
+ template< typename View >
+ void read_data_15( const View& view )
+ {
+ byte_vector_t row( _pitch );
+
+ // read the color masks
+ if( this->_info._compression == bmp_compression::_bitfield )
+ {
+ this->_mask.red.mask = this->_io_dev.read_uint32();
+ this->_mask.green.mask = this->_io_dev.read_uint32();
+ this->_mask.blue.mask = this->_io_dev.read_uint32();
+
+ this->_mask.red.width = detail::count_ones( this->_mask.red.mask );
+ this->_mask.green.width = detail::count_ones( this->_mask.green.mask );
+ this->_mask.blue.width = detail::count_ones( this->_mask.blue.mask );
+
+ this->_mask.red.shift = detail::trailing_zeros( this->_mask.red.mask );
+ this->_mask.green.shift = detail::trailing_zeros( this->_mask.green.mask );
+ this->_mask.blue.shift = detail::trailing_zeros( this->_mask.blue.mask );
+ }
+ else if( this->_info._compression == bmp_compression::_rgb )
+ {
+ switch( this->_info._bits_per_pixel )
+ {
+ case 15:
+ case 16:
+ {
+ this->_mask.red.mask = 0x007C00; this->_mask.red.width = 5; this->_mask.red.shift = 10;
+ this->_mask.green.mask = 0x0003E0; this->_mask.green.width = 5; this->_mask.green.shift = 5;
+ this->_mask.blue.mask = 0x00001F; this->_mask.blue.width = 5; this->_mask.blue.shift = 0;
+
+ break;
+ }
+
+ case 24:
+ case 32:
+ {
+ this->_mask.red.mask = 0xFF0000; this->_mask.red.width = 8; this->_mask.red.shift = 16;
+ this->_mask.green.mask = 0x00FF00; this->_mask.green.width = 8; this->_mask.green.shift = 8;
+ this->_mask.blue.mask = 0x0000FF; this->_mask.blue.width = 8; this->_mask.blue.shift = 0;
+
+ break;
+ }
+ }
+ }
+ else
+ {
+ io_error( "bmp_reader::apply(): unsupported BMP compression" );
+ }
+
+ typedef rgb8_image_t image_t;
+ typedef typename image_t::view_t::x_iterator it_t;
+
+ for( std::ptrdiff_t y = 0
+ ; y < this->_settings._dim.y
+ ; ++y
+ )
+ {
+ this->_io_dev.seek( get_offset( y + this->_settings._top_left.y ));
+
+ this->_io_dev.read( &row.front()
+ , row.size()
+ );
+
+ image_t img_row( this->_info._width, 1 );
+ image_t::view_t v = gil::view( img_row );
+ it_t it = v.row_begin( 0 );
+
+ it_t beg = v.row_begin( 0 ) + this->_settings._top_left.x;
+ it_t end = beg + this->_settings._dim.x;
+
+ byte_t* src = &row.front();
+ for( int32_t i = 0 ; i < this->_info._width; ++i, src += 2 )
+ {
+ int p = ( src[1] << 8 ) | src[0];
+
+ int r = ((p & this->_mask.red.mask) >> this->_mask.red.shift) << (8 - this->_mask.red.width);
+ int g = ((p & this->_mask.green.mask) >> this->_mask.green.shift) << (8 - this->_mask.green.width);
+ int b = ((p & this->_mask.blue.mask) >> this->_mask.blue.shift) << (8 - this->_mask.blue.width);
+
+ get_color( it[i], red_t() ) = static_cast< byte_t >( r );
+ get_color( it[i], green_t() ) = static_cast< byte_t >( g );
+ get_color( it[i], blue_t() ) = static_cast< byte_t >( b );
+ }
+
+ this->_cc_policy.read( beg
+ , end
+ , view.row_begin( y )
+ );
+ }
+ }
+
+
+ // 8-8-8 BGR
+ // 8-8-8-8 BGRA
+ template< typename View_Src
+ , typename View_Dst
+ >
+ void read_data( const View_Dst& view )
+ {
+ byte_vector_t row( _pitch );
+
+ View_Src v = interleaved_view( this->_info._width
+ , 1
+ , (typename View_Src::value_type*) &row.front()
+ , this->_info._width * num_channels< View_Src >::value
+ );
+
+ typename View_Src::x_iterator beg = v.row_begin( 0 ) + this->_settings._top_left.x;
+ typename View_Src::x_iterator end = beg + this->_settings._dim.x;
+
+ for( std::ptrdiff_t y = 0
+ ; y < this->_settings._dim.y
+ ; ++y
+ )
+ {
+ this->_io_dev.seek( get_offset( y + this->_settings._top_left.y ));
+
+ this->_io_dev.read( &row.front()
+ , row.size()
+ );
+
+ this->_cc_policy.read( beg
+ , end
+ , view.row_begin( y )
+ );
+ }
+ }
+
+ template< typename Buffer
+ , typename View
+ >
+ void copy_row_if_needed( const Buffer& buf
+ , const View& view
+ , std::ptrdiff_t y
+ )
+ {
+ if( y >= this->_settings._top_left.y
+ && y < this->_settings._dim.y
+ )
+ {
+ typename Buffer::const_iterator beg = buf.begin() + this->_settings._top_left.x;
+ typename Buffer::const_iterator end = beg + this->_settings._dim.x;
+
+ std::copy( beg
+ , end
+ , view.row_begin( y )
+ );
+ }
+ }
+
+ template< typename View_Dst >
+ void read_palette_image_rle( const View_Dst& view )
+ {
+ assert( this->_info._compression == bmp_compression::_rle4
+ || this->_info._compression == bmp_compression::_rle8
+ );
+
+ this->read_palette();
+
+ // jump to start of rle4 data
+ this->_io_dev.seek( this->_info._offset );
+
+ // we need to know the stream position for padding purposes
+ std::size_t stream_pos = this->_info._offset;
+
+ typedef std::vector< rgba8_pixel_t > Buf_type;
+ Buf_type buf( this->_settings._dim.x );
+ Buf_type::iterator dst_it = buf.begin();
+ Buf_type::iterator dst_end = buf.end();
+
+ // If height is positive, the bitmap is a bottom-up DIB.
+ // If height is negative, the bitmap is a top-down DIB.
+ // The origin of a bottom-up DIB is the bottom left corner of the bitmap image,
+ // which is the first pixel of the first row of bitmap data.
+ // The origin of a top-down DIB is also the bottom left corner of the bitmap image,
+ // but in this case the bottom left corner is the first pixel of the last row of bitmap data.
+ // - "Programming Windows", 5th Ed. by Charles Petzold explains Windows docs ambiguities.
+ std::ptrdiff_t ybeg = 0;
+ std::ptrdiff_t yend = this->_settings._dim.y;
+ std::ptrdiff_t yinc = 1;
+ if( this->_info._height > 0 )
+ {
+ ybeg = this->_settings._dim.y - 1;
+ yend = -1;
+ yinc = -1;
+ }
+
+ std::ptrdiff_t y = ybeg;
+ bool finished = false;
+
+ while ( !finished )
+ {
+ std::ptrdiff_t count = this->_io_dev.read_uint8();
+ std::ptrdiff_t second = this->_io_dev.read_uint8();
+ stream_pos += 2;
+
+ if ( count )
+ {
+ // encoded mode
+
+ // clamp to boundary
+ if( count > dst_end - dst_it )
+ {
+ count = dst_end - dst_it;
+ }
+
+ if( this->_info._compression == bmp_compression::_rle4 )
+ {
+ std::ptrdiff_t cs[2] = { second >> 4, second & 0x0f };
+
+ for( int i = 0; i < count; ++i )
+ {
+ *dst_it++ = this->_palette[ cs[i & 1] ];
+ }
+ }
+ else
+ {
+ for( int i = 0; i < count; ++i )
+ {
+ *dst_it++ = this->_palette[ second ];
+ }
+ }
+ }
+ else
+ {
+ switch( second )
+ {
+ case 0: // end of row
+ {
+ copy_row_if_needed( buf, view, y );
+
+ y += yinc;
+ if( y == yend )
+ {
+ finished = true;
+ }
+ else
+ {
+ dst_it = buf.begin();
+ dst_end = buf.end();
+ }
+
+ break;
+ }
+
+ case 1: // end of bitmap
+ {
+ copy_row_if_needed( buf, view, y );
+ finished = true;
+
+ break;
+ }
+
+ case 2: // offset coordinates
+ {
+ std::ptrdiff_t dx = this->_io_dev.read_uint8();
+ std::ptrdiff_t dy = this->_io_dev.read_uint8() * yinc;
+ stream_pos += 2;
+
+ if( dy )
+ {
+ copy_row_if_needed( buf, view, y );
+ }
+
+ std::ptrdiff_t x = dst_it - buf.begin();
+ x += dx;
+
+ if( x > this->_info._width )
+ {
+ io_error( "Mangled BMP file." );
+ }
+
+ y += dy;
+ if( yinc > 0 ? y > yend : y < yend )
+ {
+ io_error( "Mangled BMP file." );
+ }
+
+ dst_it = buf.begin() + x;
+ dst_end = buf.end();
+
+ break;
+ }
+
+ default: // absolute mode
+ {
+ count = second;
+
+ // clamp to boundary
+ if( count > dst_end - dst_it )
+ {
+ count = dst_end - dst_it;
+ }
+
+ if ( this->_info._compression == bmp_compression::_rle4 )
+ {
+ for( int i = 0; i < count; ++i )
+ {
+ uint8_t packed_indices = this->_io_dev.read_uint8();
+ ++stream_pos;
+
+ *dst_it++ = this->_palette[ packed_indices >> 4 ];
+ if( ++i == second )
+ break;
+
+ *dst_it++ = this->_palette[ packed_indices & 0x0f ];
+ }
+ }
+ else
+ {
+ for( int i = 0; i < count; ++i )
+ {
+ uint8_t c = this->_io_dev.read_uint8();
+ ++stream_pos;
+ *dst_it++ = this->_palette[ c ];
+ }
+ }
+
+ // pad to word boundary
+ if( ( stream_pos - get_offset( 0 )) & 1 )
+ {
+ this->_io_dev.seek( 1, SEEK_CUR );
+ ++stream_pos;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+ }
+
+private:
+
+ std::size_t _pitch;
+};
+
+namespace detail {
+
+class bmp_type_format_checker
+{
+public:
+
+ bmp_type_format_checker( const bmp_bits_per_pixel::type& bpp )
+ : _bpp( bpp )
+ {}
+
+ template< typename Image >
+ bool apply()
+ {
+ if( _bpp < 32 )
+ {
+ return pixels_are_compatible< typename Image::value_type, rgb8_pixel_t >::value
+ ? true
+ : false;
+ }
+ else
+ {
+ return pixels_are_compatible< typename Image::value_type, rgba8_pixel_t >::value
+ ? true
+ : false;
+ }
+ }
+
+private:
+
+ // to avoid C4512
+ bmp_type_format_checker& operator=( const bmp_type_format_checker& ) { return *this; }
+
+private:
+
+ const bmp_bits_per_pixel::type _bpp;
+};
+
+struct bmp_read_is_supported
+{
+ template< typename View >
+ struct apply : public is_read_supported< typename get_pixel_type< View >::type
+ , bmp_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+///
+/// BMP Dynamic Reader
+///
+template< typename Device >
+class dynamic_image_reader< Device
+ , bmp_tag
+ >
+ : public reader< Device
+ , bmp_tag
+ , detail::read_and_no_convert
+ >
+{
+ typedef reader< Device
+ , bmp_tag
+ , detail::read_and_no_convert
+ > parent_t;
+
+public:
+
+ dynamic_image_reader( const Device& io_dev
+ , const image_read_settings< bmp_tag >& settings
+ )
+ : parent_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename Images >
+ void apply( any_image< Images >& images )
+ {
+ detail::bmp_type_format_checker format_checker( this->_info._bits_per_pixel );
+
+ if( !construct_matched( images
+ , format_checker
+ ))
+ {
+ io_error( "No matching image type between those of the given any_image and that of the file" );
+ }
+ else
+ {
+ this->init_image( images
+ , this->_settings
+ );
+
+ detail::dynamic_io_fnobj< detail::bmp_read_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( view( images )
+ , op
+ );
+ }
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/detail/reader_backend.hpp b/boost/gil/extension/io/bmp/detail/reader_backend.hpp
new file mode 100644
index 0000000000..589a5e3c4f
--- /dev/null
+++ b/boost/gil/extension/io/bmp/detail/reader_backend.hpp
@@ -0,0 +1,258 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_READER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_READER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/bmp/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+/// Color channel mask
+struct bit_field
+{
+ unsigned int mask; // Bit mask at corresponding position
+ unsigned int width; // Bit width of the mask
+ unsigned int shift; // Bit position from right to left
+};
+
+/// BMP color masks
+struct color_mask
+{
+ bit_field red; // Red bits
+ bit_field green; // Green bits
+ bit_field blue; // Blue bits
+};
+
+
+///
+/// BMP Backend
+///
+template< typename Device >
+struct reader_backend< Device
+ , bmp_tag
+ >
+{
+public:
+
+ typedef bmp_tag format_tag_t;
+
+public:
+
+ reader_backend( const Device& io_dev
+ , const image_read_settings< bmp_tag >& settings
+ )
+ : _io_dev ( io_dev )
+ , _settings( settings )
+ , _info()
+ , _scanline_length( 0 )
+ , _palette()
+ {
+ read_header();
+
+ if( _settings._dim.x == 0 )
+ {
+ _settings._dim.x = _info._width;
+ }
+
+ if( _settings._dim.y == 0 )
+ {
+ _settings._dim.y = _info._height;
+ }
+ }
+
+ void read_header()
+ {
+ // the magic number used to identify the BMP file:
+ // 0x42 0x4D (ASCII code points for B and M)
+ if( _io_dev.read_uint16() == 0x424D )
+ {
+ io_error( "Wrong magic number for bmp file." );
+ }
+
+ // the size of the BMP file in bytes
+ _io_dev.read_uint32();
+
+ // reserved; actual value depends on the application that creates the image
+ _io_dev.read_uint16();
+ // reserved; actual value depends on the application that creates the image
+ _io_dev.read_uint16();
+
+ _info._offset = _io_dev.read_uint32();
+
+
+ // bitmap information
+
+ // the size of this header ( 40 bytes )
+ _info._header_size = _io_dev.read_uint32();
+
+ if( _info._header_size == bmp_header_size::_win32_info_size )
+ {
+ _info._width = _io_dev.read_uint32();
+ _info._height = _io_dev.read_uint32();
+
+ if (_info._height < 0)
+ {
+ _info._height = -_info._height;
+ _info._top_down = true;
+ }
+
+ // the number of color planes being used. Must be set to 1.
+ _io_dev.read_uint16();
+
+ _info._bits_per_pixel = _io_dev.read_uint16();
+
+ _info._compression = _io_dev.read_uint32();
+
+ _info._image_size = _io_dev.read_uint32();
+
+ _info._horizontal_resolution = _io_dev.read_uint32();
+ _info._vertical_resolution = _io_dev.read_uint32();
+
+ _info._num_colors = _io_dev.read_uint32();
+ _info._num_important_colors = _io_dev.read_uint32();
+
+ }
+ else if( _info._header_size == bmp_header_size::_os2_info_size )
+ {
+ _info._width = static_cast< bmp_image_width::type >( _io_dev.read_uint16() );
+ _info._height = static_cast< bmp_image_height::type >( _io_dev.read_uint16() );
+
+ // the number of color planes being used. Must be set to 1.
+ _io_dev.read_uint16();
+
+ _info._bits_per_pixel = _io_dev.read_uint16();
+
+ _info._compression = bmp_compression::_rgb;
+
+ // not used
+ _info._image_size = 0;
+ _info._horizontal_resolution = 0;
+ _info._vertical_resolution = 0;
+ _info._num_colors = 0;
+ _info._num_important_colors = 0;
+ }
+ else if (_info._header_size > bmp_header_size::_win32_info_size)
+ {
+ // could be v4 or v5
+ // see MSDN: Bitmap Header Types ( BITMAPV4HEADER or BITMAPV5HEADER )
+
+ _info._width = _io_dev.read_uint32();
+ _info._height = _io_dev.read_uint32();
+
+ // the number of color planes being used. Must be set to 1.
+ _io_dev.read_uint16();
+
+ _info._bits_per_pixel = _io_dev.read_uint16();
+
+ _info._compression = _io_dev.read_uint32();
+
+ _info._image_size = _io_dev.read_uint32();
+
+ _info._horizontal_resolution = _io_dev.read_uint32();
+ _info._vertical_resolution = _io_dev.read_uint32();
+
+ _info._num_colors = _io_dev.read_uint32();
+ _info._num_important_colors = _io_dev.read_uint32();
+ }
+ else
+ {
+ io_error( "Invalid BMP info header." );
+ }
+
+ _info._valid = true;
+ }
+
+ void read_palette()
+ {
+ int entries = this->_info._num_colors;
+
+ if( entries == 0 )
+ {
+ entries = 1u << this->_info._bits_per_pixel;
+ }
+
+ _palette.resize( entries, rgba8_pixel_t(0, 0, 0, 0));
+
+ for( int i = 0; i < entries; ++i )
+ {
+ get_color( _palette[i], blue_t() ) = _io_dev.read_uint8();
+ get_color( _palette[i], green_t() ) = _io_dev.read_uint8();
+ get_color( _palette[i], red_t() ) = _io_dev.read_uint8();
+
+ // there are 4 entries when windows header
+ // but 3 for os2 header
+ if( _info._header_size == bmp_header_size::_win32_info_size )
+ {
+ _io_dev.read_uint8();
+ }
+
+ } // for
+ }
+
+ /// Check if image is large enough.
+ void check_image_size( const point_t& img_dim )
+ {
+ if( _settings._dim.x > 0 )
+ {
+ if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
+ }
+
+
+ if( _settings._dim.y > 0 )
+ {
+ if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
+ }
+ }
+
+public:
+
+ Device _io_dev;
+
+ image_read_settings< bmp_tag > _settings;
+ image_read_info< bmp_tag > _info;
+
+ std::size_t _scanline_length;
+
+ ///@todo make it an image.
+ std::vector< rgba8_pixel_t > _palette;
+
+ color_mask _mask;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/detail/scanline_read.hpp b/boost/gil/extension/io/bmp/detail/scanline_read.hpp
new file mode 100644
index 0000000000..fdc1e54f68
--- /dev/null
+++ b/boost/gil/extension/io/bmp/detail/scanline_read.hpp
@@ -0,0 +1,425 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_SCANLINE_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_SCANLINE_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 - 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/function.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/scanline_read_iterator.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/bmp/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/bmp/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+///
+/// BMP Scanline Reader
+///
+template< typename Device >
+class scanline_reader< Device
+ , bmp_tag
+ >
+ : public reader_backend< Device
+ , bmp_tag
+ >
+{
+public:
+
+ typedef bmp_tag tag_t;
+ typedef reader_backend < Device, tag_t > backend_t;
+ typedef scanline_reader< Device, tag_t > this_t;
+ typedef scanline_read_iterator< this_t > iterator_t;
+
+public:
+
+ //
+ // Constructor
+ //
+ scanline_reader( Device& device
+ , const image_read_settings< bmp_tag >& settings
+ )
+ : backend_t( device
+ , settings
+ )
+
+ , _pitch( 0 )
+ {
+ initialize();
+ }
+
+ /// Read part of image defined by View and return the data.
+ void read( byte_t* dst, int pos )
+ {
+ // jump to scanline
+ long offset = 0;
+
+ if( this->_info._height > 0 )
+ {
+ // the image is upside down
+ offset = this->_info._offset
+ + ( this->_info._height - 1 - pos ) * this->_pitch;
+ }
+ else
+ {
+ offset = this->_info._offset
+ + pos * _pitch;
+ }
+
+ this->_io_dev.seek( offset );
+
+
+ // read data
+ _read_function(this, dst);
+ }
+
+ /// Skip over a scanline.
+ void skip( byte_t*, int )
+ {
+ // nothing to do.
+ }
+
+ iterator_t begin() { return iterator_t( *this ); }
+ iterator_t end() { return iterator_t( *this, this->_info._height ); }
+
+private:
+
+ void initialize()
+ {
+ if( this->_info._bits_per_pixel < 8 )
+ {
+ _pitch = (( this->_info._width * this->_info._bits_per_pixel ) + 7 ) >> 3;
+ }
+ else
+ {
+ _pitch = this->_info._width * (( this->_info._bits_per_pixel + 7 ) >> 3);
+ }
+
+ _pitch = (_pitch + 3) & ~3;
+
+ //
+
+ switch( this->_info._bits_per_pixel )
+ {
+ case 1:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+
+ read_palette();
+ _buffer.resize( _pitch );
+
+ _read_function = boost::mem_fn( &this_t::read_1_bit_row );
+
+ break;
+ }
+
+ case 4:
+ {
+ switch( this->_info._compression )
+ {
+ case bmp_compression::_rle4:
+ {
+ io_error( "Cannot read run-length encoded images in iterator mode. Try to read as whole image." );
+
+ break;
+ }
+
+ case bmp_compression::_rgb :
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+
+ read_palette();
+ _buffer.resize( _pitch );
+
+ _read_function = boost::mem_fn( &this_t::read_4_bits_row );
+
+ break;
+ }
+
+ default:
+ {
+ io_error( "Unsupported compression mode in BMP file." );
+ }
+ }
+
+ break;
+ }
+
+ case 8:
+ {
+ switch( this->_info._compression )
+ {
+ case bmp_compression::_rle8:
+ {
+ io_error( "Cannot read run-length encoded images in iterator mode. Try to read as whole image." );
+
+ break;
+ }
+ case bmp_compression::_rgb:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+
+ read_palette();
+ _buffer.resize( _pitch );
+
+ _read_function = boost::mem_fn( &this_t::read_8_bits_row );
+
+ break;
+ }
+
+ default: { io_error( "Unsupported compression mode in BMP file." ); break; }
+ }
+
+ break;
+ }
+
+ case 15:
+ case 16:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgb8_view_t >::value + 3 ) & ~3;
+
+ _buffer.resize( _pitch );
+
+ if( this->_info._compression == bmp_compression::_bitfield )
+ {
+ this->_mask.red.mask = this->_io_dev.read_uint32();
+ this->_mask.green.mask = this->_io_dev.read_uint32();
+ this->_mask.blue.mask = this->_io_dev.read_uint32();
+
+ this->_mask.red.width = detail::count_ones( this->_mask.red.mask );
+ this->_mask.green.width = detail::count_ones( this->_mask.green.mask );
+ this->_mask.blue.width = detail::count_ones( this->_mask.blue.mask );
+
+ this->_mask.red.shift = detail::trailing_zeros( this->_mask.red.mask );
+ this->_mask.green.shift = detail::trailing_zeros( this->_mask.green.mask );
+ this->_mask.blue.shift = detail::trailing_zeros( this->_mask.blue.mask );
+ }
+ else if( this->_info._compression == bmp_compression::_rgb )
+ {
+ switch( this->_info._bits_per_pixel )
+ {
+ case 15:
+ case 16:
+ {
+ this->_mask.red.mask = 0x007C00; this->_mask.red.width = 5; this->_mask.red.shift = 10;
+ this->_mask.green.mask = 0x0003E0; this->_mask.green.width = 5; this->_mask.green.shift = 5;
+ this->_mask.blue.mask = 0x00001F; this->_mask.blue.width = 5; this->_mask.blue.shift = 0;
+
+ break;
+ }
+
+ case 24:
+ case 32:
+ {
+ this->_mask.red.mask = 0xFF0000; this->_mask.red.width = 8; this->_mask.red.shift = 16;
+ this->_mask.green.mask = 0x00FF00; this->_mask.green.width = 8; this->_mask.green.shift = 8;
+ this->_mask.blue.mask = 0x0000FF; this->_mask.blue.width = 8; this->_mask.blue.shift = 0;
+
+ break;
+ }
+ }
+ }
+ else
+ {
+ io_error( "Unsupported BMP compression." );
+ }
+
+
+ _read_function = boost::mem_fn( &this_t::read_15_bits_row );
+
+ break;
+ }
+
+ case 24:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgb8_view_t >::value + 3 ) & ~3;
+ _read_function = boost::mem_fn( &this_t::read_row );
+
+ break;
+ }
+
+ case 32:
+ {
+ this->_scanline_length = ( this->_info._width * num_channels< rgba8_view_t >::value + 3 ) & ~3;
+ _read_function = boost::mem_fn( &this_t::read_row );
+
+ break;
+ }
+
+ default:
+ {
+ io_error( "Unsupported bits per pixel." );
+ }
+ }
+ }
+
+ void read_palette()
+ {
+ if( this->_palette.size() > 0 )
+ {
+ // palette has been read already.
+ return;
+ }
+
+ int entries = this->_info._num_colors;
+
+ if( entries == 0 )
+ {
+ entries = 1u << this->_info._bits_per_pixel;
+ }
+
+ this->_palette.resize( entries, rgba8_pixel_t(0,0,0,0) );
+
+ for( int i = 0; i < entries; ++i )
+ {
+ get_color( this->_palette[i], blue_t() ) = this->_io_dev.read_uint8();
+ get_color( this->_palette[i], green_t() ) = this->_io_dev.read_uint8();
+ get_color( this->_palette[i], red_t() ) = this->_io_dev.read_uint8();
+
+ // there are 4 entries when windows header
+ // but 3 for os2 header
+ if( this->_info._header_size == bmp_header_size::_win32_info_size )
+ {
+ this->_io_dev.read_uint8();
+ }
+
+ } // for
+ }
+
+ template< typename View >
+ void read_bit_row( byte_t* dst )
+ {
+ typedef View src_view_t;
+ typedef rgba8_image_t::view_t dst_view_t;
+
+ src_view_t src_view = interleaved_view( this->_info._width
+ , 1
+ , (typename src_view_t::x_iterator) &_buffer.front()
+ , this->_pitch
+ );
+
+ dst_view_t dst_view = interleaved_view( this->_info._width
+ , 1
+ , (typename dst_view_t::value_type*) dst
+ , num_channels< dst_view_t >::value * this->_info._width
+ );
+
+
+ typename src_view_t::x_iterator src_it = src_view.row_begin( 0 );
+ typename dst_view_t::x_iterator dst_it = dst_view.row_begin( 0 );
+
+ for( dst_view_t::x_coord_t i = 0
+ ; i < this->_info._width
+ ; ++i, src_it++, dst_it++
+ )
+ {
+ unsigned char c = get_color( *src_it, gray_color_t() );
+ *dst_it = this->_palette[c];
+ }
+ }
+
+ // Read 1 bit image. The colors are encoded by an index.
+ void read_1_bit_row( byte_t* dst )
+ {
+ this->_io_dev.read( &_buffer.front(), _pitch );
+ _mirror_bits( _buffer );
+
+ read_bit_row< gray1_image_t::view_t >( dst );
+ }
+
+ // Read 4 bits image. The colors are encoded by an index.
+ void read_4_bits_row( byte_t* dst )
+ {
+ this->_io_dev.read( &_buffer.front(), _pitch );
+ _swap_half_bytes( _buffer );
+
+ read_bit_row< gray4_image_t::view_t >( dst );
+ }
+
+ /// Read 8 bits image. The colors are encoded by an index.
+ void read_8_bits_row( byte_t* dst )
+ {
+ this->_io_dev.read( &_buffer.front(), _pitch );
+
+ read_bit_row< gray8_image_t::view_t >( dst );
+ }
+
+ /// Read 15 or 16 bits image.
+ void read_15_bits_row( byte_t* dst )
+ {
+ typedef rgb8_view_t dst_view_t;
+
+ dst_view_t dst_view = interleaved_view( this->_info._width
+ , 1
+ , (typename dst_view_t::value_type*) dst
+ , this->_pitch
+ );
+
+ typename dst_view_t::x_iterator dst_it = dst_view.row_begin( 0 );
+
+ //
+ byte_t* src = &_buffer.front();
+ this->_io_dev.read( src, _pitch );
+
+ for( dst_view_t::x_coord_t i = 0
+ ; i < this->_info._width
+ ; ++i, src += 2
+ )
+ {
+ int p = ( src[1] << 8 ) | src[0];
+
+ int r = ((p & this->_mask.red.mask) >> this->_mask.red.shift) << (8 - this->_mask.red.width);
+ int g = ((p & this->_mask.green.mask) >> this->_mask.green.shift) << (8 - this->_mask.green.width);
+ int b = ((p & this->_mask.blue.mask) >> this->_mask.blue.shift) << (8 - this->_mask.blue.width);
+
+ get_color( dst_it[i], red_t() ) = static_cast< byte_t >( r );
+ get_color( dst_it[i], green_t() ) = static_cast< byte_t >( g );
+ get_color( dst_it[i], blue_t() ) = static_cast< byte_t >( b );
+ }
+ }
+
+ void read_row( byte_t* dst )
+ {
+ this->_io_dev.read( dst, _pitch );
+ }
+
+private:
+
+ // the row pitch must be multiple of 4 bytes
+ int _pitch;
+
+ std::vector< byte_t > _buffer;
+ detail::mirror_bits < std::vector< byte_t >, mpl::true_ > _mirror_bits;
+ detail::swap_half_bytes< std::vector< byte_t >, mpl::true_ > _swap_half_bytes;
+
+ boost::function< void ( this_t*, byte_t* ) > _read_function;
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/detail/supported_types.hpp b/boost/gil/extension/io/bmp/detail/supported_types.hpp
new file mode 100644
index 0000000000..89765594aa
--- /dev/null
+++ b/boost/gil/extension/io/bmp/detail/supported_types.hpp
@@ -0,0 +1,150 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_SUPPORTED_TYPES_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_SUPPORTED_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/gil/channel.hpp>
+#include <boost/gil/color_base.hpp>
+#include <boost/gil/bit_aligned_pixel_reference.hpp>
+#include <boost/gil/packed_pixel.hpp>
+
+#include <boost/gil/io/base.hpp>
+
+
+namespace boost { namespace gil { namespace detail {
+
+// Read support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct bmp_read_support : read_support_false
+{
+ static const bmp_bits_per_pixel::type bpp = 0;
+};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct bmp_read_support< packed_dynamic_channel_reference< BitField
+ , 1
+ , Mutable
+ >
+ , gray_t
+ > : read_support_true
+{
+ static const bmp_bits_per_pixel::type bpp = 1;
+};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct bmp_read_support< packed_dynamic_channel_reference< BitField
+ , 4
+ , Mutable
+ >
+ , gray_t
+ > : read_support_true
+{
+ static const bmp_bits_per_pixel::type bpp = 4;
+};
+
+
+template<>
+struct bmp_read_support<uint8_t
+ , gray_t
+ > : read_support_true
+{
+ static const bmp_bits_per_pixel::type bpp = 8;
+};
+
+
+
+template<>
+struct bmp_read_support<uint8_t
+ , rgb_t
+ > : read_support_true
+{
+ static const bmp_bits_per_pixel::type bpp = 24;
+};
+
+
+template<>
+struct bmp_read_support<uint8_t
+ , rgba_t
+ > : read_support_true
+{
+ static const bmp_bits_per_pixel::type bpp = 32;
+};
+
+
+// Write support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct bmp_write_support : write_support_false
+{};
+
+template<>
+struct bmp_write_support<uint8_t
+ , rgb_t
+ > : write_support_true {};
+
+template<>
+struct bmp_write_support<uint8_t
+ , rgba_t
+ > : write_support_true {};
+
+} // namespace detail
+
+
+template< typename Pixel >
+struct is_read_supported< Pixel
+ , bmp_tag
+ >
+ : mpl::bool_< detail::bmp_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ >
+{
+ typedef detail::bmp_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ > parent_t;
+
+ static const typename bmp_bits_per_pixel::type bpp = parent_t::bpp;
+};
+
+template< typename Pixel >
+struct is_write_supported< Pixel
+ , bmp_tag
+ >
+ : mpl::bool_< detail::bmp_write_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ > {};
+
+} // namespace gil
+} // namespace boost
+
+
+#endif
diff --git a/boost/gil/extension/io/bmp/detail/write.hpp b/boost/gil/extension/io/bmp/detail/write.hpp
new file mode 100644
index 0000000000..08ea24bae0
--- /dev/null
+++ b/boost/gil/extension/io/bmp/detail/write.hpp
@@ -0,0 +1,230 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+
+#include <boost/gil/extension/io/bmp/tags.hpp>
+
+#include <boost/gil/extension/io/bmp/detail/writer_backend.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+namespace detail {
+
+struct bmp_write_is_supported
+{
+ template< typename View >
+ struct apply
+ : public is_write_supported< typename get_pixel_type< View >::type
+ , bmp_tag
+ >
+ {};
+};
+
+template < int N > struct get_bgr_cs {};
+template <> struct get_bgr_cs< 1 > { typedef gray8_view_t type; };
+template <> struct get_bgr_cs< 3 > { typedef bgr8_view_t type; };
+template <> struct get_bgr_cs< 4 > { typedef bgra8_view_t type; };
+
+} // namespace detail
+
+///
+/// BMP Writer
+///
+template< typename Device >
+class writer< Device
+ , bmp_tag
+ >
+ : public writer_backend< Device
+ , bmp_tag
+ >
+{
+public:
+
+ writer( const Device& io_dev
+ , const image_write_info< bmp_tag >& info
+ )
+ : backend_t( io_dev
+ , info
+ )
+ {}
+
+ template<typename View>
+ void apply( const View& view )
+ {
+ write( view );
+ }
+
+private:
+
+ typedef writer_backend< Device, bmp_tag > backend_t;
+
+ template< typename View >
+ void write( const View& view )
+ {
+ // typedef typename channel_type<
+ // typename get_pixel_type< View >::type >::type channel_t;
+
+ // typedef typename color_space_type< View >::type color_space_t;
+
+ // check if supported
+/*
+ /// todo
+ if( bmp_read_write_support_private<channel_t, color_space_t>::channel != 8)
+ {
+ io_error("Input view type is incompatible with the image type");
+ }
+*/
+
+ // compute the file size
+ int bpp = num_channels< View >::value * 8;
+ int entries = 0;
+
+/*
+ /// @todo: Not supported for now. bit_aligned_images refer to indexed images
+ /// in this context.
+ if( bpp <= 8 )
+ {
+ entries = 1u << bpp;
+ }
+*/
+
+ std::size_t spn = ( view.width() * num_channels< View >::value + 3 ) & ~3;
+ std::size_t ofs = bmp_header_size::_size
+ + bmp_header_size::_win32_info_size
+ + entries * 4;
+
+ std::size_t siz = ofs + spn * view.height();
+
+ // write the BMP file header
+ this->_io_dev.write_uint16( bmp_signature );
+ this->_io_dev.write_uint32( (uint32_t) siz );
+ this->_io_dev.write_uint16( 0 );
+ this->_io_dev.write_uint16( 0 );
+ this->_io_dev.write_uint32( (uint32_t) ofs );
+
+ // writes Windows information header
+ this->_io_dev.write_uint32( bmp_header_size::_win32_info_size );
+ this->_io_dev.write_uint32( static_cast< uint32_t >( view.width() ));
+ this->_io_dev.write_uint32( static_cast< uint32_t >( view.height() ));
+ this->_io_dev.write_uint16( 1 );
+ this->_io_dev.write_uint16( static_cast< uint16_t >( bpp ));
+ this->_io_dev.write_uint32( bmp_compression::_rgb );
+ this->_io_dev.write_uint32( 0 );
+ this->_io_dev.write_uint32( 0 );
+ this->_io_dev.write_uint32( 0 );
+ this->_io_dev.write_uint32( entries );
+ this->_io_dev.write_uint32( 0 );
+
+ write_image< View
+ , typename detail::get_bgr_cs< num_channels< View >::value >::type
+ >( view, spn );
+ }
+
+
+ template< typename View
+ , typename BMP_View
+ >
+ void write_image( const View& view
+ , const std::size_t spn
+ )
+ {
+ byte_vector_t buffer( spn );
+ std::fill( buffer.begin(), buffer.end(), 0 );
+
+
+ BMP_View row = interleaved_view( view.width()
+ , 1
+ , (typename BMP_View::value_type*) &buffer.front()
+ , spn
+ );
+
+ for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
+ {
+ copy_pixels( subimage_view( view
+ , 0
+ , (int) y
+ , (int) view.width()
+ , 1
+ )
+ , row
+ );
+
+ this->_io_dev.write( &buffer.front(), spn );
+ }
+
+ }
+};
+
+///
+/// BMP Dynamic Image Writer
+///
+template< typename Device >
+class dynamic_image_writer< Device
+ , bmp_tag
+ >
+ : public writer< Device
+ , bmp_tag
+ >
+{
+ typedef writer< Device
+ , bmp_tag
+ > parent_t;
+
+public:
+
+ dynamic_image_writer( const Device& io_dev
+ , const image_write_info< bmp_tag >& info
+ )
+ : parent_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename Views >
+ void apply( const any_image_view< Views >& views )
+ {
+ detail::dynamic_io_fnobj< detail::bmp_write_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( views
+ , op
+ );
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/detail/writer_backend.hpp b/boost/gil/extension/io/bmp/detail/writer_backend.hpp
new file mode 100644
index 0000000000..a5147859f8
--- /dev/null
+++ b/boost/gil/extension/io/bmp/detail/writer_backend.hpp
@@ -0,0 +1,66 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_DETAIL_WRITER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/bmp/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// BMP Writer Backend
+///
+template< typename Device >
+struct writer_backend< Device
+ , bmp_tag
+ >
+{
+public:
+
+ typedef bmp_tag format_tag_t;
+
+public:
+
+ writer_backend( const Device& io_dev
+ , const image_write_info< bmp_tag >& info
+ )
+ : _io_dev( io_dev )
+ , _info ( info )
+ {}
+
+public:
+
+ Device _io_dev;
+
+ image_write_info< bmp_tag > _info;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/old.hpp b/boost/gil/extension/io/bmp/old.hpp
new file mode 100644
index 0000000000..b265ca1960
--- /dev/null
+++ b/boost/gil/extension/io/bmp/old.hpp
@@ -0,0 +1,181 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_OLD_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_OLD_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/bmp.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup BMP_IO
+/// \brief Returns the width and height of the BMP file at the specified location.
+/// Throws std::ios_base::failure if the location does not correspond to a valid BMP file
+template< typename String >
+inline
+point2< std::ptrdiff_t > bmp_read_dimensions( const String& filename )
+{
+ typedef typename get_reader_backend< String
+ , bmp_tag
+ >::type backend_t;
+
+ backend_t backend = read_image_info( filename
+ , bmp_tag()
+ );
+
+ return point2< std::ptrdiff_t >( backend._info._width
+ , backend._info._height
+ );
+}
+
+
+/// \ingroup BMP_IO
+/// \brief Loads the image specified by the given bmp image file name into the given view.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the BMP library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its color space or channel depth are not
+/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void bmp_read_view( const String& filename
+ , const View& view
+ )
+{
+ read_view( filename
+ , view
+ , bmp_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Allocates a new image whose dimensions are determined by the given bmp image file, and loads the pixels into it.
+/// Triggers a compile assert if the image color space or channel depth are not supported by the BMP library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its color space or channel depth are not
+/// compatible with the ones specified by Image
+template< typename String
+ , typename Image
+ >
+inline
+void bmp_read_image( const String& filename
+ , Image& img
+ )
+{
+ read_image( filename
+ , img
+ , bmp_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Loads and color-converts the image specified by the given bmp image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ , typename CC
+ >
+inline
+void bmp_read_and_convert_view( const String& filename
+ , const View& view
+ , CC cc
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , cc
+ , bmp_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Loads and color-converts the image specified by the given bmp image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void bmp_read_and_convert_view( const String& filename
+ , const View& view
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , bmp_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Allocates a new image whose dimensions are determined by the given bmp image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid BMP file
+template< typename String
+ , typename Image
+ , typename CC
+ >
+inline
+void bmp_read_and_convert_image( const String& filename
+ , Image& img
+ , CC cc
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , cc
+ , bmp_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Allocates a new image whose dimensions are determined by the given bmp image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid BMP file
+template< typename String
+ , typename Image
+ >
+inline
+void bmp_read_and_convert_image( const String filename
+ , Image& img
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , bmp_tag()
+ );
+}
+
+
+/// \ingroup BMP_IO
+/// \brief Saves the view to a bmp file specified by the given bmp image file name.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the BMP library or by the I/O extension.
+/// Throws std::ios_base::failure if it fails to create the file.
+template< typename String
+ , typename View
+ >
+inline
+void bmp_write_view( const String& filename
+ , const View& view
+ )
+{
+ write_view( filename
+ , view
+ , bmp_tag()
+ );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/read.hpp b/boost/gil/extension/io/bmp/read.hpp
new file mode 100644
index 0000000000..e28c169bdf
--- /dev/null
+++ b/boost/gil/extension/io/bmp/read.hpp
@@ -0,0 +1,43 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_READ_HPP
+
+#define BOOST_GIL_EXTENSION_IO_BMP_READ_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/bmp/tags.hpp>
+#include <boost/gil/extension/io/bmp/detail/supported_types.hpp>
+#include <boost/gil/extension/io/bmp/detail/read.hpp>
+#include <boost/gil/extension/io/bmp/detail/scanline_read.hpp>
+
+#include <boost/gil/io/get_reader.hpp>
+#include <boost/gil/io/make_backend.hpp>
+#include <boost/gil/io/make_reader.hpp>
+#include <boost/gil/io/make_dynamic_image_reader.hpp>
+#include <boost/gil/io/make_scanline_reader.hpp>
+
+#include <boost/gil/io/read_image.hpp>
+#include <boost/gil/io/read_view.hpp>
+#include <boost/gil/io/read_image_info.hpp>
+#include <boost/gil/io/read_and_convert_image.hpp>
+#include <boost/gil/io/read_and_convert_view.hpp>
+
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/bmp/tags.hpp b/boost/gil/extension/io/bmp/tags.hpp
new file mode 100644
index 0000000000..ec8c4a15f8
--- /dev/null
+++ b/boost/gil/extension/io/bmp/tags.hpp
@@ -0,0 +1,170 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_TAGS_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_TAGS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil {
+
+/// Defines bmp tag.
+struct bmp_tag : format_tag {};
+
+ /// See http://en.wikipedia.org/wiki/BMP_file_format#BMP_File_Header for reference.
+
+/// Defines type for offset value.
+struct bmp_offset : property_base< uint32_t > {};
+
+/// Defines type for header sizes.
+struct bmp_header_size : property_base< uint32_t >
+{
+ static const type _size = 14; /// Constant size for bmp file header size.
+ static const type _win32_info_size = 40; /// Constant size for win32 bmp info header size.
+ static const type _os2_info_size = 12; /// Constant size for os2 bmp info header size.
+};
+
+/// Defines type for image width property.
+struct bmp_image_width : property_base< int32_t > {};
+
+/// Defines type for image height property.
+struct bmp_image_height : property_base< int32_t > {};
+
+/// Defines type for bits per pixels property.
+struct bmp_bits_per_pixel : property_base< uint16_t > {};
+
+/// Defines type for compression property.
+struct bmp_compression : property_base< uint32_t >
+{
+ static const type _rgb = 0; /// RGB without compression
+ static const type _rle8 = 1; /// 8 bit index with RLE compression
+ static const type _rle4 = 2; /// 4 bit index with RLE compression
+ static const type _bitfield = 3; /// 16 or 32 bit fields without compression
+};
+
+/// Defines type for image size property.
+struct bmp_image_size : property_base< uint32_t > {};
+
+/// Defines type for horizontal resolution property.
+struct bmp_horizontal_resolution : property_base< int32_t > {};
+
+/// Defines type for vertical resolution property.
+struct bmp_vertical_resolution : property_base< int32_t > {};
+
+/// Defines type for number of colors property.
+struct bmp_num_colors : property_base< uint32_t > {};
+
+/// Defines type for important number of colors property.
+struct bmp_num_important_colors : property_base< uint32_t > {};
+
+/// if height is negative then image is stored top-down instead of bottom-up.
+struct bmp_top_down : property_base< bool > {};
+
+static const uint32_t bmp_signature = 0x4D42; /// Constant signature for bmp file format.
+
+/// Read information for bmp images.
+///
+/// The structure is returned when using read_image_info.
+template<>
+struct image_read_info< bmp_tag >
+{
+ /// Default contructor.
+ image_read_info< bmp_tag >()
+ : _top_down(false)
+ , _valid( false )
+ {}
+
+ /// The offset, i.e. starting address, of the byte where the bitmap data can be found.
+ bmp_offset::type _offset;
+
+ /// The size of this header:
+ /// - 40 bytes for Windows V3 header
+ /// - 12 bytes for OS/2 V1 header
+ bmp_header_size::type _header_size;
+
+ /// The bitmap width in pixels ( signed integer ).
+ bmp_image_width::type _width;
+
+ /// The bitmap height in pixels ( signed integer ).
+ bmp_image_height::type _height;
+
+ /// The number of bits per pixel, which is the color depth of the image.
+ /// Typical values are 1, 4, 8, 16, 24 and 32.
+ bmp_bits_per_pixel::type _bits_per_pixel;
+
+ /// The compression method being used. See above for a list of possible values.
+ bmp_compression::type _compression;
+
+ /// The image size. This is the size of the raw bitmap data (see below),
+ /// and should not be confused with the file size.
+ bmp_image_size::type _image_size;
+
+ /// The horizontal resolution of the image. (pixel per meter, signed integer)
+ bmp_horizontal_resolution::type _horizontal_resolution;
+
+ /// The vertical resolution of the image. (pixel per meter, signed integer)
+ bmp_vertical_resolution::type _vertical_resolution;
+
+ /// The number of colors in the color palette, or 0 to default to 2^n - 1.
+ bmp_num_colors::type _num_colors;
+
+ /// The number of important colors used, or 0 when every color is important;
+ /// generally ignored.
+ bmp_num_important_colors::type _num_important_colors;
+
+ bmp_top_down::type _top_down;
+
+ /// Used internaly to identify is the header has been read.
+ bool _valid;
+};
+
+/// Read settings for bmp images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< bmp_tag > : public image_read_settings_base
+{
+ /// Default constructor
+ image_read_settings()
+ : image_read_settings_base()
+ {}
+
+ /// Constructor
+ /// \param top_left Top left coordinate for reading partial image.
+ /// \param dim Dimensions for reading partial image.
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ {}
+};
+
+/// Write information for bmp images.
+///
+/// The structure can be used for write_view() function.
+template<>
+struct image_write_info< bmp_tag >
+{
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/bmp/write.hpp b/boost/gil/extension/io/bmp/write.hpp
new file mode 100644
index 0000000000..634bf3bd89
--- /dev/null
+++ b/boost/gil/extension/io/bmp/write.hpp
@@ -0,0 +1,31 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_BMP_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_BMP_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/bmp/tags.hpp>
+#include <boost/gil/extension/io/bmp/detail/supported_types.hpp>
+#include <boost/gil/extension/io/bmp/detail/write.hpp>
+
+#include <boost/gil/io/make_writer.hpp>
+#include <boost/gil/io/make_dynamic_image_writer.hpp>
+
+#include <boost/gil/io/write_view.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/io_error.hpp b/boost/gil/extension/io/io_error.hpp
deleted file mode 100644
index 5ea79c58f6..0000000000
--- a/boost/gil/extension/io/io_error.hpp
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/jpeg.hpp b/boost/gil/extension/io/jpeg.hpp
new file mode 100644
index 0000000000..8f4b5db410
--- /dev/null
+++ b/boost/gil/extension/io/jpeg.hpp
@@ -0,0 +1,25 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/jpeg/read.hpp>
+#include <boost/gil/extension/io/jpeg/write.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/base.hpp b/boost/gil/extension/io/jpeg/detail/base.hpp
new file mode 100644
index 0000000000..551c4759d1
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/base.hpp
@@ -0,0 +1,46 @@
+/*
+ Copyright 2010 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_BASE_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_BASE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+#include <boost/gil/extension/io/jpeg/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4324) //structure was padded due to __declspec(align())
+#endif
+
+class jpeg_io_base
+{
+
+protected:
+
+ jpeg_error_mgr _jerr;
+ jmp_buf _mark;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/is_allowed.hpp b/boost/gil/extension/io/jpeg/detail/is_allowed.hpp
new file mode 100644
index 0000000000..cf8015492e
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/is_allowed.hpp
@@ -0,0 +1,54 @@
+/*
+ Copyright 2009 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_IS_ALLOWED_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_IS_ALLOWED_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil { namespace detail {
+
+template< typename View >
+bool is_allowed( const image_read_info< jpeg_tag >& info
+ , mpl::true_ // is read_and_no_convert
+ )
+{
+ if( info._color_space == JCS_YCbCr )
+ {
+ // We read JCS_YCbCr files as rgb.
+ return ( is_read_supported< typename View::value_type
+ , jpeg_tag
+ >::_color_space == JCS_RGB );
+ }
+
+ return ( is_read_supported< typename View::value_type
+ , jpeg_tag
+ >::_color_space == info._color_space );
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< jpeg_tag >& /* info */
+ , mpl::false_ // is read_and_convert
+ )
+{
+ return true;
+}
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/read.hpp b/boost/gil/extension/io/jpeg/detail/read.hpp
new file mode 100644
index 0000000000..f3f5a8afef
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/read.hpp
@@ -0,0 +1,331 @@
+/*
+ Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <csetjmp>
+#include <vector>
+#include <boost/gil/extension/io/jpeg/tags.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/jpeg/detail/base.hpp>
+#include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+///
+/// JPEG Reader
+///
+template< typename Device
+ , typename ConversionPolicy
+ >
+class reader< Device
+ , jpeg_tag
+ , ConversionPolicy
+ >
+ : public reader_base< jpeg_tag
+ , ConversionPolicy
+ >
+ , public reader_backend< Device
+ , jpeg_tag
+ >
+{
+private:
+
+ typedef reader< Device
+ , jpeg_tag
+ , ConversionPolicy
+ > this_t;
+
+ typedef typename ConversionPolicy::color_converter_type cc_t;
+
+public:
+
+ typedef reader_backend< Device, jpeg_tag > backend_t;
+
+public:
+
+ //
+ // Constructor
+ //
+ reader( const Device& io_dev
+ , const image_read_settings< jpeg_tag >& settings
+ )
+ : reader_base< jpeg_tag
+ , ConversionPolicy
+ >()
+
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ //
+ // Constructor
+ //
+ reader( const Device& io_dev
+ , const typename ConversionPolicy::color_converter_type& cc
+ , const image_read_settings< jpeg_tag >& settings
+ )
+ : reader_base< jpeg_tag
+ , ConversionPolicy
+ >( cc )
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ template<typename View>
+ void apply( const View& view )
+ {
+ // Fire exception in case of error.
+ if( setjmp( this->_mark ))
+ {
+ this->raise_error();
+ }
+
+ this->get()->dct_method = this->_settings._dct_method;
+
+ typedef typename is_same< ConversionPolicy
+ , detail::read_and_no_convert
+ >::type is_read_and_convert_t;
+
+ io_error_if( !detail::is_allowed< View >( this->_info
+ , is_read_and_convert_t()
+ )
+ , "Image types aren't compatible."
+ );
+
+ if( jpeg_start_decompress( this->get() ) == false )
+ {
+ io_error( "Cannot start decompression." );
+ }
+
+ switch( this->_info._color_space )
+ {
+ case JCS_GRAYSCALE:
+ {
+ this->_scanline_length = this->_info._width;
+ read_rows< gray8_pixel_t >( view );
+
+ break;
+ }
+
+ case JCS_RGB:
+ //!\todo add Y'CbCr? We loose image quality when reading JCS_YCbCr as JCS_RGB
+ case JCS_YCbCr:
+ {
+ this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
+
+ read_rows< rgb8_pixel_t >( view );
+ break;
+ }
+
+ case JCS_CMYK:
+ //!\todo add Y'CbCrK? We loose image quality when reading JCS_YCCK as JCS_CMYK
+ case JCS_YCCK:
+ {
+ this->get()->out_color_space = JCS_CMYK;
+ this->_scanline_length = this->_info._width * num_channels< cmyk8_view_t >::value;
+
+ read_rows< cmyk8_pixel_t >( view );
+
+ break;
+ }
+ default: { io_error( "Unsupported jpeg color space." ); }
+ }
+
+ jpeg_finish_decompress ( this->get() );
+ }
+
+private:
+
+ template< typename ImagePixel
+ , typename View
+ >
+ void read_rows( const View& view )
+ {
+ typedef std::vector<ImagePixel> buffer_t;
+ buffer_t buffer( this->_info._width );
+
+ // In case of an error we'll jump back to here and fire an exception.
+ // @todo Is the buffer above cleaned up when the exception is thrown?
+ // The strategy right now is to allocate necessary memory before
+ // the setjmp.
+ if( setjmp( this->_mark ))
+ {
+ this->raise_error();
+ }
+
+
+ JSAMPLE *row_adr = reinterpret_cast< JSAMPLE* >( &buffer[0] );
+
+ //Skip scanlines if necessary.
+ for( int y = 0; y < this->_settings._top_left.y; ++y )
+ {
+ io_error_if( jpeg_read_scanlines( this->get()
+ , &row_adr
+ , 1
+ ) !=1
+ , "jpeg_read_scanlines: fail to read JPEG file"
+ );
+ }
+
+ // Read data.
+ for( int y = 0; y < view.height(); ++y )
+ {
+ io_error_if( jpeg_read_scanlines( this->get()
+ , &row_adr
+ , 1
+ ) != 1
+ , "jpeg_read_scanlines: fail to read JPEG file"
+ );
+
+ typename buffer_t::iterator beg = buffer.begin() + this->_settings._top_left.x;
+ typename buffer_t::iterator end = beg + this->_settings._dim.x;
+
+ this->_cc_policy.read( beg
+ , end
+ , view.row_begin( y )
+ );
+ }
+
+ //@todo: There might be a better way to do that.
+ while( this->get()->output_scanline < this->get()->image_height )
+ {
+ io_error_if( jpeg_read_scanlines( this->get()
+ , &row_adr
+ , 1
+ ) !=1
+ , "jpeg_read_scanlines: fail to read JPEG file"
+ );
+ }
+
+ }
+};
+
+namespace detail {
+
+struct jpeg_type_format_checker
+{
+ jpeg_type_format_checker( jpeg_color_space::type color_space )
+ : _color_space( color_space )
+ {}
+
+ template< typename Image >
+ bool apply()
+ {
+ return is_read_supported< typename get_pixel_type< typename Image::view_t >::type
+ , jpeg_tag
+ >::_color_space == _color_space;
+ }
+
+private:
+
+ jpeg_color_space::type _color_space;
+};
+
+struct jpeg_read_is_supported
+{
+ template< typename View >
+ struct apply : public is_read_supported< typename get_pixel_type< View >::type
+ , jpeg_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+///
+/// JPEG Dynamic Reader
+///
+template< typename Device >
+class dynamic_image_reader< Device
+ , jpeg_tag
+ >
+ : public reader< Device
+ , jpeg_tag
+ , detail::read_and_no_convert
+ >
+{
+ typedef reader< Device
+ , jpeg_tag
+ , detail::read_and_no_convert
+ > parent_t;
+
+public:
+
+ dynamic_image_reader( const Device& io_dev
+ , const image_read_settings< jpeg_tag >& settings
+ )
+ : parent_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename Images >
+ void apply( any_image< Images >& images )
+ {
+ detail::jpeg_type_format_checker format_checker( this->_info._color_space != JCS_YCbCr
+ ? this->_info._color_space
+ : JCS_RGB
+ );
+
+ if( !construct_matched( images
+ , format_checker
+ ))
+ {
+ io_error( "No matching image type between those of the given any_image and that of the file" );
+ }
+ else
+ {
+ this->init_image( images
+ , this->_settings
+ );
+
+ detail::dynamic_io_fnobj< detail::jpeg_read_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( view( images )
+ , op
+ );
+ }
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/reader_backend.hpp b/boost/gil/extension/io/jpeg/detail/reader_backend.hpp
new file mode 100644
index 0000000000..71c446af4f
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/reader_backend.hpp
@@ -0,0 +1,329 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_READER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/jpeg/tags.hpp>
+
+#include <memory>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+namespace detail {
+
+///
+/// Wrapper for libjpeg's decompress object. Implements value semantics.
+///
+struct jpeg_decompress_wrapper
+{
+protected:
+
+ using jpeg_decompress_ptr_t = std::shared_ptr<jpeg_decompress_struct> ;
+
+protected:
+
+ ///
+ /// Default Constructor
+ ///
+ jpeg_decompress_wrapper()
+ : _jpeg_decompress_ptr( new jpeg_decompress_struct()
+ , jpeg_decompress_deleter
+ )
+ {}
+
+ jpeg_decompress_struct* get() { return _jpeg_decompress_ptr.get(); }
+ const jpeg_decompress_struct* get() const { return _jpeg_decompress_ptr.get(); }
+
+private:
+
+ static void jpeg_decompress_deleter( jpeg_decompress_struct* jpeg_decompress_ptr )
+ {
+ if( jpeg_decompress_ptr )
+ {
+ jpeg_destroy_decompress( jpeg_decompress_ptr );
+
+ delete jpeg_decompress_ptr;
+ jpeg_decompress_ptr = NULL;
+ }
+ }
+
+private:
+
+ jpeg_decompress_ptr_t _jpeg_decompress_ptr;
+
+};
+
+} // namespace detail
+
+///
+/// JPEG Backend
+///
+template< typename Device >
+struct reader_backend< Device
+ , jpeg_tag
+ >
+ : public jpeg_io_base
+ , public detail::jpeg_decompress_wrapper
+{
+public:
+
+ typedef jpeg_tag format_tag_t;
+
+public:
+ //
+ // Constructor
+ //
+ reader_backend( const Device& io_dev
+ , const image_read_settings< jpeg_tag >& settings
+ )
+ : _io_dev( io_dev )
+ , _settings( settings )
+ , _info()
+
+ , _scanline_length( 0 )
+ {
+ get()->err = jpeg_std_error( &_jerr );
+ get()->client_data = this;
+
+ // Error exit handler: does not return to caller.
+ _jerr.error_exit = &reader_backend::error_exit;
+
+ if( setjmp( _mark ))
+ {
+ raise_error();
+ }
+
+ _src._jsrc.bytes_in_buffer = 0;
+ _src._jsrc.next_input_byte = buffer;
+ _src._jsrc.init_source = reinterpret_cast< void(*) ( j_decompress_ptr )>( &reader_backend< Device, jpeg_tag >::init_device );
+ _src._jsrc.fill_input_buffer = reinterpret_cast< boolean(*)( j_decompress_ptr )>( &reader_backend< Device, jpeg_tag >::fill_buffer );
+ _src._jsrc.skip_input_data = reinterpret_cast< void(*) ( j_decompress_ptr
+ , long num_bytes
+ ) >( &reader_backend< Device, jpeg_tag >::skip_input_data );
+ _src._jsrc.term_source = reinterpret_cast< void(*) ( j_decompress_ptr ) >( &reader_backend< Device, jpeg_tag >::close_device );
+ _src._jsrc.resync_to_restart = jpeg_resync_to_restart;
+ _src._this = this;
+
+ jpeg_create_decompress( get() );
+
+ get()->src = &_src._jsrc;
+
+ jpeg_read_header( get()
+ , TRUE
+ );
+
+ io_error_if( get()->data_precision != 8
+ , "Image file is not supported."
+ );
+
+ //
+ read_header();
+
+ //
+ if( _settings._dim.x == 0 )
+ {
+ _settings._dim.x = _info._width;
+ }
+
+ if( _settings._dim.y == 0 )
+ {
+ _settings._dim.y = _info._height;
+ }
+ }
+
+ /// Read image header.
+ void read_header()
+ {
+ _info._width = get()->image_width;
+ _info._height = get()->image_height;
+ _info._num_components = get()->num_components;
+ _info._color_space = get()->jpeg_color_space;
+ _info._data_precision = get()->data_precision;
+
+ _info._density_unit = get()->density_unit;
+ _info._x_density = get()->X_density;
+ _info._y_density = get()->Y_density;
+
+ // obtain real world dimensions
+ // taken from https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/read.cpp#cl-62
+
+ jpeg_calc_output_dimensions( get() );
+
+ double units_conversion = 0;
+ if (get()->density_unit == 1) // dots per inch
+ {
+ units_conversion = 25.4; // millimeters in an inch
+ }
+ else if (get()->density_unit == 2) // dots per cm
+ {
+ units_conversion = 10; // millimeters in a centimeter
+ }
+
+ _info._pixel_width_mm = get()->X_density ? (get()->output_width / double(get()->X_density)) * units_conversion : 0;
+ _info._pixel_height_mm = get()->Y_density ? (get()->output_height / double(get()->Y_density)) * units_conversion : 0;
+ }
+
+ /// Return image read settings.
+ const image_read_settings< jpeg_tag >& get_settings()
+ {
+ return _settings;
+ }
+
+ /// Return image header info.
+ const image_read_info< jpeg_tag >& get_info()
+ {
+ return _info;
+ }
+
+ /// Check if image is large enough.
+ void check_image_size( const point_t& img_dim )
+ {
+ if( _settings._dim.x > 0 )
+ {
+ if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( (jpeg_image_width::type) img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
+ }
+
+
+ if( _settings._dim.y > 0 )
+ {
+ if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( (jpeg_image_height::type) img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
+ }
+ }
+
+protected:
+
+ // Taken from jerror.c
+ /*
+ * Error exit handler: must not return to caller.
+ *
+ * Applications may override this if they want to get control back after
+ * an error. Typically one would longjmp somewhere instead of exiting.
+ * The setjmp buffer can be made a private field within an expanded error
+ * handler object. Note that the info needed to generate an error message
+ * is stored in the error object, so you can generate the message now or
+ * later, at your convenience.
+ * You should make sure that the JPEG object is cleaned up (with jpeg_abort
+ * or jpeg_destroy) at some point.
+ */
+ static void error_exit( j_common_ptr cinfo )
+ {
+ reader_backend< Device, jpeg_tag >* mgr = reinterpret_cast< reader_backend< Device, jpeg_tag >* >( cinfo->client_data );
+
+ longjmp( mgr->_mark, 1 );
+ }
+
+ void raise_error()
+ {
+ // we clean up in the destructor
+
+ io_error( "jpeg is invalid." );
+ }
+
+private:
+
+ // See jdatasrc.c for default implementation for the following static member functions.
+
+ static void init_device( jpeg_decompress_struct* cinfo )
+ {
+ gil_jpeg_source_mgr* src = reinterpret_cast< gil_jpeg_source_mgr* >( cinfo->src );
+ src->_jsrc.bytes_in_buffer = 0;
+ src->_jsrc.next_input_byte = src->_this->buffer;
+ }
+
+ static boolean fill_buffer( jpeg_decompress_struct* cinfo )
+ {
+ gil_jpeg_source_mgr* src = reinterpret_cast< gil_jpeg_source_mgr* >( cinfo->src );
+ size_t count = src->_this->_io_dev.read(src->_this->buffer, sizeof(src->_this->buffer) );
+
+ if( count <= 0 )
+ {
+ // libjpeg does that: adding an EOF marker
+ src->_this->buffer[0] = (JOCTET) 0xFF;
+ src->_this->buffer[1] = (JOCTET) JPEG_EOI;
+ count = 2;
+ }
+
+ src->_jsrc.next_input_byte = src->_this->buffer;
+ src->_jsrc.bytes_in_buffer = count;
+
+ return TRUE;
+ }
+
+ static void skip_input_data( jpeg_decompress_struct * cinfo, long num_bytes )
+ {
+ gil_jpeg_source_mgr* src = reinterpret_cast< gil_jpeg_source_mgr* >( cinfo->src );
+
+ if( num_bytes > 0 )
+ {
+ while( num_bytes > long( src->_jsrc.bytes_in_buffer ))
+ {
+ num_bytes -= (long) src->_jsrc.bytes_in_buffer;
+ fill_buffer( cinfo );
+ }
+
+ src->_jsrc.next_input_byte += num_bytes;
+ src->_jsrc.bytes_in_buffer -= num_bytes;
+ }
+ }
+
+ static void close_device( jpeg_decompress_struct* ) {}
+
+public:
+
+ Device _io_dev;
+
+ image_read_settings< jpeg_tag > _settings;
+ image_read_info< jpeg_tag > _info;
+
+ std::size_t _scanline_length;
+
+ struct gil_jpeg_source_mgr
+ {
+ jpeg_source_mgr _jsrc;
+ reader_backend* _this;
+ };
+
+ gil_jpeg_source_mgr _src;
+
+ // libjpeg default is 4096 - see jdatasrc.c
+ JOCTET buffer[4096];
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/scanline_read.hpp b/boost/gil/extension/io/jpeg/detail/scanline_read.hpp
new file mode 100644
index 0000000000..ee33154c61
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/scanline_read.hpp
@@ -0,0 +1,163 @@
+/*
+ Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SCANLINE_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SCANLINE_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <csetjmp>
+#include <vector>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/scanline_read_iterator.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+
+#include <boost/gil/extension/io/jpeg/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/jpeg/detail/base.hpp>
+#include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+///
+/// JPEG Scanline Reader
+///
+template< typename Device >
+class scanline_reader< Device
+ , jpeg_tag
+ >
+ : public reader_backend< Device
+ , jpeg_tag
+ >
+{
+public:
+
+ typedef jpeg_tag tag_t;
+ typedef reader_backend < Device, tag_t > backend_t;
+ typedef scanline_reader< Device, tag_t > this_t;
+ typedef scanline_read_iterator< this_t > iterator_t;
+
+public:
+ scanline_reader( Device& device
+ , const image_read_settings< jpeg_tag >& settings
+ )
+ : reader_backend< Device
+ , jpeg_tag
+ >( device
+ , settings
+ )
+ {
+ initialize();
+ }
+
+ void read( byte_t* dst
+ , int
+ )
+ {
+ // Fire exception in case of error.
+ if( setjmp( this->_mark )) { this->raise_error(); }
+
+ // read data
+ read_scanline( dst );
+ }
+
+ /// Skip over a scanline.
+ void skip( byte_t* dst, int )
+ {
+ // Fire exception in case of error.
+ if( setjmp( this->_mark )) { this->raise_error(); }
+
+ // read data
+ read_scanline( dst );
+ }
+
+ iterator_t begin() { return iterator_t( *this ); }
+ iterator_t end() { return iterator_t( *this, this->_info._height ); }
+
+private:
+
+ void initialize()
+ {
+ this->get()->dct_method = this->_settings._dct_method;
+
+ io_error_if( jpeg_start_decompress( this->get() ) == false
+ , "Cannot start decompression." );
+
+ switch( this->_info._color_space )
+ {
+ case JCS_GRAYSCALE:
+ {
+ this->_scanline_length = this->_info._width;
+
+ break;
+ }
+
+ case JCS_RGB:
+ //!\todo add Y'CbCr? We loose image quality when reading JCS_YCbCr as JCS_RGB
+ case JCS_YCbCr:
+ {
+ this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
+
+ break;
+ }
+
+
+ case JCS_CMYK:
+ //!\todo add Y'CbCrK? We loose image quality when reading JCS_YCCK as JCS_CMYK
+ case JCS_YCCK:
+ {
+ this->get()->out_color_space = JCS_CMYK;
+ this->_scanline_length = this->_info._width * num_channels< cmyk8_view_t >::value;
+
+ break;
+ }
+
+ default: { io_error( "Unsupported jpeg color space." ); }
+ }
+ }
+
+ void read_scanline( byte_t* dst )
+ {
+ JSAMPLE *row_adr = reinterpret_cast< JSAMPLE* >( dst );
+
+ // Read data.
+ io_error_if( jpeg_read_scanlines( this->get()
+ , &row_adr
+ , 1
+ ) != 1
+ , "jpeg_read_scanlines: fail to read JPEG file"
+ );
+
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/supported_types.hpp b/boost/gil/extension/io/jpeg/detail/supported_types.hpp
new file mode 100644
index 0000000000..209a99f857
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/supported_types.hpp
@@ -0,0 +1,121 @@
+/*
+ Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SUPPORTED_TYPES_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_SUPPORTED_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/gil/channel.hpp>
+#include <boost/gil/color_base.hpp>
+
+namespace boost { namespace gil { namespace detail {
+
+// Read support
+
+template< jpeg_color_space::type ColorSpace >
+struct jpeg_rw_support_base
+{
+ static const jpeg_color_space::type _color_space = ColorSpace;
+};
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct jpeg_read_support : read_support_false
+ , jpeg_rw_support_base< JCS_UNKNOWN > {};
+
+template<>
+struct jpeg_read_support<uint8_t
+ , rgb_t
+ > : read_support_true
+ , jpeg_rw_support_base< JCS_RGB > {};
+
+template<>
+struct jpeg_read_support<uint8_t
+ , cmyk_t
+ > : read_support_true
+ , jpeg_rw_support_base< JCS_CMYK > {};
+
+template<>
+struct jpeg_read_support<uint8_t
+ , gray_t
+ > : read_support_true
+ , jpeg_rw_support_base< JCS_GRAYSCALE > {};
+
+// Write support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct jpeg_write_support : write_support_false
+ , jpeg_rw_support_base< JCS_UNKNOWN > {};
+
+template<>
+struct jpeg_write_support<uint8_t
+ , gray_t
+ > : write_support_true
+ , jpeg_rw_support_base< JCS_GRAYSCALE > {};
+
+template<>
+struct jpeg_write_support<uint8_t
+ , rgb_t
+ > : write_support_true
+ , jpeg_rw_support_base< JCS_RGB > {};
+
+template<>
+struct jpeg_write_support<uint8_t
+ , cmyk_t
+ > : write_support_true
+ , jpeg_rw_support_base< JCS_CMYK > {};
+
+} // namespace detail
+
+template< typename Pixel >
+struct is_read_supported< Pixel
+ , jpeg_tag
+ >
+ : mpl::bool_< detail::jpeg_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ >
+{
+ typedef detail::jpeg_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ > parent_t;
+
+ static const typename jpeg_color_space::type _color_space = parent_t::_color_space;
+};
+
+template< typename Pixel >
+struct is_write_supported< Pixel
+ , jpeg_tag
+ >
+ : mpl::bool_< detail::jpeg_write_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ >
+{};
+
+
+} // namespace gil
+} // namespace boost
+
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/write.hpp b/boost/gil/extension/io/jpeg/detail/write.hpp
new file mode 100644
index 0000000000..f9d2abfb57
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/write.hpp
@@ -0,0 +1,194 @@
+/*
+ Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+
+#include <boost/gil/extension/io/jpeg/tags.hpp>
+
+#include <boost/gil/extension/io/jpeg/detail/supported_types.hpp>
+#include <boost/gil/extension/io/jpeg/detail/writer_backend.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+namespace detail {
+
+struct jpeg_write_is_supported
+{
+ template< typename View >
+ struct apply
+ : public is_write_supported< typename get_pixel_type< View >::type
+ , jpeg_tag
+ >
+ {};
+};
+
+} // detail
+
+///
+/// JPEG Writer
+///
+template< typename Device >
+class writer< Device
+ , jpeg_tag
+ >
+ : public writer_backend< Device
+ , jpeg_tag
+ >
+{
+public:
+
+ typedef writer_backend< Device
+ , jpeg_tag
+ > backend_t;
+
+public:
+
+ writer( const Device& io_dev
+ , const image_write_info< jpeg_tag >& info
+ )
+ : backend_t( io_dev
+ , info
+ )
+ {}
+
+ template<typename View>
+ void apply( const View& view )
+ {
+ write_rows( view );
+ }
+
+private:
+
+ template<typename View>
+ void write_rows( const View& view )
+ {
+ std::vector< pixel< typename channel_type< View >::type
+ , layout<typename color_space_type< View >::type >
+ >
+ > row_buffer( view.width() );
+
+ // In case of an error we'll jump back to here and fire an exception.
+ // @todo Is the buffer above cleaned up when the exception is thrown?
+ // The strategy right now is to allocate necessary memory before
+ // the setjmp.
+ if( setjmp( this->_mark )) { this->raise_error(); }
+
+ typedef typename channel_type< typename View::value_type >::type channel_t;
+
+ this->get()->image_width = JDIMENSION( view.width() );
+ this->get()->image_height = JDIMENSION( view.height() );
+ this->get()->input_components = num_channels<View>::value;
+ this->get()->in_color_space = detail::jpeg_write_support< channel_t
+ , typename color_space_type< View >::type
+ >::_color_space;
+
+ jpeg_set_defaults( this->get() );
+
+ jpeg_set_quality( this->get()
+ , this->_info._quality
+ , TRUE
+ );
+
+ // Needs to be done after jpeg_set_defaults() since it's overridding this value back to slow.
+ this->get()->dct_method = this->_info._dct_method;
+
+
+ // set the pixel dimensions
+ this->get()->density_unit = this->_info._density_unit;
+ this->get()->X_density = this->_info._x_density;
+ this->get()->Y_density = this->_info._y_density;
+
+ // done reading header information
+
+ jpeg_start_compress( this->get()
+ , TRUE
+ );
+
+ JSAMPLE* row_addr = reinterpret_cast< JSAMPLE* >( &row_buffer[0] );
+
+ for( int y =0; y != view.height(); ++ y )
+ {
+ std::copy( view.row_begin( y )
+ , view.row_end ( y )
+ , row_buffer.begin()
+ );
+
+ jpeg_write_scanlines( this->get()
+ , &row_addr
+ , 1
+ );
+ }
+ }
+};
+
+///
+/// JPEG Dyamic Image Writer
+///
+template< typename Device >
+class dynamic_image_writer< Device
+ , jpeg_tag
+ >
+ : public writer< Device
+ , jpeg_tag
+ >
+{
+ typedef writer< Device
+ , jpeg_tag
+ > parent_t;
+
+public:
+
+ dynamic_image_writer( const Device& io_dev
+ , const image_write_info< jpeg_tag >& info
+ )
+ : parent_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename Views >
+ void apply( const any_image_view< Views >& views )
+ {
+ detail::dynamic_io_fnobj< detail::jpeg_write_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( views, op );
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/detail/writer_backend.hpp b/boost/gil/extension/io/jpeg/detail/writer_backend.hpp
new file mode 100644
index 0000000000..962c46df69
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/detail/writer_backend.hpp
@@ -0,0 +1,203 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_DETAIL_WRITER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/jpeg/tags.hpp>
+#include <boost/gil/extension/io/jpeg/detail/base.hpp>
+
+#include <memory>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+namespace detail {
+
+///
+/// Wrapper for libjpeg's compress object. Implements value semantics.
+///
+struct jpeg_compress_wrapper
+{
+protected:
+
+ using jpeg_compress_ptr_t = std::shared_ptr<jpeg_compress_struct>;
+
+protected:
+
+ ///
+ /// Default Constructor
+ ///
+ jpeg_compress_wrapper()
+ : _jpeg_compress_ptr( new jpeg_compress_struct()
+ , jpeg_compress_deleter
+ )
+ {}
+
+ jpeg_compress_struct* get() { return _jpeg_compress_ptr.get(); }
+ const jpeg_compress_struct* get() const { return _jpeg_compress_ptr.get(); }
+
+private:
+
+ static void jpeg_compress_deleter( jpeg_compress_struct* jpeg_compress_ptr )
+ {
+ if( jpeg_compress_ptr )
+ {
+ jpeg_destroy_compress( jpeg_compress_ptr );
+
+ delete jpeg_compress_ptr;
+ jpeg_compress_ptr = NULL;
+ }
+ }
+
+private:
+
+ jpeg_compress_ptr_t _jpeg_compress_ptr;
+
+};
+
+} // namespace detail
+
+///
+/// JPEG Writer Backend
+///
+template< typename Device >
+struct writer_backend< Device
+ , jpeg_tag
+ >
+ : public jpeg_io_base
+ , public detail::jpeg_compress_wrapper
+{
+public:
+
+ typedef jpeg_tag format_tag_t;
+
+public:
+ ///
+ /// Constructor
+ ///
+ writer_backend( const Device& io_dev
+ , const image_write_info< jpeg_tag >& info
+ )
+ : _io_dev( io_dev )
+ , _info( info )
+ {
+ get()->err = jpeg_std_error( &_jerr );
+ get()->client_data = this;
+
+ // Error exit handler: does not return to caller.
+ _jerr.error_exit = &writer< Device, jpeg_tag >::error_exit;
+
+ // Fire exception in case of error.
+ if( setjmp( _mark )) { raise_error(); }
+
+ _dest._jdest.free_in_buffer = sizeof( buffer );
+ _dest._jdest.next_output_byte = buffer;
+ _dest._jdest.init_destination = reinterpret_cast< void(*) ( j_compress_ptr ) >( &writer< Device, jpeg_tag >::init_device );
+ _dest._jdest.empty_output_buffer = reinterpret_cast< boolean(*)( j_compress_ptr ) >( &writer< Device, jpeg_tag >::empty_buffer );
+ _dest._jdest.term_destination = reinterpret_cast< void(*) ( j_compress_ptr ) >( &writer< Device, jpeg_tag >::close_device );
+ _dest._this = this;
+
+ jpeg_create_compress( get() );
+ get()->dest = &_dest._jdest;
+ }
+
+ ~writer_backend()
+ {
+ jpeg_finish_compress ( get() );
+ jpeg_destroy_compress( get() );
+ }
+
+protected:
+
+ struct gil_jpeg_destination_mgr
+ {
+ jpeg_destination_mgr _jdest;
+ writer_backend< Device
+ , jpeg_tag
+ >* _this;
+ };
+
+ static void init_device( jpeg_compress_struct* cinfo )
+ {
+ gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
+
+ dest->_jdest.free_in_buffer = sizeof( dest->_this->buffer );
+ dest->_jdest.next_output_byte = dest->_this->buffer;
+ }
+
+ static boolean empty_buffer( jpeg_compress_struct* cinfo )
+ {
+ gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
+
+ dest->_this->_io_dev.write( dest->_this->buffer
+ , buffer_size
+ );
+
+ writer<Device,jpeg_tag>::init_device( cinfo );
+ return static_cast<boolean>(TRUE);
+ }
+
+ static void close_device( jpeg_compress_struct* cinfo )
+ {
+ writer_backend< Device
+ , jpeg_tag
+ >::empty_buffer( cinfo );
+
+ gil_jpeg_destination_mgr* dest = reinterpret_cast< gil_jpeg_destination_mgr* >( cinfo->dest );
+
+ dest->_this->_io_dev.flush();
+ }
+
+ void raise_error()
+ {
+ io_error( "Cannot write jpeg file." );
+ }
+
+ static void error_exit( j_common_ptr cinfo )
+ {
+ writer< Device, jpeg_tag >* mgr = reinterpret_cast< writer< Device, jpeg_tag >* >( cinfo->client_data );
+
+ longjmp( mgr->_mark, 1 );
+ }
+
+public:
+
+ Device _io_dev;
+
+ image_write_info< jpeg_tag > _info;
+
+ gil_jpeg_destination_mgr _dest;
+
+ static const unsigned int buffer_size = 1024;
+ JOCTET buffer[buffer_size];
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/old.hpp b/boost/gil/extension/io/jpeg/old.hpp
new file mode 100644
index 0000000000..3b3dd2a89b
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/old.hpp
@@ -0,0 +1,182 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_OLD_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_OLD_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/jpeg.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup JPEG_IO
+/// \brief Returns the width and height of the JPEG file at the specified location.
+/// Throws std::ios_base::failure if the location does not correspond to a valid JPEG file
+template< typename String >
+inline
+point2< std::ptrdiff_t > jpeg_read_dimensions( const String& filename )
+{
+ typedef typename get_reader_backend< String
+ , jpeg_tag
+ >::type backend_t;
+
+ backend_t backend = read_image_info( filename
+ , jpeg_tag()
+ );
+
+ return point2< std::ptrdiff_t >( backend._info._width
+ , backend._info._height
+ );
+}
+
+
+/// \ingroup JPEG_IO
+/// \brief Loads the image specified by the given jpeg image file name into the given view.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not
+/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void jpeg_read_view( const String& filename
+ , const View& view
+ )
+{
+ read_view( filename
+ , view
+ , jpeg_tag()
+ );
+}
+
+/// \ingroup JPEG_IO
+/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, and loads the pixels into it.
+/// Triggers a compile assert if the image color space or channel depth are not supported by the JPEG library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its color space or channel depth are not
+/// compatible with the ones specified by Image
+template< typename String
+ , typename Image
+ >
+inline
+void jpeg_read_image( const String& filename
+ , Image& img
+ )
+{
+ read_image( filename
+ , img
+ , jpeg_tag()
+ );
+}
+
+/// \ingroup JPEG_IO
+/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ , typename CC
+ >
+inline
+void jpeg_read_and_convert_view( const String& filename
+ , const View& view
+ , CC cc
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , cc
+ , jpeg_tag()
+ );
+}
+
+/// \ingroup JPEG_IO
+/// \brief Loads and color-converts the image specified by the given jpeg image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid JPEG file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void jpeg_read_and_convert_view( const String& filename
+ , const View& view
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , jpeg_tag()
+ );
+}
+
+/// \ingroup JPEG_IO
+/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid JPEG file
+template< typename String
+ , typename Image
+ , typename CC
+ >
+inline
+void jpeg_read_and_convert_image( const String& filename
+ , Image& img
+ , CC cc
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , cc
+ , jpeg_tag()
+ );
+}
+
+/// \ingroup JPEG_IO
+/// \brief Allocates a new image whose dimensions are determined by the given jpeg image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid JPEG file
+template< typename String
+ , typename Image
+ >
+inline
+void jpeg_read_and_convert_image( const String filename
+ , Image& img
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , jpeg_tag()
+ );
+}
+
+
+/// \ingroup JPEG_IO
+/// \brief Saves the view to a jpeg file specified by the given jpeg image file name.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the JPEG library or by the I/O extension.
+/// Throws std::ios_base::failure if it fails to create the file.
+template< typename String
+ , typename View
+ >
+inline
+void jpeg_write_view( const String& filename
+ , const View& view
+ , int quality = jpeg_quality::default_value
+ )
+{
+ write_view( filename
+ , view
+ , image_write_info< jpeg_tag >( quality )
+ );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/read.hpp b/boost/gil/extension/io/jpeg/read.hpp
new file mode 100644
index 0000000000..ada31ff5bf
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/read.hpp
@@ -0,0 +1,43 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_READ_HPP
+
+#define BOOST_GIL_EXTENSION_IO_JPEG_READ_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/jpeg/tags.hpp>
+#include <boost/gil/extension/io/jpeg/detail/supported_types.hpp>
+#include <boost/gil/extension/io/jpeg/detail/read.hpp>
+#include <boost/gil/extension/io/jpeg/detail/scanline_read.hpp>
+
+#include <boost/gil/io/get_reader.hpp>
+#include <boost/gil/io/make_backend.hpp>
+#include <boost/gil/io/make_reader.hpp>
+#include <boost/gil/io/make_dynamic_image_reader.hpp>
+#include <boost/gil/io/make_scanline_reader.hpp>
+
+#include <boost/gil/io/read_image.hpp>
+#include <boost/gil/io/read_view.hpp>
+#include <boost/gil/io/read_image_info.hpp>
+#include <boost/gil/io/read_and_convert_image.hpp>
+#include <boost/gil/io/read_and_convert_view.hpp>
+
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/tags.hpp b/boost/gil/extension/io/jpeg/tags.hpp
new file mode 100644
index 0000000000..047b5cbfd5
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/tags.hpp
@@ -0,0 +1,244 @@
+/*
+ Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_TAGS_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_TAGS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief All supported jpeg tags by the gil io extension.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#else
+ // DONT_USE_EXTERN_C introduced in v7 of the IJG library.
+ // By default the v7 IJG headers check for __cplusplus being defined and
+ // wrap the content in an 'extern "C"' block if it's present.
+ // When DONT_USE_EXTERN_C is defined, this wrapping is not performed.
+ #ifndef DONT_USE_EXTERN_C
+ #define DONT_USE_EXTERN_C 1
+ #endif
+#endif
+
+//jpeglib doesn't know about FILE
+#include <stdio.h>
+
+#include <jpeglib.h>
+#include <jerror.h>
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil {
+
+/// Defines jpeg tag.
+struct jpeg_tag : format_tag {};
+
+/// see http://en.wikipedia.org/wiki/JPEG for reference
+
+/// Defines type for image width property.
+struct jpeg_image_width : property_base< JDIMENSION > {};
+
+/// Defines type for image height property.
+struct jpeg_image_height : property_base< JDIMENSION > {};
+
+/// Defines type for number of components property.
+struct jpeg_num_components : property_base< int > {};
+
+/// Defines type for color space property.
+struct jpeg_color_space : property_base< J_COLOR_SPACE > {};
+
+/// Defines type for jpeg quality property.
+struct jpeg_quality : property_base< int >
+{
+ static const type default_value = 100;
+};
+
+/// Defines type for data precision property.
+struct jpeg_data_precision : property_base< int > {};
+
+/// JFIF code for pixel size units
+struct jpeg_density_unit : property_base< UINT8 >
+{
+ static const type default_value = 0;
+};
+
+/// pixel density
+struct jpeg_pixel_density : property_base< UINT16 >
+{
+ static const type default_value = 0;
+};
+
+/// Defines type for dct ( discrete cosine transformation ) method property.
+struct jpeg_dct_method : property_base< J_DCT_METHOD >
+{
+ static const type slow = JDCT_ISLOW;
+ static const type fast = JDCT_IFAST;
+ static const type floating_pt = JDCT_FLOAT;
+ static const type fastest = JDCT_FASTEST;
+
+ static const type default_value = slow;
+};
+
+/// Read information for jpeg images.
+///
+/// The structure is returned when using read_image_info.
+template<>
+struct image_read_info< jpeg_tag >
+{
+ image_read_info()
+ : _width ( 0 )
+ , _height( 0 )
+
+ , _num_components( 0 )
+
+ , _color_space( J_COLOR_SPACE( 0 ))
+
+ , _data_precision( 0 )
+
+ , _density_unit ( 0 )
+ , _x_density ( 0 )
+ , _y_density ( 0 )
+
+ , _pixel_width_mm ( 0.0 )
+ , _pixel_height_mm( 0.0 )
+ {}
+
+ /// The image width.
+ jpeg_image_width::type _width;
+
+ /// The image height.
+ jpeg_image_height::type _height;
+
+ /// The number of channels.
+ jpeg_num_components::type _num_components;
+
+ /// The color space.
+ jpeg_color_space::type _color_space;
+
+ /// The width of channel.
+ /// I believe this number is always 8 in the case libjpeg is built with 8.
+ /// see: http://www.asmail.be/msg0055405033.html
+ jpeg_data_precision::type _data_precision;
+
+ /// Density conversion unit.
+ jpeg_density_unit::type _density_unit;
+ jpeg_pixel_density::type _x_density;
+ jpeg_pixel_density::type _y_density;
+
+ /// Real-world dimensions
+ double _pixel_width_mm;
+ double _pixel_height_mm;
+};
+
+/// Read settings for jpeg images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< jpeg_tag > : public image_read_settings_base
+{
+ /// Default constructor
+ image_read_settings<jpeg_tag>()
+ : image_read_settings_base()
+ , _dct_method( jpeg_dct_method::default_value )
+ {}
+
+ /// Constructor
+ /// \param top_left Top left coordinate for reading partial image.
+ /// \param dim Dimensions for reading partial image.
+ /// \param dct_method Specifies dct method.
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ , jpeg_dct_method::type dct_method = jpeg_dct_method::default_value
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ , _dct_method( dct_method )
+ {}
+
+ /// The dct ( discrete cosine transformation ) method.
+ jpeg_dct_method::type _dct_method;
+};
+
+/// Write information for jpeg images.
+///
+/// The structure can be used for write_view() function.
+template<>
+struct image_write_info< jpeg_tag >
+{
+ /// Constructor
+ /// \param quality Defines the jpeg quality.
+ /// \param dct_method Defines the DCT method.
+ /// \param density_unit Defines the density unit.
+ /// \param x_density Defines the x density.
+ /// \param y_density Defines the y density.
+ image_write_info( const jpeg_quality::type quality = jpeg_quality::default_value
+ , const jpeg_dct_method::type dct_method = jpeg_dct_method::default_value
+ , const jpeg_density_unit::type density_unit = jpeg_density_unit::default_value
+ , const jpeg_pixel_density::type x_density = jpeg_pixel_density::default_value
+ , const jpeg_pixel_density::type y_density = jpeg_pixel_density::default_value
+ )
+ : _quality ( quality )
+ , _dct_method( dct_method )
+
+ , _density_unit( density_unit )
+ , _x_density ( x_density )
+ , _y_density ( y_density )
+ {}
+
+ /// The jpeg quality.
+ jpeg_quality::type _quality;
+
+ /// The dct ( discrete cosine transformation ) method.
+ jpeg_dct_method::type _dct_method;
+
+ /// Density conversion unit.
+ jpeg_density_unit::type _density_unit;
+
+ /// Pixel density dimensions.
+ jpeg_pixel_density::type _x_density;
+ jpeg_pixel_density::type _y_density;
+
+ /// Sets the pixel dimensions.
+ void set_pixel_dimensions( int image_width // in pixels
+ , int image_height // in pixels
+ , double pixel_width // in mm
+ , double pixel_height // in mm
+ )
+ {
+ _density_unit = 2; // dots per cm
+
+ _x_density = round( image_width / ( pixel_width / 10 ));
+ _y_density = round( image_height / ( pixel_height / 10 ));
+ }
+
+private:
+
+ UINT16 round( double d )
+ {
+ return static_cast< UINT16 >( d + 0.5 );
+ }
+
+};
+
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/jpeg/write.hpp b/boost/gil/extension/io/jpeg/write.hpp
new file mode 100644
index 0000000000..e04967b0ec
--- /dev/null
+++ b/boost/gil/extension/io/jpeg/write.hpp
@@ -0,0 +1,31 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_JPEG_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_JPEG_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/jpeg/tags.hpp>
+#include <boost/gil/extension/io/jpeg/detail/supported_types.hpp>
+#include <boost/gil/extension/io/jpeg/detail/write.hpp>
+
+#include <boost/gil/io/make_writer.hpp>
+#include <boost/gil/io/make_dynamic_image_writer.hpp>
+
+#include <boost/gil/io/write_view.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/jpeg_dynamic_io.hpp b/boost/gil/extension/io/jpeg_dynamic_io.hpp
deleted file mode 100644
index b1108fe8fa..0000000000
--- a/boost/gil/extension/io/jpeg_dynamic_io.hpp
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/jpeg_io.hpp b/boost/gil/extension/io/jpeg_io.hpp
deleted file mode 100644
index b9adc02339..0000000000
--- a/boost/gil/extension/io/jpeg_io.hpp
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/jpeg_io_private.hpp b/boost/gil/extension/io/jpeg_io_private.hpp
deleted file mode 100644
index 4b3e7bdd5b..0000000000
--- a/boost/gil/extension/io/jpeg_io_private.hpp
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/png.hpp b/boost/gil/extension/io/png.hpp
new file mode 100644
index 0000000000..648170b1c0
--- /dev/null
+++ b/boost/gil/extension/io/png.hpp
@@ -0,0 +1,25 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/png/read.hpp>
+#include <boost/gil/extension/io/png/write.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/base.hpp b/boost/gil/extension/io/png/detail/base.hpp
new file mode 100644
index 0000000000..a58d033d10
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/base.hpp
@@ -0,0 +1,109 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_BASE_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_BASE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/png/tags.hpp>
+
+#include <memory>
+
+namespace boost { namespace gil { namespace detail {
+
+struct png_ptr_wrapper
+{
+ png_ptr_wrapper()
+ : _struct( NULL )
+ , _info ( NULL )
+ {}
+
+ png_structp _struct;
+ png_infop _info;
+};
+
+///
+/// Wrapper for libpng's png_struct and png_info object. Implements value semantics.
+///
+struct png_struct_info_wrapper
+{
+protected:
+
+ using png_ptr_t = std::shared_ptr<png_ptr_wrapper>;
+
+protected:
+
+ ///
+ /// Default Constructor
+ ///
+ png_struct_info_wrapper( bool read = true )
+ : _png_ptr( new png_ptr_wrapper()
+ , ( ( read ) ? png_ptr_read_deleter : png_ptr_write_deleter )
+ )
+ {}
+
+ png_ptr_wrapper* get() { return _png_ptr.get(); }
+ const png_ptr_wrapper* get() const { return _png_ptr.get(); }
+
+ png_structp get_struct() { return get()->_struct; }
+ const png_structp get_struct() const { return get()->_struct; }
+
+ png_infop get_info() { return get()->_info; }
+ const png_infop get_info() const { return get()->_info; }
+
+private:
+
+ static void png_ptr_read_deleter( png_ptr_wrapper* png_ptr )
+ {
+ if( png_ptr )
+ {
+ assert( png_ptr->_struct && png_ptr->_info );
+
+ png_destroy_read_struct( &png_ptr->_struct
+ , &png_ptr->_info
+ , NULL
+ );
+
+ delete png_ptr;
+ png_ptr = NULL;
+ }
+ }
+
+ static void png_ptr_write_deleter( png_ptr_wrapper* png_ptr )
+ {
+ if( png_ptr )
+ {
+ assert( png_ptr->_struct && png_ptr->_info );
+
+ png_destroy_write_struct( &png_ptr->_struct
+ , &png_ptr->_info
+ );
+
+ delete png_ptr;
+ png_ptr = NULL;
+ }
+ }
+
+
+private:
+
+ png_ptr_t _png_ptr;
+};
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/is_allowed.hpp b/boost/gil/extension/io/png/detail/is_allowed.hpp
new file mode 100644
index 0000000000..cf83dd5f02
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/is_allowed.hpp
@@ -0,0 +1,55 @@
+/*
+ Copyright 2008 Christian Henning, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_IS_ALLOWED_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_IS_ALLOWED_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/for_each.hpp>
+
+namespace boost { namespace gil { namespace detail {
+
+template< typename View >
+bool is_allowed( const image_read_info< png_tag >& info
+ , mpl::true_ // is read_and_no_convert
+ )
+{
+ typedef typename get_pixel_type< View >::type pixel_t;
+
+ typedef typename channel_traits<
+ typename element_type< pixel_t >::type >::value_type channel_t;
+
+ const png_num_channels::type dst_num_channels = num_channels< pixel_t >::value;
+ const png_bitdepth::type dst_bit_depth = detail::unsigned_integral_num_bits< channel_t >::value;
+
+ return dst_num_channels == info._num_channels
+ && dst_bit_depth == info._bit_depth;
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< png_tag >& /* info */
+ , mpl::false_ // is read_and_convert
+ )
+{
+ return true;
+}
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/read.hpp b/boost/gil/extension/io/png/detail/read.hpp
new file mode 100644
index 0000000000..9c4588c380
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/read.hpp
@@ -0,0 +1,444 @@
+/*
+ Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/png/tags.hpp>
+
+#include <boost/gil.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/typedefs.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+
+#include <boost/gil/extension/io/png/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/png/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// PNG Reader
+///
+template< typename Device
+ , typename ConversionPolicy
+ >
+class reader< Device
+ , png_tag
+ , ConversionPolicy
+ >
+ : public reader_base< png_tag
+ , ConversionPolicy >
+ , public reader_backend< Device
+ , png_tag
+ >
+{
+private:
+
+ typedef reader< Device
+ , png_tag
+ , ConversionPolicy
+ > this_t;
+
+ typedef typename ConversionPolicy::color_converter_type cc_t;
+
+public:
+
+ typedef reader_backend< Device, png_tag > backend_t;
+
+public:
+
+ reader( const Device& io_dev
+ , const image_read_settings< png_tag >& settings
+ )
+ : reader_base< png_tag
+ , ConversionPolicy
+ >()
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ reader( const Device& io_dev
+ , const typename ConversionPolicy::color_converter_type& cc
+ , const image_read_settings< png_tag >& settings
+ )
+ : reader_base< png_tag
+ , ConversionPolicy
+ >( cc )
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename View >
+ void apply( const View& view )
+ {
+ // The info structures are filled at this point.
+
+ // Now it's time for some transformations.
+
+ if( little_endian() )
+ {
+ if( this->_info._bit_depth == 16 )
+ {
+ // Swap bytes of 16 bit files to least significant byte first.
+ png_set_swap( this->get_struct() );
+ }
+
+ if( this->_info._bit_depth < 8 )
+ {
+ // swap bits of 1, 2, 4 bit packed pixel formats
+ png_set_packswap( this->get_struct() );
+ }
+ }
+
+ if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE )
+ {
+ png_set_palette_to_rgb( this->get_struct() );
+ }
+
+ if( png_get_valid( this->get_struct(), this->get_info(), PNG_INFO_tRNS ) )
+ {
+ png_set_tRNS_to_alpha( this->get_struct() );
+ }
+
+ // Tell libpng to handle the gamma conversion for you. The final call
+ // is a good guess for PC generated images, but it should be configurable
+ // by the user at run time by the user. It is strongly suggested that
+ // your application support gamma correction.
+ if( this->_settings._apply_screen_gamma )
+ {
+ // png_set_gamma will change the image data!
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ png_set_gamma( this->get_struct()
+ , this->_settings._screen_gamma
+ , this->_info._file_gamma
+ );
+#else
+ png_set_gamma( this->get_struct()
+ , this->_settings._screen_gamma
+ , this->_info._file_gamma
+ );
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ }
+
+ // Turn on interlace handling. REQUIRED if you are not using
+ // png_read_image(). To see how to handle interlacing passes,
+ // see the png_read_row() method below:
+ this->_number_passes = png_set_interlace_handling( this->get_struct() );
+
+
+ // The above transformation might have changed the bit_depth and color type.
+ png_read_update_info( this->get_struct()
+ , this->get_info()
+ );
+
+ this->_info._bit_depth = png_get_bit_depth( this->get_struct()
+ , this->get_info()
+ );
+
+ this->_info._num_channels = png_get_channels( this->get_struct()
+ , this->get_info()
+ );
+
+ this->_info._color_type = png_get_color_type( this->get_struct()
+ , this->get_info()
+ );
+
+ this->_scanline_length = png_get_rowbytes( this->get_struct()
+ , this->get_info()
+ );
+
+ switch( this->_info._color_type )
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ {
+ switch( this->_info._bit_depth )
+ {
+ case 1: read_rows< gray1_image_t::view_t::reference >( view ); break;
+ case 2: read_rows< gray2_image_t::view_t::reference >( view ); break;
+ case 4: read_rows< gray4_image_t::view_t::reference >( view ); break;
+ case 8: read_rows< gray8_pixel_t >( view ); break;
+ case 16: read_rows< gray16_pixel_t >( view ); break;
+ default: io_error( "png_reader::read_data(): unknown combination of color type and bit depth" );
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_GA:
+ {
+ #ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+ switch( this->_info._bit_depth )
+ {
+ case 8: read_rows< gray_alpha8_pixel_t > ( view ); break;
+ case 16: read_rows< gray_alpha16_pixel_t >( view ); break;
+ default: io_error( "png_reader::read_data(): unknown combination of color type and bit depth" );
+ }
+ #else
+ io_error( "gray_alpha isn't enabled. Use ENABLE_GRAY_ALPHA when building application." );
+ #endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+
+
+ break;
+ }
+ case PNG_COLOR_TYPE_RGB:
+ {
+ switch( this->_info._bit_depth )
+ {
+ case 8: read_rows< rgb8_pixel_t > ( view ); break;
+ case 16: read_rows< rgb16_pixel_t >( view ); break;
+ default: io_error( "png_reader::read_data(): unknown combination of color type and bit depth" );
+ }
+
+ break;
+ }
+ case PNG_COLOR_TYPE_RGBA:
+ {
+ switch( this->_info._bit_depth )
+ {
+ case 8: read_rows< rgba8_pixel_t > ( view ); break;
+ case 16: read_rows< rgba16_pixel_t >( view ); break;
+ default: io_error( "png_reader_color_convert::read_data(): unknown combination of color type and bit depth" );
+ }
+
+ break;
+ }
+ default: io_error( "png_reader_color_convert::read_data(): unknown color type" );
+ }
+
+ // read rest of file, and get additional chunks in info_ptr
+ png_read_end( this->get_struct()
+ , NULL
+ );
+ }
+
+private:
+
+ template< typename ImagePixel
+ , typename View
+ >
+ void read_rows( const View& view )
+ {
+ typedef detail::row_buffer_helper_view< ImagePixel > row_buffer_helper_t;
+
+ typedef typename row_buffer_helper_t::iterator_t it_t;
+
+ typedef typename is_same< ConversionPolicy
+ , detail::read_and_no_convert
+ >::type is_read_and_convert_t;
+
+ io_error_if( !detail::is_allowed< View >( this->_info
+ , is_read_and_convert_t()
+ )
+ , "Image types aren't compatible."
+ );
+
+ std::size_t rowbytes = png_get_rowbytes( this->get_struct()
+ , this->get_info()
+ );
+
+ row_buffer_helper_t buffer( rowbytes
+ , true
+ );
+
+ png_bytep row_ptr = (png_bytep)( &( buffer.data()[0]));
+
+ for( std::size_t pass = 0; pass < this->_number_passes; pass++ )
+ {
+ if( pass == this->_number_passes - 1 )
+ {
+ // skip lines if necessary
+ for( std::ptrdiff_t y = 0; y < this->_settings._top_left.y; ++y )
+ {
+ // Read the image using the "sparkle" effect.
+ png_read_rows( this->get_struct()
+ , &row_ptr
+ , NULL
+ , 1
+ );
+ }
+
+ for( std::ptrdiff_t y = 0
+ ; y < this->_settings._dim.y
+ ; ++y
+ )
+ {
+ // Read the image using the "sparkle" effect.
+ png_read_rows( this->get_struct()
+ , &row_ptr
+ , NULL
+ , 1
+ );
+
+ it_t first = buffer.begin() + this->_settings._top_left.x;
+ it_t last = first + this->_settings._dim.x; // one after last element
+
+ this->_cc_policy.read( first
+ , last
+ , view.row_begin( y ));
+ }
+
+ // Read the rest of the image. libpng needs that.
+ std::ptrdiff_t remaining_rows = static_cast< std::ptrdiff_t >( this->_info._height )
+ - this->_settings._top_left.y
+ - this->_settings._dim.y;
+ for( std::ptrdiff_t y = 0
+ ; y < remaining_rows
+ ; ++y
+ )
+ {
+ // Read the image using the "sparkle" effect.
+ png_read_rows( this->get_struct()
+ , &row_ptr
+ , NULL
+ , 1
+ );
+ }
+ }
+ else
+ {
+ for( int y = 0; y < view.height(); ++y )
+ {
+ // Read the image using the "sparkle" effect.
+ png_read_rows( this->get_struct()
+ , &row_ptr
+ , NULL
+ , 1
+ );
+ }
+ }
+ }
+ }
+};
+
+namespace detail {
+
+struct png_type_format_checker
+{
+ png_type_format_checker( png_bitdepth::type bit_depth
+ , png_color_type::type color_type
+ )
+ : _bit_depth ( bit_depth )
+ , _color_type( color_type )
+ {}
+
+ template< typename Image >
+ bool apply()
+ {
+ typedef is_read_supported< typename get_pixel_type< typename Image::view_t >::type
+ , png_tag
+ > is_supported_t;
+
+ return is_supported_t::_bit_depth == _bit_depth
+ && is_supported_t::_color_type == _color_type;
+ }
+
+private:
+
+ png_bitdepth::type _bit_depth;
+ png_color_type::type _color_type;
+};
+
+struct png_read_is_supported
+{
+ template< typename View >
+ struct apply : public is_read_supported< typename get_pixel_type< View >::type
+ , png_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+
+///
+/// PNG Dynamic Image Reader
+///
+template< typename Device
+ >
+class dynamic_image_reader< Device
+ , png_tag
+ >
+ : public reader< Device
+ , png_tag
+ , detail::read_and_no_convert
+ >
+{
+ typedef reader< Device
+ , png_tag
+ , detail::read_and_no_convert
+ > parent_t;
+
+public:
+
+ dynamic_image_reader( const Device& io_dev
+ , const image_read_settings< png_tag >& settings
+ )
+ : parent_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename Images >
+ void apply( any_image< Images >& images )
+ {
+ detail::png_type_format_checker format_checker( this->_info._bit_depth
+ , this->_info._color_type
+ );
+
+ if( !construct_matched( images
+ , format_checker
+ ))
+ {
+ io_error( "No matching image type between those of the given any_image and that of the file" );
+ }
+ else
+ {
+ this->init_image( images
+ , this->_settings
+ );
+
+ detail::dynamic_io_fnobj< detail::png_read_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( view( images )
+ , op
+ );
+ }
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/reader_backend.hpp b/boost/gil/extension/io/png/detail/reader_backend.hpp
new file mode 100644
index 0000000000..914d4c7505
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/reader_backend.hpp
@@ -0,0 +1,698 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_DETAIL_READER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_DETAIL_READER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/png/tags.hpp>
+
+#include <boost/gil/extension/io/png/detail/base.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+///
+/// PNG Backend
+///
+template<typename Device >
+struct reader_backend< Device
+ , png_tag
+ >
+ : public detail::png_struct_info_wrapper
+{
+public:
+
+ typedef png_tag format_tag_t;
+
+public:
+
+ typedef reader_backend< Device
+ , png_tag
+ > this_t;
+
+
+public:
+
+ reader_backend( const Device& io_dev
+ , const image_read_settings< png_tag >& settings
+ )
+ : _io_dev( io_dev )
+
+ , _settings( settings )
+ , _info()
+ , _scanline_length( 0 )
+
+ , _number_passes( 0 )
+ {
+ read_header();
+
+ if( _settings._dim.x == 0 )
+ {
+ _settings._dim.x = _info._width;
+ }
+
+ if( _settings._dim.y == 0 )
+ {
+ _settings._dim.y = _info._height;
+ }
+ }
+
+ void read_header()
+ {
+ using boost::gil::detail::PNG_BYTES_TO_CHECK;
+
+ // check the file's first few bytes
+ byte_t buf[PNG_BYTES_TO_CHECK];
+
+ io_error_if( _io_dev.read( buf
+ , PNG_BYTES_TO_CHECK
+ ) != PNG_BYTES_TO_CHECK
+ , "png_check_validity: failed to read image"
+ );
+
+ io_error_if( png_sig_cmp( png_bytep(buf)
+ , png_size_t(0)
+ , PNG_BYTES_TO_CHECK
+ ) != 0
+ , "png_check_validity: invalid png image"
+ );
+
+ // Create and initialize the png_struct with the desired error handler
+ // functions. If you want to use the default stderr and longjump method,
+ // you can supply NULL for the last three parameters. We also supply the
+ // the compiler header file version, so that we know if the application
+ // was compiled with a compatible version of the library. REQUIRED
+ get()->_struct = png_create_read_struct( PNG_LIBPNG_VER_STRING
+ , NULL // user_error_ptr
+ , NULL // user_error_fn
+ , NULL // user_warning_fn
+ );
+
+ io_error_if( get()->_struct == NULL
+ , "png_reader: fail to call png_create_write_struct()"
+ );
+
+ png_uint_32 user_chunk_data[4];
+ user_chunk_data[0] = 0;
+ user_chunk_data[1] = 0;
+ user_chunk_data[2] = 0;
+ user_chunk_data[3] = 0;
+ png_set_read_user_chunk_fn( get_struct()
+ , user_chunk_data
+ , this_t::read_user_chunk_callback
+ );
+
+ // Allocate/initialize the memory for image information. REQUIRED.
+ get()->_info = png_create_info_struct( get_struct() );
+
+ if( get_info() == NULL )
+ {
+ png_destroy_read_struct( &get()->_struct
+ , NULL
+ , NULL
+ );
+
+ io_error( "png_reader: fail to call png_create_info_struct()" );
+ }
+
+ // Set error handling if you are using the setjmp/longjmp method (this is
+ // the normal method of doing things with libpng). REQUIRED unless you
+ // set up your own error handlers in the png_create_read_struct() earlier.
+ if( setjmp( png_jmpbuf( get_struct() )))
+ {
+ //free all of the memory associated with the png_ptr and info_ptr
+ png_destroy_read_struct( &get()->_struct
+ , &get()->_info
+ , NULL
+ );
+
+ io_error( "png is invalid" );
+ }
+
+ png_set_read_fn( get_struct()
+ , static_cast< png_voidp >( &this->_io_dev )
+ , this_t::read_data
+ );
+
+ // Set up a callback function that will be
+ // called after each row has been read, which you can use to control
+ // a progress meter or the like.
+ png_set_read_status_fn( get_struct()
+ , this_t::read_row_callback
+ );
+
+ // Set up a callback which implements user defined transformation.
+ // @todo
+ png_set_read_user_transform_fn( get_struct()
+ , png_user_transform_ptr( NULL )
+ );
+
+ png_set_keep_unknown_chunks( get_struct()
+ , PNG_HANDLE_CHUNK_ALWAYS
+ , NULL
+ , 0
+ );
+
+
+ // Make sure we read the signature.
+ // @todo make it an option
+ png_set_sig_bytes( get_struct()
+ , PNG_BYTES_TO_CHECK
+ );
+
+ // The call to png_read_info() gives us all of the information from the
+ // PNG file before the first IDAT (image data chunk). REQUIRED
+ png_read_info( get_struct()
+ , get_info()
+ );
+
+ ///
+ /// Start reading the image information
+ ///
+
+ // get PNG_IHDR chunk information from png_info structure
+ png_get_IHDR( get_struct()
+ , get_info()
+ , &this->_info._width
+ , &this->_info._height
+ , &this->_info._bit_depth
+ , &this->_info._color_type
+ , &this->_info._interlace_method
+ , &this->_info._compression_method
+ , &this->_info._filter_method
+ );
+
+ // get number of color channels in image
+ this->_info._num_channels = png_get_channels( get_struct()
+ , get_info()
+ );
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+ // Get CIE chromacities and referenced white point
+ if( this->_settings._read_cie_chromacities )
+ {
+ this->_info._valid_cie_colors = png_get_cHRM( get_struct()
+ , get_info()
+ , &this->_info._white_x, &this->_info._white_y
+ , &this->_info._red_x, &this->_info._red_y
+ , &this->_info._green_x, &this->_info._green_y
+ , &this->_info._blue_x, &this->_info._blue_y
+ );
+ }
+
+ // get the gamma value
+ if( this->_settings._read_file_gamma )
+ {
+ this->_info._valid_file_gamma = png_get_gAMA( get_struct()
+ , get_info()
+ , &this->_info._file_gamma
+ );
+
+ if( this->_info._valid_file_gamma == false )
+ {
+ this->_info._file_gamma = 1.0;
+ }
+ }
+#else
+
+ // Get CIE chromacities and referenced white point
+ if( this->_settings._read_cie_chromacities )
+ {
+ this->_info._valid_cie_colors = png_get_cHRM_fixed( get_struct()
+ , get_info()
+ , &this->_info._white_x, &this->_info._white_y
+ , &this->_info._red_x, &this->_info._red_y
+ , &this->_info._green_x, &this->_info._green_y
+ , &this->_info._blue_x, &this->_info._blue_y
+ );
+ }
+
+ // get the gamma value
+ if( this->_settings._read_file_gamma )
+ {
+ this->_info._valid_file_gamma = png_get_gAMA_fixed( get_struct()
+ , get_info()
+ , &this->_info._file_gamma
+ );
+
+ if( this->_info._valid_file_gamma == false )
+ {
+ this->_info._file_gamma = 1;
+ }
+ }
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+ // get the embedded ICC profile data
+ if( this->_settings._read_icc_profile )
+ {
+#if PNG_LIBPNG_VER_MINOR >= 5
+ png_charp icc_name = png_charp( NULL );
+ png_bytep profile = png_bytep( NULL );
+
+ this->_info._valid_icc_profile = png_get_iCCP( get_struct()
+ , get_info()
+ , &icc_name
+ , &this->_info._iccp_compression_type
+ , &profile
+ , &this->_info._profile_length
+ );
+#else
+ png_charp icc_name = png_charp( NULL );
+ png_charp profile = png_charp( NULL );
+
+ this->_info._valid_icc_profile = png_get_iCCP( get_struct()
+ , get_info()
+ , &icc_name
+ , &this->_info._iccp_compression_type
+ , &profile
+ , &this->_info._profile_length
+ );
+#endif
+ if( icc_name )
+ {
+ this->_info._icc_name.append( icc_name
+ , std::strlen( icc_name )
+ );
+ }
+
+ if( this->_info._profile_length != 0 )
+ {
+ std:: copy_n (profile, this->_info._profile_length, std:: back_inserter (this->_info._profile));
+ }
+ }
+
+ // get the rendering intent
+ if( this->_settings._read_intent )
+ {
+ this->_info._valid_intent = png_get_sRGB( get_struct()
+ , get_info()
+ , &this->_info._intent
+ );
+ }
+
+ // get image palette information from png_info structure
+ if( this->_settings._read_palette )
+ {
+ png_colorp palette = png_colorp( NULL );
+
+ this->_info._valid_palette = png_get_PLTE( get_struct()
+ , get_info()
+ , &palette
+ , &this->_info._num_palette
+ );
+
+ if( this->_info._num_palette > 0 )
+ {
+ this->_info._palette.resize( this->_info._num_palette );
+ std::copy( palette
+ , palette + this->_info._num_palette
+ , &this->_info._palette.front()
+ );
+ }
+ }
+
+ // get background color
+ if( this->_settings._read_background )
+ {
+ png_color_16p background = png_color_16p( NULL );
+
+ this->_info._valid_background = png_get_bKGD( get_struct()
+ , get_info()
+ , &background
+ );
+ if( background )
+ {
+ this->_info._background = *background;
+ }
+ }
+
+ // get the histogram
+ if( this->_settings._read_histogram )
+ {
+ png_uint_16p histogram = png_uint_16p( NULL );
+
+ this->_info._valid_histogram = png_get_hIST( get_struct()
+ , get_info()
+ , &histogram
+ );
+
+ if( histogram )
+ {
+ // the number of values is set by the number of colors inside
+ // the palette.
+ if( this->_settings._read_palette == false )
+ {
+ png_colorp palette = png_colorp( NULL );
+ png_get_PLTE( get_struct()
+ , get_info()
+ , &palette
+ , &this->_info._num_palette
+ );
+ }
+
+ std::copy( histogram
+ , histogram + this->_info._num_palette
+ , &this->_info._histogram.front()
+ );
+ }
+ }
+
+ // get screen offsets for the given image
+ if( this->_settings._read_screen_offsets )
+ {
+ this->_info._valid_offset = png_get_oFFs( get_struct()
+ , get_info()
+ , &this->_info._offset_x
+ , &this->_info._offset_y
+ , &this->_info._off_unit_type
+ );
+ }
+
+
+ // get pixel calibration settings
+ if( this->_settings._read_pixel_calibration )
+ {
+ png_charp purpose = png_charp ( NULL );
+ png_charp units = png_charp ( NULL );
+ png_charpp params = png_charpp( NULL );
+
+ this->_info._valid_pixel_calibration = png_get_pCAL( get_struct()
+ , get_info()
+ , &purpose
+ , &this->_info._X0
+ , &this->_info._X1
+ , &this->_info._cal_type
+ , &this->_info._num_params
+ , &units
+ , &params
+ );
+ if( purpose )
+ {
+ this->_info._purpose.append( purpose
+ , std::strlen( purpose )
+ );
+ }
+
+ if( units )
+ {
+ this->_info._units.append( units
+ , std::strlen( units )
+ );
+ }
+
+ if( this->_info._num_params > 0 )
+ {
+ this->_info._params.resize( this->_info._num_params );
+
+ for( png_CAL_nparam::type i = 0
+ ; i < this->_info._num_params
+ ; ++i
+ )
+ {
+ this->_info._params[i].append( params[i]
+ , std::strlen( params[i] )
+ );
+ }
+ }
+ }
+
+ // get the physical resolution
+ if( this->_settings._read_physical_resolution )
+ {
+ this->_info._valid_resolution = png_get_pHYs( get_struct()
+ , get_info()
+ , &this->_info._res_x
+ , &this->_info._res_y
+ , &this->_info._phy_unit_type
+ );
+ }
+
+ // get the image resolution in pixels per meter.
+ if( this->_settings._read_pixels_per_meter )
+ {
+ this->_info._pixels_per_meter = png_get_pixels_per_meter( get_struct()
+ , get_info()
+ );
+ }
+
+
+ // get number of significant bits for each color channel
+ if( this->_settings._read_number_of_significant_bits )
+ {
+ png_color_8p sig_bits = png_color_8p( NULL );
+
+ this->_info._valid_significant_bits = png_get_sBIT( get_struct()
+ , get_info()
+ , &sig_bits
+ );
+
+ // @todo Is there one or more colors?
+ if( sig_bits )
+ {
+ this->_info._sig_bits = *sig_bits;
+ }
+ }
+
+#ifndef BOOST_GIL_IO_PNG_1_4_OR_LOWER
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+ // get physical scale settings
+ if( this->_settings._read_scale_factors )
+ {
+ this->_info._valid_scale_factors = png_get_sCAL( get_struct()
+ , get_info()
+ , &this->_info._scale_unit
+ , &this->_info._scale_width
+ , &this->_info._scale_height
+ );
+ }
+#else
+#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+ if( this->_settings._read_scale_factors )
+ {
+ this->_info._valid_scale_factors = png_get_sCAL_fixed( get_struct()
+ , get_info()
+ , &this->_info._scale_unit
+ , &this->_info._scale_width
+ , &this->_info._scale_height
+ );
+ }
+#else
+ if( this->_settings._read_scale_factors )
+ {
+ png_charp scale_width = NULL;
+ png_charp scale_height = NULL;
+
+ if( this->_info._valid_scale_factors = png_get_sCAL_s( get_struct()
+ , get_info()
+ , &this->_info._scale_unit
+ , &scale_width
+ , &scale_height
+ ) > 0
+ )
+ {
+ if( scale_width )
+ {
+ this->_info._scale_width.append( scale_width
+ , std::strlen( scale_width )
+ );
+ }
+
+ if( scale_height )
+ {
+ this->_info._scale_height.append( scale_height
+ , std::strlen( scale_height )
+ );
+ }
+ }
+ }
+#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+#endif // BOOST_GIL_IO_PNG_1_4_OR_LOWER
+
+ // get comments information from png_info structure
+ if( this->_settings._read_comments )
+ {
+ png_textp text = png_textp( NULL );
+
+ this->_info._valid_text = png_get_text( get_struct()
+ , get_info()
+ , &text
+ , &this->_info._num_text
+ );
+
+ if( this->_info._num_text > 0 )
+ {
+ this->_info._text.resize( this->_info._num_text );
+
+ for( png_num_text::type i = 0
+ ; i < this->_info._num_text
+ ; ++i
+ )
+ {
+ this->_info._text[i]._compression = text[i].compression;
+ this->_info._text[i]._key.append( text[i].key
+ , std::strlen( text[i].key )
+ );
+
+ this->_info._text[i]._text.append( text[i].text
+ , std::strlen( text[i].text )
+ );
+ }
+ }
+ }
+
+ // get last modification time
+ if( this->_settings._read_last_modification_time )
+ {
+ png_timep mod_time = png_timep( NULL );
+ this->_info._valid_modification_time = png_get_tIME( get_struct()
+ , get_info()
+ , &mod_time
+ );
+ if( mod_time )
+ {
+ this->_info._mod_time = *mod_time;
+ }
+ }
+
+ // get transparency data
+ if( this->_settings._read_transparency_data )
+ {
+ png_bytep trans = png_bytep ( NULL );
+ png_color_16p trans_values = png_color_16p( NULL );
+
+ this->_info._valid_transparency_factors = png_get_tRNS( get_struct()
+ , get_info()
+ , &trans
+ , &this->_info._num_trans
+ , &trans_values
+ );
+
+ if( trans )
+ {
+ //@todo What to do, here? How do I know the length of the "trans" array?
+ }
+
+ if( this->_info._num_trans )
+ {
+ this->_info._trans_values.resize( this->_info._num_trans );
+ std::copy( trans_values
+ , trans_values + this->_info._num_trans
+ , &this->_info._trans_values.front()
+ );
+ }
+ }
+
+ // @todo One day!
+/*
+ if( false )
+ {
+ png_unknown_chunkp unknowns = png_unknown_chunkp( NULL );
+ int num_unknowns = static_cast< int >( png_get_unknown_chunks( get_struct()
+ , get_info()
+ , &unknowns
+ )
+ );
+ }
+*/
+ }
+
+ /// Check if image is large enough.
+ void check_image_size( const point_t& img_dim )
+ {
+ if( _settings._dim.x > 0 )
+ {
+ if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
+ }
+
+
+ if( _settings._dim.y > 0 )
+ {
+ if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
+ }
+ }
+
+protected:
+
+ static void read_data( png_structp png_ptr
+ , png_bytep data
+ , png_size_t length
+ )
+ {
+ static_cast<Device*>(png_get_io_ptr(png_ptr) )->read( data
+ , length );
+ }
+
+ static void flush( png_structp png_ptr )
+ {
+ static_cast<Device*>(png_get_io_ptr(png_ptr) )->flush();
+ }
+
+
+ static int read_user_chunk_callback( png_struct* /* png_ptr */
+ , png_unknown_chunkp /* chunk */
+ )
+ {
+ // @todo
+ return 0;
+ }
+
+ static void read_row_callback( png_structp /* png_ptr */
+ , png_uint_32 /* row_number */
+ , int /* pass */
+ )
+ {
+ // @todo
+ }
+
+public:
+
+ Device _io_dev;
+
+ image_read_settings< png_tag > _settings;
+ image_read_info < png_tag > _info;
+
+ std::size_t _scanline_length;
+
+ std::size_t _number_passes;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/scanline_read.hpp b/boost/gil/extension/io/png/detail/scanline_read.hpp
new file mode 100644
index 0000000000..33b1dcba31
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/scanline_read.hpp
@@ -0,0 +1,181 @@
+/*
+ Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_SCANLINE_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_SCANLINE_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/typedefs.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#include <boost/gil/extension/io/png/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/png/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+///
+/// PNG Reader
+///
+template< typename Device >
+class scanline_reader< Device
+ , png_tag
+ >
+ : public reader_backend< Device
+ , png_tag
+ >
+{
+public:
+
+ typedef png_tag tag_t;
+ typedef reader_backend < Device, tag_t > backend_t;
+ typedef scanline_reader< Device, tag_t > this_t;
+ typedef scanline_read_iterator< this_t > iterator_t;
+
+public:
+
+ //
+ // Constructor
+ //
+ scanline_reader( const Device& io_dev
+ , const image_read_settings< png_tag >& settings
+ )
+ : reader_backend< Device
+ , png_tag
+ >( io_dev
+ , settings
+ )
+ {
+ initialize();
+ }
+
+ void read( byte_t* dst
+ , int
+ )
+ {
+ read_scanline( dst );
+ }
+
+ /// Skip over a scanline.
+ void skip( byte_t* dst, int )
+ {
+ read_scanline( dst );
+ }
+
+ iterator_t begin() { return iterator_t( *this ); }
+ iterator_t end() { return iterator_t( *this, this->_info._height ); }
+
+private:
+
+ void initialize()
+ {
+ // Now it's time for some transformations.
+
+ if( little_endian() )
+ {
+ if( this->_info._bit_depth == 16 )
+ {
+ // Swap bytes of 16 bit files to least significant byte first.
+ png_set_swap( this->get()->_struct );
+ }
+
+ if( this->_info._bit_depth < 8 )
+ {
+ // swap bits of 1, 2, 4 bit packed pixel formats
+ png_set_packswap( this->get()->_struct );
+ }
+ }
+
+ if( this->_info._color_type == PNG_COLOR_TYPE_PALETTE )
+ {
+ png_set_palette_to_rgb( this->get()->_struct );
+ }
+
+ if( this->_info._num_trans > 0 )
+ {
+ png_set_tRNS_to_alpha( this->get()->_struct );
+ }
+
+ // Tell libpng to handle the gamma conversion for you. The final call
+ // is a good guess for PC generated images, but it should be configurable
+ // by the user at run time by the user. It is strongly suggested that
+ // your application support gamma correction.
+ if( this->_settings._apply_screen_gamma )
+ {
+ // png_set_gamma will change the image data!
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ png_set_gamma( this->get()->_struct
+ , this->_settings._screen_gamma
+ , this->_info._file_gamma
+ );
+#else
+ png_set_gamma( this->get()->_struct
+ , this->_settings._screen_gamma
+ , this->_info._file_gamma
+ );
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ }
+
+ // Interlaced images are not supported.
+ this->_number_passes = png_set_interlace_handling( this->get()->_struct );
+ io_error_if( this->_number_passes != 1
+ , "scanline_read_iterator cannot read interlaced png images."
+ );
+
+
+ // The above transformation might have changed the bit_depth and color type.
+ png_read_update_info( this->get()->_struct
+ , this->get()->_info
+ );
+
+ this->_info._bit_depth = png_get_bit_depth( this->get()->_struct
+ , this->get()->_info
+ );
+
+ this->_info._num_channels = png_get_channels( this->get()->_struct
+ , this->get()->_info
+ );
+
+ this->_info._color_type = png_get_color_type( this->get()->_struct
+ , this->get()->_info
+ );
+
+ this->_scanline_length = png_get_rowbytes( this->get()->_struct
+ , this->get()->_info
+ );
+ }
+
+ void read_scanline( byte_t* dst )
+ {
+ png_read_row( this->get()->_struct
+ , dst
+ , NULL
+ );
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/supported_types.hpp b/boost/gil/extension/io/png/detail/supported_types.hpp
new file mode 100644
index 0000000000..165e8f4877
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/supported_types.hpp
@@ -0,0 +1,366 @@
+/*
+ Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_SUPPORTED_TYPES_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_SUPPORTED_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+#include <boost/gil/extension/toolbox/color_spaces/gray_alpha.hpp>
+#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+
+namespace boost { namespace gil { namespace detail {
+
+static const size_t PNG_BYTES_TO_CHECK = 4;
+
+// Read support
+template< png_bitdepth::type BitDepth
+ , png_color_type::type ColorType
+ >
+struct png_rw_support_base
+{
+ static const png_bitdepth::type _bit_depth = BitDepth;
+ static const png_color_type::type _color_type = ColorType;
+};
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct png_read_support : read_support_false
+ , png_rw_support_base< 1
+ , PNG_COLOR_TYPE_GRAY
+ > {};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_read_support< packed_dynamic_channel_reference< BitField
+ , 1
+ , Mutable
+ >
+ , gray_t
+ > : read_support_true
+ , png_rw_support_base< 1
+ , PNG_COLOR_TYPE_GRAY
+ > {};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_read_support< packed_dynamic_channel_reference< BitField
+ , 2
+ , Mutable
+ >
+ , gray_t
+ > : read_support_true
+ , png_rw_support_base< 2
+ , PNG_COLOR_TYPE_GRAY
+ > {};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_read_support< packed_dynamic_channel_reference< BitField
+ , 4
+ , Mutable
+ >
+ , gray_t
+ > : read_support_true
+ , png_rw_support_base< 4
+ , PNG_COLOR_TYPE_GRAY
+ > {};
+
+template<>
+struct png_read_support<uint8_t
+ , gray_t
+ > : read_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_GRAY
+ > {};
+
+#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+template<>
+struct png_read_support<uint8_t
+ , gray_alpha_t
+ > : read_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_GA
+ > {};
+#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+
+template<>
+struct png_read_support<uint8_t
+ , rgb_t
+ > : read_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_RGB
+ > {};
+
+template<>
+struct png_read_support<uint8_t
+ , rgba_t
+ > : read_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_RGBA
+ > {};
+
+template<>
+struct png_read_support<uint16_t
+ , gray_t
+ > : read_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_GRAY
+ > {};
+
+template<>
+struct png_read_support<uint16_t
+ , rgb_t
+ > : read_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_RGB
+ > {};
+
+template<>
+struct png_read_support<uint16_t
+ , rgba_t
+ > : read_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_RGBA
+ > {};
+
+#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+template<>
+struct png_read_support<uint16_t
+ , gray_alpha_t
+ > : read_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_GA
+ > {};
+#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+
+// Write support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct png_write_support : write_support_false
+ , png_rw_support_base< 1
+ , PNG_COLOR_TYPE_GRAY
+ > {};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_write_support< packed_dynamic_channel_reference< BitField
+ , 1
+ , Mutable
+ >
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 1
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_write_support< packed_dynamic_channel_reference< BitField
+ , 1
+ , Mutable
+ > const
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 1
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_write_support< packed_dynamic_channel_reference< BitField
+ , 2
+ , Mutable
+ >
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 2
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_write_support< packed_dynamic_channel_reference< BitField
+ , 2
+ , Mutable
+ > const
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 2
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_write_support< packed_dynamic_channel_reference< BitField
+ , 4
+ , Mutable
+ >
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 4
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+template< typename BitField
+ , bool Mutable
+ >
+struct png_write_support< packed_dynamic_channel_reference< BitField
+ , 4
+ , Mutable
+ > const
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 4
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+template<>
+struct png_write_support<uint8_t
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+template<>
+struct png_write_support<uint8_t
+ , gray_alpha_t
+ > : write_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_GA
+ >
+{};
+#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+
+template<>
+struct png_write_support<uint8_t
+ , rgb_t
+ > : write_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_RGB
+ >
+{};
+
+template<>
+struct png_write_support<uint8_t
+ , rgba_t
+ > : write_support_true
+ , png_rw_support_base< 8
+ , PNG_COLOR_TYPE_RGBA
+ >
+{};
+
+template<>
+struct png_write_support<uint16_t
+ , gray_t
+ > : write_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_GRAY
+ >
+{};
+
+template<>
+struct png_write_support<uint16_t
+ , rgb_t
+ > : write_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_RGB
+ >
+{};
+
+template<>
+struct png_write_support<uint16_t
+ , rgba_t
+ > : write_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_RGBA
+ >
+{};
+
+#ifdef BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+template<>
+struct png_write_support<uint16_t
+ , gray_alpha_t
+ > : write_support_true
+ , png_rw_support_base< 16
+ , PNG_COLOR_TYPE_GA
+ >
+{};
+#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
+
+
+} // namespace detail
+
+template< typename Pixel >
+struct is_read_supported< Pixel
+ , png_tag
+ >
+ : mpl::bool_< detail::png_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ >
+{
+ typedef detail::png_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ > parent_t;
+
+ static const png_bitdepth::type _bit_depth = parent_t::_bit_depth;
+ static const png_color_type::type _color_type = parent_t::_color_type;
+};
+
+template< typename Pixel >
+struct is_write_supported< Pixel
+ , png_tag
+ >
+ : mpl::bool_< detail::png_write_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ >
+{
+ typedef detail::png_write_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ > parent_t;
+
+ static const png_bitdepth::type _bit_depth = parent_t::_bit_depth;
+ static const png_color_type::type _color_type = parent_t::_color_type;
+};
+
+} // namespace gil
+} // namespace boost
+
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/write.hpp b/boost/gil/extension/io/png/detail/write.hpp
new file mode 100644
index 0000000000..e571c09459
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/write.hpp
@@ -0,0 +1,242 @@
+/*
+ Copyright 2007-2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/and.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/less.hpp>
+#include <boost/mpl/not.hpp>
+
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+
+#include <boost/gil/extension/io/png/detail/writer_backend.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+namespace detail {
+
+struct png_write_is_supported
+{
+ template< typename View >
+ struct apply
+ : public is_write_supported< typename get_pixel_type< View >::type
+ , png_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+///
+/// PNG Writer
+///
+template< typename Device >
+class writer< Device
+ , png_tag
+ >
+ : public writer_backend< Device
+ , png_tag
+ >
+{
+
+public:
+
+ typedef writer_backend< Device , png_tag > backend_t;
+
+ writer( const Device& io_dev
+ , const image_write_info< png_tag >& info
+ )
+ : backend_t( io_dev
+ , info
+ )
+ {}
+
+
+ template< typename View >
+ void apply( const View& view )
+ {
+ io_error_if( view.width() == 0 && view.height() == 0
+ , "png format cannot handle empty views."
+ );
+
+ this->write_header( view );
+
+ write_view( view
+ , typename is_bit_aligned< typename View::value_type >::type()
+ );
+ }
+
+private:
+
+ template<typename View>
+ void write_view( const View& view
+ , mpl::false_ // is bit aligned
+ )
+ {
+ typedef typename get_pixel_type< View >::type pixel_t;
+
+ typedef detail::png_write_support< typename channel_type < pixel_t >::type
+ , typename color_space_type< pixel_t >::type
+ > png_rw_info;
+
+ if( little_endian() )
+ {
+ set_swap< png_rw_info >();
+ }
+
+ std::vector< pixel< typename channel_type< View >::type
+ , layout<typename color_space_type< View >::type >
+ >
+ > row_buffer( view.width() );
+
+ for( int y = 0; y != view.height(); ++ y)
+ {
+ std::copy( view.row_begin( y )
+ , view.row_end ( y )
+ , row_buffer.begin()
+ );
+
+ png_write_row( this->get_struct()
+ , reinterpret_cast< png_bytep >( row_buffer.data() )
+ );
+ }
+
+ png_write_end( this->get_struct()
+ , this->get_info()
+ );
+ }
+
+ template<typename View>
+ void write_view( const View& view
+ , mpl::true_ // is bit aligned
+ )
+ {
+ typedef detail::png_write_support< typename kth_semantic_element_type< typename View::value_type
+ , 0
+ >::type
+ , typename color_space_type<View>::type
+ > png_rw_info;
+
+ if (little_endian() )
+ {
+ set_swap< png_rw_info >();
+ }
+
+ detail::row_buffer_helper_view< View > row_buffer( view.width()
+ , false
+ );
+
+ for( int y = 0; y != view.height(); ++y )
+ {
+ std::copy( view.row_begin( y )
+ , view.row_end ( y )
+ , row_buffer.begin()
+ );
+
+ png_write_row( this->get_struct()
+ , reinterpret_cast< png_bytep >( row_buffer.data() )
+ );
+ }
+
+ png_free_data( this->get_struct()
+ , this->get_info()
+ , PNG_FREE_UNKN
+ , -1
+ );
+
+ png_write_end( this->get_struct()
+ , this->get_info()
+ );
+ }
+
+ template< typename Info > struct is_less_than_eight : mpl::less< mpl::int_< Info::_bit_depth >, mpl::int_< 8 > > {};
+ template< typename Info > struct is_equal_to_sixteen : mpl::equal_to< mpl::int_< Info::_bit_depth >, mpl::int_< 16 > > {};
+
+ template< typename Info >
+ void set_swap( typename enable_if< is_less_than_eight< Info > >::type* /* ptr */ = 0 )
+ {
+ png_set_packswap( this->get_struct() );
+ }
+
+ template< typename Info >
+ void set_swap( typename enable_if< is_equal_to_sixteen< Info > >::type* /* ptr */ = 0 )
+ {
+ png_set_swap( this->get_struct() );
+ }
+
+ template< typename Info >
+ void set_swap( typename enable_if< mpl::and_< mpl::not_< is_less_than_eight< Info > >
+ , mpl::not_< is_equal_to_sixteen< Info > >
+ >
+ >::type* /* ptr */ = 0
+ )
+ {}
+};
+
+///
+/// PNG Dynamic Image Writer
+///
+template< typename Device >
+class dynamic_image_writer< Device
+ , png_tag
+ >
+ : public writer< Device
+ , png_tag
+ >
+{
+ typedef writer< Device
+ , png_tag
+ > parent_t;
+
+public:
+
+ dynamic_image_writer( const Device& io_dev
+ , const image_write_info< png_tag >& info
+)
+ : parent_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename Views >
+ void apply( const any_image_view< Views >& views )
+ {
+ detail::dynamic_io_fnobj< detail::png_write_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( views, op );
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/detail/writer_backend.hpp b/boost/gil/extension/io/png/detail/writer_backend.hpp
new file mode 100644
index 0000000000..e018df79ea
--- /dev/null
+++ b/boost/gil/extension/io/png/detail/writer_backend.hpp
@@ -0,0 +1,516 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_DETAIL_WRITER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/io/typedefs.hpp>
+#include <boost/gil/io/base.hpp>
+
+#include <boost/gil/extension/io/png/tags.hpp>
+
+#include <boost/gil/extension/io/png/detail/base.hpp>
+#include <boost/gil/extension/io/png/detail/supported_types.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#pragma warning(disable:4611) //interaction between '_setjmp' and C++ object destruction is non-portable
+#endif
+
+///
+/// PNG Writer Backend
+///
+template< typename Device >
+struct writer_backend< Device
+ , png_tag
+ >
+ : public detail::png_struct_info_wrapper
+{
+
+private:
+
+ typedef writer_backend< Device
+ , png_tag
+ > this_t;
+
+public:
+
+ typedef png_tag format_tag_t;
+
+public:
+
+ ///
+ /// Constructor
+ ///
+ writer_backend( const Device& io_dev
+ , const image_write_info< png_tag >& info
+ )
+ : png_struct_info_wrapper( false )
+ , _io_dev( io_dev )
+ , _info( info )
+ {
+ // Create and initialize the png_struct with the desired error handler
+ // functions. If you want to use the default stderr and longjump method,
+ // you can supply NULL for the last three parameters. We also check that
+ // the library version is compatible with the one used at compile time,
+ // in case we are using dynamically linked libraries. REQUIRED.
+ get()->_struct = png_create_write_struct( PNG_LIBPNG_VER_STRING
+ , NULL // user_error_ptr
+ , NULL // user_error_fn
+ , NULL // user_warning_fn
+ );
+
+ io_error_if( get_struct() == NULL
+ , "png_writer: fail to call png_create_write_struct()"
+ );
+
+ // Allocate/initialize the image information data. REQUIRED
+ get()->_info = png_create_info_struct( get_struct() );
+
+ if( get_info() == NULL )
+ {
+ png_destroy_write_struct( &get()->_struct
+ , NULL
+ );
+
+ io_error( "png_writer: fail to call png_create_info_struct()" );
+ }
+
+ // Set error handling. REQUIRED if you aren't supplying your own
+ // error handling functions in the png_create_write_struct() call.
+ if( setjmp( png_jmpbuf( get_struct() )))
+ {
+ //free all of the memory associated with the png_ptr and info_ptr
+ png_destroy_write_struct( &get()->_struct
+ , &get()->_info
+ );
+
+ io_error( "png_writer: fail to call setjmp()" );
+ }
+
+ init_io( get_struct() );
+ }
+
+protected:
+
+ template< typename View >
+ void write_header( const View& view )
+ {
+ typedef detail::png_write_support< typename channel_type< typename get_pixel_type< View >::type >::type
+ , typename color_space_type< View >::type
+ > png_rw_info_t;
+
+ // Set the image information here. Width and height are up to 2^31,
+ // bit_depth is one of 1, 2, 4, 8, or 16, but valid values also depend on
+ // the color_type selected. color_type is one of PNG_COLOR_TYPE_GRAY,
+ // PNG_COLOR_TYPE_GRAY_ALPHA, PNG_COLOR_TYPE_PALETTE, PNG_COLOR_TYPE_RGB,
+ // or PNG_COLOR_TYPE_RGB_ALPHA. interlace is either PNG_INTERLACE_NONE or
+ // PNG_INTERLACE_ADAM7, and the compression_type and filter_type MUST
+ // currently be PNG_COMPRESSION_TYPE_BASE and PNG_FILTER_TYPE_BASE. REQUIRED
+ png_set_IHDR( get_struct()
+ , get_info()
+ , static_cast< png_image_width::type >( view.width() )
+ , static_cast< png_image_height::type >( view.height() )
+ , static_cast< png_bitdepth::type >( png_rw_info_t::_bit_depth )
+ , static_cast< png_color_type::type >( png_rw_info_t::_color_type )
+ , _info._interlace_method
+ , _info._compression_type
+ , _info._filter_method
+ );
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ if( _info._valid_cie_colors )
+ {
+ png_set_cHRM( get_struct()
+ , get_info()
+ , _info._white_x
+ , _info._white_y
+ , _info._red_x
+ , _info._red_y
+ , _info._green_x
+ , _info._green_y
+ , _info._blue_x
+ , _info._blue_y
+ );
+ }
+
+ if( _info._valid_file_gamma )
+ {
+ png_set_gAMA( get_struct()
+ , get_info()
+ , _info._file_gamma
+ );
+ }
+#else
+ if( _info._valid_cie_colors )
+ {
+ png_set_cHRM_fixed( get_struct()
+ , get_info()
+ , _info._white_x
+ , _info._white_y
+ , _info._red_x
+ , _info._red_y
+ , _info._green_x
+ , _info._green_y
+ , _info._blue_x
+ , _info._blue_y
+ );
+ }
+
+ if( _info._valid_file_gamma )
+ {
+ png_set_gAMA_fixed( get_struct()
+ , get_info()
+ , _info._file_gamma
+ );
+ }
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+ if( _info._valid_icc_profile )
+ {
+#if PNG_LIBPNG_VER_MINOR >= 5
+ png_set_iCCP( get_struct()
+ , get_info()
+ , const_cast< png_charp >( _info._icc_name.c_str() )
+ , _info._iccp_compression_type
+ , reinterpret_cast< png_const_bytep >( & (_info._profile.front ()) )
+ , _info._profile_length
+ );
+#else
+ png_set_iCCP( get_struct()
+ , get_info()
+ , const_cast< png_charp >( _info._icc_name.c_str() )
+ , _info._iccp_compression_type
+ , const_cast< png_charp >( & (_info._profile.front()) )
+ , _info._profile_length
+ );
+#endif
+ }
+
+ if( _info._valid_intent )
+ {
+ png_set_sRGB( get_struct()
+ , get_info()
+ , _info._intent
+ );
+ }
+
+ if( _info._valid_palette )
+ {
+ png_set_PLTE( get_struct()
+ , get_info()
+ , const_cast< png_colorp >( &_info._palette.front() )
+ , _info._num_palette
+ );
+ }
+
+ if( _info._valid_background )
+ {
+ png_set_bKGD( get_struct()
+ , get_info()
+ , const_cast< png_color_16p >( &_info._background )
+ );
+ }
+
+ if( _info._valid_histogram )
+ {
+ png_set_hIST( get_struct()
+ , get_info()
+ , const_cast< png_uint_16p >( &_info._histogram.front() )
+ );
+ }
+
+ if( _info._valid_offset )
+ {
+ png_set_oFFs( get_struct()
+ , get_info()
+ , _info._offset_x
+ , _info._offset_y
+ , _info._off_unit_type
+ );
+ }
+
+ if( _info._valid_pixel_calibration )
+ {
+ std::vector< const char* > params( _info._num_params );
+ for( std::size_t i = 0; i < params.size(); ++i )
+ {
+ params[i] = _info._params[ i ].c_str();
+ }
+
+ png_set_pCAL( get_struct()
+ , get_info()
+ , const_cast< png_charp >( _info._purpose.c_str() )
+ , _info._X0
+ , _info._X1
+ , _info._cal_type
+ , _info._num_params
+ , const_cast< png_charp >( _info._units.c_str() )
+ , const_cast< png_charpp >( &params.front() )
+ );
+ }
+
+ if( _info._valid_resolution )
+ {
+ png_set_pHYs( get_struct()
+ , get_info()
+ , _info._res_x
+ , _info._res_y
+ , _info._phy_unit_type
+ );
+ }
+
+ if( _info._valid_significant_bits )
+ {
+ png_set_sBIT( get_struct()
+ , get_info()
+ , const_cast< png_color_8p >( &_info._sig_bits )
+ );
+ }
+
+#ifndef BOOST_GIL_IO_PNG_1_4_OR_LOWER
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ if( _info._valid_scale_factors )
+ {
+ png_set_sCAL( get_struct()
+ , get_info()
+ , this->_info._scale_unit
+ , this->_info._scale_width
+ , this->_info._scale_height
+ );
+ }
+#else
+#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+ if( _info._valid_scale_factors )
+ {
+ png_set_sCAL_fixed( get_struct()
+ , get_info()
+ , this->_info._scale_unit
+ , this->_info._scale_width
+ , this->_info._scale_height
+ );
+ }
+#else
+ if( _info._valid_scale_factors )
+ {
+ png_set_sCAL_s( get_struct()
+ , get_info()
+ , this->_info._scale_unit
+ , const_cast< png_charp >( this->_info._scale_width.c_str() )
+ , const_cast< png_charp >( this->_info._scale_height.c_str() )
+ );
+ }
+
+#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+#endif // BOOST_GIL_IO_PNG_1_4_OR_LOWER
+
+ if( _info._valid_text )
+ {
+ std::vector< png_text > texts( _info._num_text );
+ for( std::size_t i = 0; i < texts.size(); ++i )
+ {
+ png_text pt;
+ pt.compression = _info._text[i]._compression;
+ pt.key = const_cast< png_charp >( this->_info._text[i]._key.c_str() );
+ pt.text = const_cast< png_charp >( this->_info._text[i]._text.c_str() );
+ pt.text_length = _info._text[i]._text.length();
+
+ texts[i] = pt;
+ }
+
+ png_set_text( get_struct()
+ , get_info()
+ , &texts.front()
+ , _info._num_text
+ );
+ }
+
+ if( _info._valid_modification_time )
+ {
+ png_set_tIME( get_struct()
+ , get_info()
+ , const_cast< png_timep >( &_info._mod_time )
+ );
+ }
+
+ if( _info._valid_transparency_factors )
+ {
+ int sample_max = ( 1u << _info._bit_depth );
+
+ /* libpng doesn't reject a tRNS chunk with out-of-range samples */
+ if( !( ( _info._color_type == PNG_COLOR_TYPE_GRAY
+ && (int) _info._trans_values[0].gray > sample_max
+ )
+ || ( _info._color_type == PNG_COLOR_TYPE_RGB
+ &&( (int) _info._trans_values[0].red > sample_max
+ || (int) _info._trans_values[0].green > sample_max
+ || (int) _info._trans_values[0].blue > sample_max
+ )
+ )
+ )
+ )
+ {
+ //@todo Fix that once reading transparency values works
+/*
+ png_set_tRNS( get_struct()
+ , get_info()
+ , trans
+ , num_trans
+ , trans_values
+ );
+*/
+ }
+ }
+
+ // Compression Levels - valid values are [0,9]
+ png_set_compression_level( get_struct()
+ , _info._compression_level
+ );
+
+ png_set_compression_mem_level( get_struct()
+ , _info._compression_mem_level
+ );
+
+ png_set_compression_strategy( get_struct()
+ , _info._compression_strategy
+ );
+
+ png_set_compression_window_bits( get_struct()
+ , _info._compression_window_bits
+ );
+
+ png_set_compression_method( get_struct()
+ , _info._compression_method
+ );
+
+ png_set_compression_buffer_size( get_struct()
+ , _info._compression_buffer_size
+ );
+
+#ifdef BOOST_GIL_IO_PNG_DITHERING_SUPPORTED
+ // Dithering
+ if( _info._set_dithering )
+ {
+ png_set_dither( get_struct()
+ , &_info._dithering_palette.front()
+ , _info._dithering_num_palette
+ , _info._dithering_maximum_colors
+ , &_info._dithering_histogram.front()
+ , _info._full_dither
+ );
+ }
+#endif // BOOST_GIL_IO_PNG_DITHERING_SUPPORTED
+
+ // Filter
+ if( _info._set_filter )
+ {
+ png_set_filter( get_struct()
+ , 0
+ , _info._filter
+ );
+ }
+
+ // Invert Mono
+ if( _info._invert_mono )
+ {
+ png_set_invert_mono( get_struct() );
+ }
+
+ // True Bits
+ if( _info._set_true_bits )
+ {
+ png_set_sBIT( get_struct()
+ , get_info()
+ , &_info._true_bits.front()
+ );
+ }
+
+ // sRGB Intent
+ if( _info._set_srgb_intent )
+ {
+ png_set_sRGB( get_struct()
+ , get_info()
+ , _info._srgb_intent
+ );
+ }
+
+ // Strip Alpha
+ if( _info._strip_alpha )
+ {
+ png_set_strip_alpha( get_struct() );
+ }
+
+ // Swap Alpha
+ if( _info._swap_alpha )
+ {
+ png_set_swap_alpha( get_struct() );
+ }
+
+
+ png_write_info( get_struct()
+ , get_info()
+ );
+ }
+
+protected:
+
+ static void write_data( png_structp png_ptr
+ , png_bytep data
+ , png_size_t length
+ )
+ {
+ static_cast< Device* >( png_get_io_ptr( png_ptr ))->write( data
+ , length );
+ }
+
+ static void flush( png_structp png_ptr )
+ {
+ static_cast< Device* >(png_get_io_ptr(png_ptr) )->flush();
+ }
+
+private:
+
+ void init_io( png_structp png_ptr )
+ {
+ png_set_write_fn( png_ptr
+ , static_cast< void* > ( &this->_io_dev )
+ , static_cast< png_rw_ptr > ( &this_t::write_data )
+ , static_cast< png_flush_ptr >( &this_t::flush )
+ );
+ }
+
+public:
+
+ Device _io_dev;
+
+ image_write_info< png_tag > _info;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/old.hpp b/boost/gil/extension/io/png/old.hpp
new file mode 100644
index 0000000000..217633661e
--- /dev/null
+++ b/boost/gil/extension/io/png/old.hpp
@@ -0,0 +1,179 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_OLD_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_OLD_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/png.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup PNG_IO
+/// \brief Returns the width and height of the PNG file at the specified location.
+/// Throws std::ios_base::failure if the location does not correspond to a valid PNG file
+template< typename String >
+inline
+point2< std::ptrdiff_t > png_read_dimensions( const String& filename )
+{
+ typedef typename get_reader_backend< String
+ , png_tag
+ >::type backend_t;
+
+ backend_t backend = read_image_info( filename
+ , png_tag()
+ );
+
+ return point2< std::ptrdiff_t >( backend._info._width
+ , backend._info._height
+ );
+}
+
+/// \ingroup PNG_IO
+/// \brief Loads the image specified by the given png image file name into the given view.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the PNG library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its color space or channel depth are not
+/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void png_read_view( const String& filename
+ , const View& view
+ )
+{
+ read_view( filename
+ , view
+ , png_tag()
+ );
+}
+
+/// \ingroup PNG_IO
+/// \brief Allocates a new image whose dimensions are determined by the given png image file, and loads the pixels into it.
+/// Triggers a compile assert if the image color space or channel depth are not supported by the PNG library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its color space or channel depth are not
+/// compatible with the ones specified by Image
+template< typename String
+ , typename Image
+ >
+inline
+void png_read_image( const String& filename
+ , Image& img
+ )
+{
+ read_image( filename
+ , img
+ , png_tag()
+ );
+}
+
+/// \ingroup PNG_IO
+/// \brief Loads the image specified by the given png image file name and color-converts it into the given view.
+/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ , typename CC
+ >
+inline
+void png_read_and_convert_view( const String& filename
+ , const View& view
+ , CC cc
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , cc
+ , png_tag()
+ );
+}
+
+/// \ingroup PNG_IO
+/// \brief Loads the image specified by the given png image file name and color-converts it into the given view.
+/// Throws std::ios_base::failure if the file is not a valid PNG file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void png_read_and_convert_view( const String& filename
+ , const View& view
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , png_tag()
+ );
+}
+
+/// \ingroup PNG_IO
+/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid PNG file
+template< typename String
+ , typename Image
+ , typename CC
+ >
+inline
+void png_read_and_convert_image( const String& filename
+ , Image& img
+ , CC cc
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , cc
+ , png_tag()
+ );
+}
+
+/// \ingroup PNG_IO
+/// \brief Allocates a new image whose dimensions are determined by the given png image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid PNG file
+template< typename String
+ , typename Image
+ >
+inline
+void png_read_and_convert_image( const String filename
+ , Image& img
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , png_tag()
+ );
+}
+
+/// \ingroup PNG_IO
+/// \brief Saves the view to a png file specified by the given png image file name.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the PNG library or by the I/O extension.
+/// Throws std::ios_base::failure if it fails to create the file.
+template< typename String
+ , typename View
+ >
+inline
+void png_write_view( const String& filename
+ , const View& view
+ )
+{
+ write_view( filename
+ , view
+ , png_tag()
+ );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/read.hpp b/boost/gil/extension/io/png/read.hpp
new file mode 100644
index 0000000000..32bbd7e01b
--- /dev/null
+++ b/boost/gil/extension/io/png/read.hpp
@@ -0,0 +1,43 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_READ_HPP
+
+#define BOOST_GIL_EXTENSION_IO_PNG_READ_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/png/tags.hpp>
+#include <boost/gil/extension/io/png/detail/supported_types.hpp>
+#include <boost/gil/extension/io/png/detail/read.hpp>
+#include <boost/gil/extension/io/png/detail/scanline_read.hpp>
+
+#include <boost/gil/io/get_reader.hpp>
+#include <boost/gil/io/make_backend.hpp>
+#include <boost/gil/io/make_reader.hpp>
+#include <boost/gil/io/make_dynamic_image_reader.hpp>
+#include <boost/gil/io/make_scanline_reader.hpp>
+
+#include <boost/gil/io/read_image.hpp>
+#include <boost/gil/io/read_view.hpp>
+#include <boost/gil/io/read_image_info.hpp>
+#include <boost/gil/io/read_and_convert_image.hpp>
+#include <boost/gil/io/read_and_convert_view.hpp>
+
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/png/tags.hpp b/boost/gil/extension/io/png/tags.hpp
new file mode 100644
index 0000000000..79e3b489a0
--- /dev/null
+++ b/boost/gil/extension/io/png/tags.hpp
@@ -0,0 +1,844 @@
+/*
+ Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_TAGS_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_TAGS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+# error "Cannot set both symbols"
+#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#endif
+ #include <png.h>
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#ifndef BOOST_GIL_EXTENSION_IO_ZLIB_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#endif
+ #include <zlib.h>
+#ifndef BOOST_GIL_EXTENSION_IO_ZLIB_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#if PNG_LIBPNG_VER_MAJOR == 1
+#if PNG_LIBPNG_VER_MINOR <= 4
+#define BOOST_GIL_IO_PNG_1_4_OR_LOWER
+#endif // PNG_LIBPNG_VER_MAJOR == 1
+#endif // PNG_LIBPNG_VER_MINOR <= 4
+
+#include <string>
+#include <vector>
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil {
+
+/// Defines png tag.
+struct png_tag : format_tag {};
+
+/// see http://en.wikipedia.org/wiki/Portable_Network_Graphics for reference
+
+/// Defines type for image width property.
+struct png_image_width : property_base< png_uint_32 > {};
+
+/// Defines type for image height property.
+struct png_image_height : property_base< png_uint_32 > {};
+
+/// Defines type for interlace method property.
+struct png_interlace_method : property_base< int > {};
+
+/// Defines type for filter method property.
+struct png_filter_method : property_base< int > {};
+
+/// Defines type for bit depth method property.
+struct png_bitdepth : property_base< int > {};
+
+/// Defines type for bit depth method property.
+struct png_color_type : property_base< int > {};
+
+/// Defines type for number of channels property.
+struct png_num_channels : property_base< png_byte > {};
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+ /// Defines type for CIE chromacities property.
+ struct png_chromacities_type : property_base< double > {};
+
+ /// Defines type for gamma correction property.
+ struct png_gamma : property_base< double > {};
+
+ /// Defines type for physical scale unit property.
+ struct png_unit : property_base< int > {};
+
+ /// Defines type for physical scale property.
+ struct png_scale : property_base< double > {};
+
+#else
+ /// Defines type for CIE chromacities property.
+ struct png_chromacities_type : property_base< png_fixed_point > {};
+
+ /// Defines type for gamma correction property.
+ struct png_gamma : property_base< png_fixed_point > {};
+
+ /// Defines type for physical scale unit property.
+ struct png_unit : property_base< int > {};
+
+#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+ /// Defines type for physical scale property.
+ struct png_scale : property_base< png_fixed_point > {};
+#else
+ /// Defines type for physical scale property.
+ struct png_scale : property_base< std::string > {};
+#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+/// Returns image resolution in pixels per meter, from pHYs chunk data.
+struct png_pixels_per_meter : property_base< png_uint_32 > {};
+
+/// Defines type for ICC profile name property.
+struct png_ICC_name : property_base< std::string > {};
+/// Defines type for ICC profile property.
+#if PNG_LIBPNG_VER_MINOR >= 5
+struct png_ICC_profile : property_base< std:: vector <uint8_t> > {};
+#else
+struct png_ICC_profile : property_base< std:: vector <char> > {};
+#endif
+/// Defines type for ICC profile length property.
+struct png_ICC_profile_length : property_base< png_uint_32 > {};
+/// Defines type for ICC compression property.
+struct png_ICC_compression_type : property_base< int > {};
+
+/// Defines type for rendering intent property.
+struct png_intent : property_base< int > {};
+
+/// Defines type for color palette property.
+struct png_color_palette : property_base< std::vector< png_color > > {};
+/// Defines type for number of colors property.
+struct png_num_palette : property_base< int > {};
+
+/// Defines type for background property.
+struct png_background : property_base< png_color_16 > {};
+
+/// Defines type for histogram property.
+struct png_histrogram : property_base< std::vector< png_uint_16 > > {};
+
+/// Defines type for screen offset property.
+struct png_offset : property_base< png_int_32 > {};
+/// Defines type for screen offset type property.
+struct png_offset_type : property_base< int > {};
+
+/// Defines type pixel calibration for property.
+struct png_CAL : property_base< std::string > {};
+/// Defines type for pixel calibration parameters property.
+struct png_CAL_params : property_base< std::vector< std::string > > {};
+/// Defines type for pixel calibration x property.
+struct png_CAL_X : property_base< png_int_32 > {};
+/// Defines type for pixel calibration type property.
+struct png_CAL_type : property_base< int > {};
+/// Defines type for number of pixel calibration properties.
+struct png_CAL_nparam : property_base< int > {};
+
+/// Defines type for physical resolution property.
+struct png_resolution : property_base< png_uint_32 > {};
+/// Defines type for physical resolution unit property.
+struct png_unit_type : property_base< int > {};
+
+/// Defines type for significant bits property.
+struct png_significant_bits : property_base< png_color_8 > {};
+
+/// Helper structure for reading text property.
+struct gil_io_png_text
+{
+ /// Compression type
+ int _compression;
+ // Key
+ std::string _key;
+ /// Text
+ std::string _text;
+};
+
+/// Defines type for text property.
+struct png_text_ : property_base< std::vector< gil_io_png_text > > {};
+/// Defines type for number of text property.
+struct png_num_text : property_base< int > {};
+
+/// Defines type for modification time property.
+struct png_mod_time : property_base< png_time > {};
+
+/// Defines type for transparency data property.
+struct png_trans : property_base< std::vector< png_byte > > {};
+/// Defines type for number of transparency data property.
+struct png_num_trans : property_base< int > {};
+/// Defines type for transparency data values property.
+struct png_trans_values : property_base< std::vector< png_color_16 > > {};
+
+/// Defines type for png function return type.
+struct png_return_value : property_base< png_uint_32 > {};
+
+////////////////////////
+// Write properties
+////////////////////////
+
+// relates to info_ptr->compression_type
+struct png_compression_type : property_base< png_byte >
+{
+ static const type default_value = PNG_COMPRESSION_TYPE_BASE;
+};
+
+// compression level - default values taken from libpng manual.
+// Look for png_set_compression_level
+struct png_compression_level : property_base< int >
+{
+ static const type default_value = 3;
+};
+
+struct png_compression_mem_level : property_base< int >
+{
+ static const type default_value = MAX_MEM_LEVEL;
+};
+
+struct png_compression_strategy : property_base< int >
+{
+ static const type default_value = Z_DEFAULT_STRATEGY;
+};
+
+struct png_compression_window_bits : property_base< int >
+{
+ static const type default_value = 9;
+};
+
+struct png_compression_method : property_base< int >
+{
+ static const type default_value = 8;
+};
+
+struct png_compression_buffer_size : property_base< int >
+{
+ static const type default_value = 8192;
+};
+
+// dithering
+struct png_dithering_palette : property_base< std::vector< png_color > >
+{};
+
+struct png_dithering_num_palette : property_base< int >
+{
+ static const type default_value = 0;
+};
+
+struct png_dithering_maximum_colors : property_base< int >
+{
+ static const type default_value = 0;
+};
+
+struct png_dithering_histogram : property_base< std::vector< png_uint_16 > >
+{};
+
+struct png_full_dither : property_base< int >
+{
+ static const type default_value = 0;
+};
+
+// filter
+struct png_filter : property_base< int >
+{
+ static const type default_value = 0;
+};
+
+// invert mono
+struct png_invert_mono : property_base< bool >
+{
+ static const type default_value = false;
+};
+
+// true bits
+struct png_true_bits : property_base< std::vector< png_color_8 > >
+{};
+
+// sRGB Intent
+struct png_srgb_intent : property_base< int >
+{
+ static const type default_value = 0;
+};
+
+// strip alpha
+struct png_strip_alpha : property_base< bool >
+{
+ static const type default_value = false;
+};
+
+struct png_swap_alpha : property_base< bool >
+{
+ static const type default_value = false;
+};
+
+
+/// PNG info base class. Containing all header information both for reading and writing.
+///
+/// This base structure was created to avoid code doubling.
+struct png_info_base
+{
+ /// Default constructor
+ png_info_base()
+ : _width ( 0 )
+ , _height( 0 )
+
+ , _bit_depth ( 0 )
+ , _color_type ( 0 )
+ , _interlace_method ( PNG_INTERLACE_NONE )
+ , _compression_method( PNG_COMPRESSION_TYPE_DEFAULT )
+ , _filter_method ( PNG_FILTER_TYPE_DEFAULT )
+
+ , _num_channels( 0 )
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ , _valid_cie_colors( 0 )
+ , _white_x ( 0.0 )
+ , _white_y ( 0.0 )
+ , _red_x ( 0.0 )
+ , _red_y ( 0.0 )
+ , _green_x ( 0.0 )
+ , _green_y ( 0.0 )
+ , _blue_x ( 0.0 )
+ , _blue_y ( 0.0 )
+
+ , _valid_file_gamma( 0 )
+ , _file_gamma ( 1.0 )
+#else
+ , _valid_cie_colors( 0 )
+ , _white_x ( 0 )
+ , _white_y ( 0 )
+ , _red_x ( 0 )
+ , _red_y ( 0 )
+ , _green_x ( 0 )
+ , _green_y ( 0 )
+ , _blue_x ( 0 )
+ , _blue_y ( 0 )
+
+ , _valid_file_gamma( 0 )
+ , _file_gamma ( 1 )
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+ , _valid_icc_profile ( 0 )
+ , _icc_name ( )
+ , _iccp_compression_type( PNG_COMPRESSION_TYPE_BASE )
+ , _profile ( )
+ , _profile_length ( 0 )
+
+ , _valid_intent( 0 )
+ , _intent ( 0 )
+
+ , _valid_palette( 0 )
+ , _palette ( )
+ , _num_palette ( 0 )
+
+ , _valid_background( 0 )
+ , _background ( )
+
+ , _valid_histogram( 0 )
+ , _histogram ( )
+
+ , _valid_offset ( 0 )
+ , _offset_x ( 0 )
+ , _offset_y ( 0 )
+ , _off_unit_type( PNG_OFFSET_PIXEL )
+
+ , _valid_pixel_calibration( 0 )
+ , _purpose ( )
+ , _X0 ( 0 )
+ , _X1 ( 0 )
+ , _cal_type ( 0 )
+ , _num_params ( 0 )
+ , _units ( )
+ , _params ( )
+
+ , _valid_resolution( 0 )
+ , _res_x ( 0 )
+ , _res_y ( 0 )
+ , _phy_unit_type ( PNG_RESOLUTION_UNKNOWN )
+
+ , _pixels_per_meter( 0 )
+
+ , _valid_significant_bits( 0 )
+ , _sig_bits ( )
+
+ , _valid_scale_factors( 0 )
+ , _scale_unit ( PNG_SCALE_UNKNOWN )
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+ , _scale_width ( 0.0 )
+ , _scale_height( 0.0 )
+#else
+#ifdef BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+ , _scale_width ( 0 )
+ , _scale_height( 0 )
+#else
+ , _scale_width ()
+ , _scale_height()
+#endif // BOOST_GIL_IO_PNG_FIXED_POINT_SUPPORTED
+#endif // BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+ , _valid_text( 0 )
+ , _text ( )
+ , _num_text ( 0 )
+
+ , _valid_modification_time( 0 )
+ , _mod_time ( )
+
+ , _valid_transparency_factors( 0 )
+ , _trans ( )
+ , _num_trans ( 0 )
+ , _trans_values ( )
+ {}
+
+ /// The image width.
+ png_image_width::type _width;
+ /// The image height.
+ png_image_height::type _height;
+
+ /// The bit depth per channel.
+ png_bitdepth::type _bit_depth;
+ /// The color space type.
+ png_color_type::type _color_type;
+ /// The interlace methos.
+ png_interlace_method::type _interlace_method;
+ /// The compression method.
+ png_compression_method::type _compression_method;
+ /// The filer method.
+ png_filter_method::type _filter_method;
+
+ /// The number of channels.
+ png_num_channels::type _num_channels;
+
+ // CIE chromacities
+ /// The return value when reading CIE chromacities.
+ png_return_value::type _valid_cie_colors;
+ /// The white x value.
+ png_chromacities_type::type _white_x;
+ /// The white y value.
+ png_chromacities_type::type _white_y;
+ /// The red x value.
+ png_chromacities_type::type _red_x;
+ /// The red y value.
+ png_chromacities_type::type _red_y;
+ /// The green x value.
+ png_chromacities_type::type _green_x;
+ /// The green y value.
+ png_chromacities_type::type _green_y;
+ /// The blue x value.
+ png_chromacities_type::type _blue_x;
+ /// The blue y value.
+ png_chromacities_type::type _blue_y;
+
+ // Gamma Value
+ /// The return value when reading gamma value.
+ png_return_value::type _valid_file_gamma;
+ /// The file gamma value.
+ png_gamma::type _file_gamma;
+
+ // Embedded ICC profile
+ /// The return value when reading ICC profile.
+ png_return_value::type _valid_icc_profile;
+ /// The ICC name.
+ png_ICC_name::type _icc_name;
+ /// The icc compression type.
+ png_ICC_compression_type::type _iccp_compression_type;
+ /// The ICC profile.
+ png_ICC_profile::type _profile;
+ /// The ICC profile length.
+ png_ICC_profile_length::type _profile_length;
+
+ // Rendering intent
+ /// The return value when reading rendering intent.
+ png_return_value::type _valid_intent;
+ /// The rendering intent value.
+ png_intent::type _intent;
+
+ // Image palette
+ /// The return value when reading image palette.
+ png_return_value::type _valid_palette;
+ /// The color palette.
+ png_color_palette::type _palette;
+ /// The number of colors in the palettes.
+ png_num_palette::type _num_palette;
+
+ // Background
+ /// The return value when reading background.
+ png_return_value::type _valid_background;
+ /// The background color.
+ png_background::type _background;
+
+ // Histogram
+ /// The return value when reading histogram.
+ png_return_value::type _valid_histogram;
+ /// The histogram.
+ png_histrogram::type _histogram;
+
+ // Screen offsets
+ /// The return value when reading screen offsets.
+ png_return_value::type _valid_offset;
+ /// The x offset.
+ png_offset::type _offset_x;
+ /// The y offset.
+ png_offset::type _offset_y;
+ /// The offset unit.
+ png_offset_type::type _off_unit_type;
+
+ // Pixel Calibration
+ /// The return value when reading pixel calibration.
+ png_return_value::type _valid_pixel_calibration;
+ /// The purpose.
+ png_CAL::type _purpose;
+ /// The x_0 value.
+ png_CAL_X::type _X0;
+ /// The x_1 value.
+ png_CAL_X::type _X1;
+ /// The calibration type.
+ png_CAL_type::type _cal_type;
+ /// The number of calibration parameters.
+ png_CAL_nparam::type _num_params;
+ /// The calibration unit type.
+ png_CAL::type _units;
+ /// The calibration parameters.
+ png_CAL_params::type _params;
+
+ // Physical resolution
+ /// The return value when reading physical resolution properties.
+ png_return_value::type _valid_resolution;
+ /// The x physical resolution.
+ png_resolution::type _res_x;
+ /// The y physical resolution.
+ png_resolution::type _res_y;
+ /// The physical resolution unit.
+ png_unit_type::type _phy_unit_type;
+
+ /// The Image resolution in pixels per meter.
+ png_pixels_per_meter::type _pixels_per_meter;
+
+ // Number of significant bits
+ /// The return value when reading significant bits.
+ png_return_value::type _valid_significant_bits;
+ /// The significant bits.
+ png_significant_bits::type _sig_bits;
+
+ // Scale Factors
+ /// The return value when reading scale factors.
+ png_return_value::type _valid_scale_factors;
+ /// The scaling unit.
+ png_unit::type _scale_unit;
+ /// The scaling width.
+ png_scale::type _scale_width;
+ /// The scaling height.
+ png_scale::type _scale_height;
+
+ // Comments information
+ /// The return value when reading image comments.
+ png_return_value::type _valid_text;
+ /// The comments.
+ png_text_::type _text;
+ /// The number of comments.
+ png_num_text::type _num_text;
+
+ // Last modification time
+ /// The return value when reading modification time.
+ png_return_value::type _valid_modification_time;
+ /// The modification time.
+ png_mod_time::type _mod_time;
+
+ // Transparency data
+ /// The return value when reading transparency data.
+ png_return_value::type _valid_transparency_factors;
+ /// The transparency data.
+ png_trans::type _trans;
+ /// The number of transparency data.
+ png_num_trans::type _num_trans;
+ /// The transparency data values.
+ png_trans_values::type _trans_values;
+};
+
+/// Read information for png images.
+///
+/// The structure is returned when using read_image_info.
+template<>
+struct image_read_info< png_tag > : public png_info_base
+{
+ /// Default constructor.
+ image_read_info< png_tag >()
+ : png_info_base()
+ {}
+};
+
+/// PNG settings base class.
+///
+/// This base structure was created to avoid code doubling.
+struct png_read_settings_base
+{
+ /// Default Constructor.
+ png_read_settings_base()
+ {
+ _read_cie_chromacities = false;
+ _read_file_gamma = false;
+ _read_icc_profile = false;
+ _read_intent = false;
+ _read_palette = false;
+ _read_background = false;
+ _read_histogram = false;
+ _read_screen_offsets = false;
+ _read_pixel_calibration = false;
+ _read_physical_resolution = false;
+ _read_pixels_per_meter = false;
+ _read_number_of_significant_bits = false;
+ _read_scale_factors = false;
+ _read_comments = false;
+ _read_last_modification_time = false;
+ _read_transparency_data = false;
+ }
+
+ /// Helper function to enabling reading all png properties.
+ void set_read_members_true()
+ {
+ _read_cie_chromacities = true;
+ _read_file_gamma = true;
+ _read_icc_profile = true;
+ _read_intent = true;
+ _read_palette = true;
+ _read_background = true;
+ _read_histogram = true;
+ _read_screen_offsets = true;
+ _read_pixel_calibration = true;
+ _read_physical_resolution = true;
+ _read_pixels_per_meter = true;
+ _read_number_of_significant_bits = true;
+ _read_scale_factors = true;
+ _read_comments = true;
+ _read_last_modification_time = true;
+ _read_transparency_data = true;
+ }
+
+ /// Enable reading CIE chromacities.
+ bool _read_cie_chromacities;
+ /// Enable reading file gamma.
+ bool _read_file_gamma;
+ /// Enable reading ICC profile.
+ bool _read_icc_profile;
+ /// Enable reading rendering intent.
+ bool _read_intent;
+ /// Enable reading color palette.
+ bool _read_palette;
+ /// Enable reading background color.
+ bool _read_background;
+ /// Enable reading histogram.
+ bool _read_histogram;
+ /// Enable reading screen offsets.
+ bool _read_screen_offsets;
+ /// Enable reading pixel calibration.
+ bool _read_pixel_calibration;
+ /// Enable reading physical resolution.
+ bool _read_physical_resolution;
+ /// Enable reading pixels per meter information.
+ bool _read_pixels_per_meter;
+ /// Enable reading significant bits.
+ bool _read_number_of_significant_bits;
+ /// Enable reading scaling factors.
+ bool _read_scale_factors;
+ /// Enable reading comments.
+ bool _read_comments;
+ /// Enable reading modification time.
+ bool _read_last_modification_time;
+ /// Enable reading transparency data.
+ bool _read_transparency_data;
+};
+
+#ifdef BOOST_GIL_IO_PNG_FLOATING_POINT_SUPPORTED
+
+/// Read settings for png images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< png_tag > : public image_read_settings_base
+ , public png_read_settings_base
+{
+ /// Default Constructor
+ image_read_settings< png_tag >()
+ : image_read_settings_base()
+ , png_read_settings_base()
+ , _screen_gamma( 1.0 )
+ {}
+
+ /// Constructor
+ /// \param top_left Top left coordinate for reading partial image.
+ /// \param dim Dimensions for reading partial image.
+ /// \param gamma Screen gamma value.
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ , const bool apply_screen_gamma = false
+ , const png_gamma::type& screen_gamma = 1.0
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ , png_read_settings_base()
+ , _apply_screen_gamma( apply_screen_gamma )
+ , _screen_gamma( screen_gamma )
+ {}
+
+ /// Apply screen gamma value.
+ bool _apply_screen_gamma;
+ /// The screen gamma value.
+ png_gamma::type _screen_gamma;
+};
+
+#else
+
+/// Read settings for png images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< png_tag > : public image_read_settings_base
+ , public png_read_settings_base
+{
+ /// Default Constructor.
+ image_read_settings< png_tag >()
+ : image_read_settings_base()
+ , png_read_settings_base()
+ , _apply_screen_gamma( false )
+ , _screen_gamma ( 2 )
+ {}
+
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ , png_read_settings_base()
+ , _apply_screen_gamma( false )
+ , _screen_gamma ( 2 )
+ {}
+
+ /// Apply screen gamma value.
+ bool _apply_screen_gamma;
+ /// The screen gamma value.
+ png_gamma::type _screen_gamma;
+};
+#endif
+
+/// Write information for png images.
+///
+/// The structure can be used for write_view() function.
+template<>
+struct image_write_info< png_tag > : public png_info_base
+{
+ image_write_info( const png_compression_type::type compression_type = png_compression_type::default_value
+ , const png_compression_level::type compression_level = png_compression_level::default_value
+ , const png_compression_mem_level::type compression_mem_level = png_compression_mem_level::default_value
+ , const png_compression_strategy::type compression_strategy = png_compression_strategy::default_value
+ , const png_compression_window_bits::type compression_window_bits = png_compression_window_bits::default_value
+ , const png_compression_method::type compression_method = png_compression_method::default_value
+ , const png_compression_buffer_size::type compression_buffer_size = png_compression_buffer_size::default_value
+ , const png_dithering_num_palette::type num_palette = png_dithering_num_palette::default_value
+ , const png_dithering_maximum_colors::type maximum_colors = png_dithering_maximum_colors::default_value
+ , const png_full_dither::type full_dither = png_full_dither::default_value
+ , const png_filter::type filter = png_filter::default_value
+ , const png_invert_mono::type invert_mono = png_invert_mono::default_value
+ , const png_srgb_intent::type srgb_intent = png_srgb_intent::default_value
+ , const png_strip_alpha::type strip_alpha = png_strip_alpha::default_value
+ , const png_swap_alpha::type swap_alpha = png_swap_alpha::default_value
+ )
+ : png_info_base()
+ , _compression_type( compression_type )
+ , _compression_level( compression_level )
+ , _compression_mem_level( compression_mem_level )
+ , _compression_strategy( compression_strategy )
+ , _compression_window_bits( compression_window_bits )
+ , _compression_method( compression_method )
+ , _compression_buffer_size( compression_buffer_size )
+
+ , _set_dithering( false )
+ , _dithering_palette()
+ , _dithering_num_palette( num_palette )
+ , _dithering_maximum_colors( maximum_colors )
+ , _dithering_histogram()
+ , _full_dither( full_dither )
+
+ , _set_filter( false )
+ , _filter( filter )
+
+ , _invert_mono( invert_mono )
+
+ , _set_true_bits( false )
+ , _true_bits()
+
+ , _set_srgb_intent( false )
+ , _srgb_intent( srgb_intent )
+
+ , _strip_alpha( strip_alpha )
+
+ , _swap_alpha( swap_alpha )
+ {}
+
+ // compression stuff
+ png_compression_type::type _compression_type;
+ png_compression_level::type _compression_level;
+ png_compression_mem_level::type _compression_mem_level;
+ png_compression_strategy::type _compression_strategy;
+ png_compression_window_bits::type _compression_window_bits;
+ png_compression_method::type _compression_method;
+ png_compression_buffer_size::type _compression_buffer_size;
+
+ // png_set_dither
+ bool _set_dithering;
+ png_dithering_palette::type _dithering_palette;
+ png_dithering_num_palette::type _dithering_num_palette;
+ png_dithering_maximum_colors::type _dithering_maximum_colors;
+ png_dithering_histogram::type _dithering_histogram;
+ png_full_dither::type _full_dither;
+
+ //png_set_filter
+ bool _set_filter;
+ png_filter::type _filter;
+
+ // png_set_invert_mono
+ png_invert_mono::type _invert_mono;
+
+ // png_set_sBIT
+ bool _set_true_bits;
+ png_true_bits::type _true_bits;
+
+ // png_set_sRGB
+ bool _set_srgb_intent;
+ png_srgb_intent::type _srgb_intent;
+
+ // png_set_strip_alpha
+ png_strip_alpha::type _strip_alpha;
+
+ // png_set_swap_alpha
+ png_swap_alpha::type _swap_alpha;
+
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/png/write.hpp b/boost/gil/extension/io/png/write.hpp
new file mode 100644
index 0000000000..47d2a8ae78
--- /dev/null
+++ b/boost/gil/extension/io/png/write.hpp
@@ -0,0 +1,31 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNG_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_PNG_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/png/tags.hpp>
+#include <boost/gil/extension/io/png/detail/supported_types.hpp>
+#include <boost/gil/extension/io/png/detail/write.hpp>
+
+#include <boost/gil/io/make_writer.hpp>
+#include <boost/gil/io/make_dynamic_image_writer.hpp>
+
+#include <boost/gil/io/write_view.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/png_dynamic_io.hpp b/boost/gil/extension/io/png_dynamic_io.hpp
deleted file mode 100644
index a3a25a97f4..0000000000
--- a/boost/gil/extension/io/png_dynamic_io.hpp
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/png_io.hpp b/boost/gil/extension/io/png_io.hpp
deleted file mode 100644
index 9b57cebb86..0000000000
--- a/boost/gil/extension/io/png_io.hpp
+++ /dev/null
@@ -1,214 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/png_io_private.hpp b/boost/gil/extension/io/png_io_private.hpp
deleted file mode 100644
index a0ee57be55..0000000000
--- a/boost/gil/extension/io/png_io_private.hpp
+++ /dev/null
@@ -1,360 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/pnm.hpp b/boost/gil/extension/io/pnm.hpp
new file mode 100644
index 0000000000..8e69277fce
--- /dev/null
+++ b/boost/gil/extension/io/pnm.hpp
@@ -0,0 +1,25 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/pnm/read.hpp>
+#include <boost/gil/extension/io/pnm/write.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/pnm/detail/is_allowed.hpp b/boost/gil/extension/io/pnm/detail/is_allowed.hpp
new file mode 100644
index 0000000000..91be3091fa
--- /dev/null
+++ b/boost/gil/extension/io/pnm/detail/is_allowed.hpp
@@ -0,0 +1,60 @@
+/*
+ Copyright 2009 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_IS_ALLOWED_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_IS_ALLOWED_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil { namespace detail {
+
+template< typename View >
+bool is_allowed( const image_read_info< pnm_tag >& info
+ , mpl::true_ // is read_and_no_convert
+ )
+{
+ pnm_image_type::type asc_type = is_read_supported< typename get_pixel_type< View >::type
+ , pnm_tag
+ >::_asc_type;
+
+ pnm_image_type::type bin_type = is_read_supported< typename get_pixel_type< View >::type
+ , pnm_tag
+ >::_bin_type;
+ if( info._type == pnm_image_type::mono_asc_t::value )
+ {
+ // ascii mono images are read gray8_image_t
+ return ( asc_type == pnm_image_type::gray_asc_t::value );
+ }
+
+
+ return ( asc_type == info._type
+ || bin_type == info._type
+ );
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< pnm_tag >& /* info */
+ , mpl::false_ // is read_and_convert
+ )
+{
+ return true;
+}
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/detail/read.hpp b/boost/gil/extension/io/pnm/detail/read.hpp
new file mode 100644
index 0000000000..5f267ada5e
--- /dev/null
+++ b/boost/gil/extension/io/pnm/detail/read.hpp
@@ -0,0 +1,465 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+#include <boost/bind.hpp>
+#include <boost/gil.hpp>
+#include <boost/gil/extension/io/pnm/tags.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/pnm/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/pnm/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// PNM Reader
+///
+template< typename Device
+ , typename ConversionPolicy
+ >
+class reader< Device
+ , pnm_tag
+ , ConversionPolicy
+ >
+ : public reader_base< pnm_tag
+ , ConversionPolicy
+ >
+ , public reader_backend< Device
+ , pnm_tag
+ >
+{
+
+private:
+
+ typedef reader< Device
+ , pnm_tag
+ , ConversionPolicy
+ > this_t;
+
+ typedef typename ConversionPolicy::color_converter_type cc_t;
+
+public:
+
+ typedef reader_backend< Device, pnm_tag > backend_t;
+
+public:
+
+ reader( const Device& io_dev
+ , const image_read_settings< pnm_tag >& settings
+ )
+ : reader_base< pnm_tag
+ , ConversionPolicy
+ >()
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ reader( const Device& io_dev
+ , const cc_t& cc
+ , const image_read_settings< pnm_tag >& settings
+ )
+ : reader_base< pnm_tag
+ , ConversionPolicy
+ >( cc )
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ template<typename View>
+ void apply( const View& view )
+ {
+ typedef typename is_same< ConversionPolicy
+ , detail::read_and_no_convert
+ >::type is_read_and_convert_t;
+
+ io_error_if( !detail::is_allowed< View >( this->_info
+ , is_read_and_convert_t()
+ )
+ , "Image types aren't compatible."
+ );
+
+ switch( this->_info._type )
+ {
+ // reading mono text is reading grayscale but with only two values
+ case pnm_image_type::mono_asc_t::value:
+ case pnm_image_type::gray_asc_t::value:
+ {
+ this->_scanline_length = this->_info._width;
+
+ read_text_data< gray8_view_t >( view );
+
+ break;
+ }
+
+ case pnm_image_type::color_asc_t::value:
+ {
+ this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
+
+ read_text_data< rgb8_view_t >( view );
+
+ break;
+ }
+
+ case pnm_image_type::mono_bin_t::value:
+ {
+ //gray1_image_t
+ this->_scanline_length = ( this->_info._width + 7 ) >> 3;
+
+ read_bin_data< gray1_image_t::view_t >( view );
+
+ break;
+ }
+
+ case pnm_image_type::gray_bin_t::value:
+ {
+ // gray8_image_t
+ this->_scanline_length = this->_info._width;
+
+ read_bin_data< gray8_view_t >( view );
+
+ break;
+ }
+
+ case pnm_image_type::color_bin_t::value:
+ {
+ // rgb8_image_t
+ this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
+
+ read_bin_data< rgb8_view_t >( view );
+ break;
+ }
+ }
+ }
+
+private:
+
+ template< typename View_Src
+ , typename View_Dst
+ >
+ void read_text_data( const View_Dst& dst )
+ {
+ typedef typename View_Dst::y_coord_t y_t;
+
+ byte_vector_t row( this->_scanline_length );
+
+ //Skip scanlines if necessary.
+ for( int y = 0; y < this->_settings._top_left.y; ++y )
+ {
+ read_text_row< View_Src >( dst, row, y, false );
+ }
+
+ for( y_t y = 0; y < dst.height(); ++y )
+ {
+ read_text_row< View_Src >( dst, row, y, true );
+ }
+ }
+
+ template< typename View_Src
+ , typename View_Dst
+ >
+ void read_text_row( const View_Dst& dst
+ , byte_vector_t& row
+ , typename View_Dst::y_coord_t y
+ , bool process
+ )
+ {
+ View_Src src = interleaved_view( this->_info._width
+ , 1
+ , (typename View_Src::value_type*) &row.front()
+ , this->_scanline_length
+ );
+
+ for( uint32_t x = 0; x < this->_scanline_length; ++x )
+ {
+ for( uint32_t k = 0; ; )
+ {
+ int ch = this->_io_dev.getc_unchecked();
+
+ if( isdigit( ch ))
+ {
+ buf[ k++ ] = static_cast< char >( ch );
+ }
+ else if( k )
+ {
+ buf[ k ] = 0;
+ break;
+ }
+ else if( ch == EOF || !isspace( ch ))
+ {
+ return;
+ }
+ }
+
+ if( process )
+ {
+ int value = atoi( buf );
+
+ if( this->_info._max_value == 1 )
+ {
+ typedef typename channel_type< typename get_pixel_type< View_Dst >::type >::type channel_t;
+
+ // for pnm format 0 is white
+ row[x] = ( value != 0 )
+ ? typename channel_traits< channel_t >::value_type( 0 )
+ : channel_traits< channel_t >::max_value();
+ }
+ else
+ {
+ row[x] = static_cast< byte_t >( value );
+ }
+ }
+ }
+
+ if( process )
+ {
+ // We are reading a gray1_image like a gray8_image but the two pixel_t
+ // aren't compatible. Though, read_and_no_convert::read(...) wont work.
+ copy_data< View_Dst
+ , View_Src >( dst
+ , src
+ , y
+ , typename is_same< View_Dst
+ , gray1_image_t::view_t
+ >::type()
+ );
+ }
+ }
+
+ template< typename View_Dst
+ , typename View_Src
+ >
+ void copy_data( const View_Dst& dst
+ , const View_Src& src
+ , typename View_Dst::y_coord_t y
+ , mpl::true_ // is gray1_view
+ )
+ {
+ if( this->_info._max_value == 1 )
+ {
+ typename View_Dst::x_iterator it = dst.row_begin( y );
+
+ for( typename View_Dst::x_coord_t x = 0
+ ; x < dst.width()
+ ; ++x
+ )
+ {
+ it[x] = src[x];
+ }
+ }
+ else
+ {
+ copy_data( dst
+ , src
+ , y
+ , mpl::false_()
+ );
+ }
+ }
+
+ template< typename View_Dst
+ , typename View_Src
+ >
+ void copy_data( const View_Dst& view
+ , const View_Src& src
+ , typename View_Dst::y_coord_t y
+ , mpl::false_ // is gray1_view
+ )
+ {
+ typename View_Src::x_iterator beg = src.row_begin( 0 ) + this->_settings._top_left.x;
+ typename View_Src::x_iterator end = beg + this->_settings._dim.x;
+
+ this->_cc_policy.read( beg
+ , end
+ , view.row_begin( y )
+ );
+ }
+
+
+ template< typename View_Src
+ , typename View_Dst
+ >
+ void read_bin_data( const View_Dst& view )
+ {
+ typedef typename View_Dst::y_coord_t y_t;
+ typedef typename is_bit_aligned<
+ typename View_Src::value_type >::type is_bit_aligned_t;
+
+ typedef detail::row_buffer_helper_view< View_Src > rh_t;
+ rh_t rh( this->_scanline_length, true );
+
+ typename rh_t::iterator_t beg = rh.begin() + this->_settings._top_left.x;
+ typename rh_t::iterator_t end = beg + this->_settings._dim.x;
+
+ // For bit_aligned images we need to negate all bytes in the row_buffer
+ // to make sure that 0 is black and 255 is white.
+ detail::negate_bits< typename rh_t::buffer_t
+ , is_bit_aligned_t
+ > neg;
+
+ detail::swap_half_bytes< typename rh_t::buffer_t
+ , is_bit_aligned_t
+ > swhb;
+
+ //Skip scanlines if necessary.
+ for( y_t y = 0; y < this->_settings._top_left.y; ++y )
+ {
+ this->_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
+ , this->_scanline_length
+ );
+ }
+
+ for( y_t y = 0; y < view.height(); ++y )
+ {
+ this->_io_dev.read( reinterpret_cast< byte_t* >( rh.data() )
+ , this->_scanline_length
+ );
+
+ neg( rh.buffer() );
+ swhb( rh.buffer() );
+
+ this->_cc_policy.read( beg
+ , end
+ , view.row_begin( y )
+ );
+ }
+ }
+
+private:
+
+ char buf[16];
+
+};
+
+
+namespace detail {
+
+struct pnm_type_format_checker
+{
+ pnm_type_format_checker( pnm_image_type::type type )
+ : _type( type )
+ {}
+
+ template< typename Image >
+ bool apply()
+ {
+ typedef is_read_supported< typename get_pixel_type< typename Image::view_t >::type
+ , pnm_tag
+ > is_supported_t;
+
+ return is_supported_t::_asc_type == _type
+ || is_supported_t::_bin_type == _type;
+ }
+
+private:
+
+ pnm_image_type::type _type;
+};
+
+struct pnm_read_is_supported
+{
+ template< typename View >
+ struct apply : public is_read_supported< typename get_pixel_type< View >::type
+ , pnm_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+///
+/// PNM Dynamic Image Reader
+///
+template< typename Device
+ >
+class dynamic_image_reader< Device
+ , pnm_tag
+ >
+ : public reader< Device
+ , pnm_tag
+ , detail::read_and_no_convert
+ >
+{
+ typedef reader< Device
+ , pnm_tag
+ , detail::read_and_no_convert
+ > parent_t;
+
+public:
+
+ dynamic_image_reader( const Device& io_dev
+ , const image_read_settings< pnm_tag >& settings
+ )
+ : parent_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename Images >
+ void apply( any_image< Images >& images )
+ {
+ detail::pnm_type_format_checker format_checker( this->_info._type );
+
+ if( !construct_matched( images
+ , format_checker
+ ))
+ {
+ io_error( "No matching image type between those of the given any_image and that of the file" );
+ }
+ else
+ {
+ this->init_image( images
+ , this->_settings
+ );
+
+ detail::dynamic_io_fnobj< detail::pnm_read_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( view( images )
+ , op
+ );
+ }
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/detail/reader_backend.hpp b/boost/gil/extension/io/pnm/detail/reader_backend.hpp
new file mode 100644
index 0000000000..01ab7a0aaa
--- /dev/null
+++ b/boost/gil/extension/io/pnm/detail/reader_backend.hpp
@@ -0,0 +1,192 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_READER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/pnm/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// PNM Backend
+///
+template< typename Device >
+struct reader_backend< Device
+ , pnm_tag
+ >
+{
+public:
+
+ typedef pnm_tag format_tag_t;
+
+public:
+
+ reader_backend( const Device& io_dev
+ , const image_read_settings< pnm_tag >& settings
+ )
+ : _io_dev ( io_dev )
+ , _settings( settings )
+ , _info()
+
+ , _scanline_length( 0 )
+ {
+ read_header();
+
+ if( _settings._dim.x == 0 )
+ {
+ _settings._dim.x = _info._width;
+ }
+
+ if( _settings._dim.y == 0 )
+ {
+ _settings._dim.y = _info._height;
+ }
+ }
+
+ void read_header()
+ {
+ // read signature
+ io_error_if( read_char() != 'P', "Invalid PNM signature" );
+
+ _info._type = read_char() - '0';
+
+ io_error_if( _info._type < pnm_image_type::mono_asc_t::value || _info._type > pnm_image_type::color_bin_t::value
+ , "Invalid PNM file (supports P1 to P6)"
+ );
+
+ _info._width = read_int();
+ _info._height = read_int();
+
+ if( _info._type == pnm_image_type::mono_asc_t::value || _info._type == pnm_image_type::mono_bin_t::value )
+ {
+ _info._max_value = 1;
+ }
+ else
+ {
+ _info._max_value = read_int();
+
+ io_error_if( _info._max_value > 255
+ , "Unsupported PNM format (supports maximum value 255)"
+ );
+ }
+ }
+
+ /// Check if image is large enough.
+ void check_image_size( const point_t& img_dim )
+ {
+ if( _settings._dim.x > 0 )
+ {
+ if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
+ }
+
+
+ if( _settings._dim.y > 0 )
+ {
+ if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
+ }
+ }
+
+private:
+
+ // Read a character and skip a comment if necessary.
+ char read_char()
+ {
+ char ch;
+
+ if(( ch = _io_dev.getc() ) == '#' )
+ {
+ // skip comment to EOL
+ do
+ {
+ ch = _io_dev.getc();
+ }
+ while (ch != '\n' && ch != '\r');
+ }
+
+ return ch;
+ }
+
+ unsigned int read_int()
+ {
+ char ch;
+
+ // skip whitespaces, tabs, and new lines
+ do
+ {
+ ch = read_char();
+ }
+ while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r');
+
+ if( ch < '0' || ch > '9' )
+ {
+ io_error( "Unexpected characters reading decimal digits" );
+ }
+
+ unsigned val = 0;
+
+ do
+ {
+ unsigned dig = ch - '0';
+
+ if( val > INT_MAX / 10 - dig )
+ {
+ io_error( "Integer too large" );
+ }
+
+ val = val * 10 + dig;
+
+ ch = read_char();
+ }
+ while( '0' <= ch && ch <= '9' );
+
+ return val;
+ }
+
+
+public:
+
+ Device _io_dev;
+
+ image_read_settings< pnm_tag > _settings;
+ image_read_info< pnm_tag > _info;
+
+ std::size_t _scanline_length;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/detail/scanline_read.hpp b/boost/gil/extension/io/pnm/detail/scanline_read.hpp
new file mode 100644
index 0000000000..b109528145
--- /dev/null
+++ b/boost/gil/extension/io/pnm/detail/scanline_read.hpp
@@ -0,0 +1,259 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_SCANLINE_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_SCANLINE_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+#include <boost/gil.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/scanline_read_iterator.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/pnm/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/pnm/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+///
+/// PNM Reader
+///
+template< typename Device >
+class scanline_reader< Device
+ , pnm_tag
+ >
+ : public reader_backend< Device
+ , pnm_tag
+ >
+{
+public:
+
+ typedef pnm_tag tag_t;
+ typedef reader_backend < Device, tag_t > backend_t;
+ typedef scanline_reader< Device, tag_t > this_t;
+ typedef scanline_read_iterator< this_t > iterator_t;
+
+
+public:
+ scanline_reader( Device& device
+ , const image_read_settings< pnm_tag >& settings
+ )
+ : backend_t( device
+ , settings
+ )
+ {
+ initialize();
+ }
+
+ /// Read part of image defined by View and return the data.
+ void read( byte_t* dst
+ , int
+ )
+ {
+ _read_function( this, dst );
+ }
+
+ /// Skip over a scanline.
+ void skip( byte_t*, int )
+ {
+ _skip_function( this );
+ }
+
+ iterator_t begin() { return iterator_t( *this ); }
+ iterator_t end() { return iterator_t( *this, this->_info._height ); }
+
+private:
+
+ void initialize()
+ {
+ switch( this->_info._type )
+ {
+ // reading mono text is reading grayscale but with only two values
+ case pnm_image_type::mono_asc_t::value:
+ case pnm_image_type::gray_asc_t::value:
+ {
+ this->_scanline_length = this->_info._width;
+
+ _read_function = boost::mem_fn( &this_t::read_text_row );
+ _skip_function = boost::mem_fn( &this_t::skip_text_row );
+
+ break;
+ }
+
+ case pnm_image_type::color_asc_t::value:
+ {
+ this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
+
+ _read_function = boost::mem_fn( &this_t::read_text_row );
+ _skip_function = boost::mem_fn( &this_t::skip_text_row );
+
+ break;
+ }
+
+
+ case pnm_image_type::mono_bin_t::value:
+ {
+ //gray1_image_t
+ this->_scanline_length = ( this->_info._width + 7 ) >> 3;
+
+ _read_function = boost::mem_fn( &this_t::read_binary_bit_row );
+ _skip_function = boost::mem_fn( &this_t::skip_binary_row );
+
+ break;
+ }
+
+ case pnm_image_type::gray_bin_t::value:
+ {
+ // gray8_image_t
+ this->_scanline_length = this->_info._width;
+
+ _read_function = boost::mem_fn( &this_t::read_binary_byte_row );
+ _skip_function = boost::mem_fn( &this_t::skip_binary_row );
+
+ break;
+ }
+
+ case pnm_image_type::color_bin_t::value:
+ {
+ // rgb8_image_t
+ this->_scanline_length = this->_info._width * num_channels< rgb8_view_t >::value;
+
+ _read_function = boost::mem_fn( &this_t::read_binary_byte_row );
+ _skip_function = boost::mem_fn( &this_t::skip_binary_row );
+
+ break;
+ }
+
+ default: { io_error( "Unsupported pnm file." ); break; }
+ }
+ }
+
+ void read_text_row( byte_t* dst )
+ {
+ for( std::size_t x = 0; x < this->_scanline_length; ++x )
+ {
+ for( uint32_t k = 0; ; )
+ {
+ int ch = this->_io_dev.getc_unchecked();
+
+ if( isdigit( ch ))
+ {
+ _text_buffer[ k++ ] = static_cast< char >( ch );
+ }
+ else if( k )
+ {
+ _text_buffer[ k ] = 0;
+ break;
+ }
+ else if( ch == EOF || !isspace( ch ))
+ {
+ return;
+ }
+ }
+
+ int value = atoi( _text_buffer );
+
+ if( this->_info._max_value == 1 )
+ {
+ // for pnm format 0 is white
+ dst[x] = ( value != 0 )
+ ? 0
+ : 255;
+ }
+ else
+ {
+ dst[x] = static_cast< byte_t >( value );
+ }
+ }
+ }
+
+ void skip_text_row()
+ {
+ for( std::size_t x = 0; x < this->_scanline_length; ++x )
+ {
+ for( uint32_t k = 0; ; )
+ {
+ int ch = this->_io_dev.getc_unchecked();
+
+ if( isdigit( ch ))
+ {
+ k++;
+ }
+ else if( k )
+ {
+ break;
+ }
+ else if( ch == EOF || !isspace( ch ))
+ {
+ return;
+ }
+ }
+ }
+ }
+
+
+ void read_binary_bit_row( byte_t* dst )
+ {
+ this->_io_dev.read( dst
+ , this->_scanline_length
+ );
+
+ _negate_bits ( dst, this->_scanline_length );
+ _swap_half_bytes( dst, this->_scanline_length );
+
+ }
+
+ void read_binary_byte_row( byte_t* dst )
+ {
+ this->_io_dev.read( dst
+ , this->_scanline_length
+ );
+ }
+
+ void skip_binary_row()
+ {
+ this->_io_dev.seek( static_cast<long>( this->_scanline_length ), SEEK_CUR );
+ }
+
+private:
+
+ char _text_buffer[16];
+
+ // For bit_aligned images we need to negate all bytes in the row_buffer
+ // to make sure that 0 is black and 255 is white.
+ detail::negate_bits < std::vector< byte_t >, mpl::true_ > _negate_bits;
+ detail::swap_half_bytes< std::vector< byte_t >, mpl::true_ > _swap_half_bytes;
+
+ boost::function< void ( this_t*, byte_t* ) > _read_function;
+ boost::function< void ( this_t* ) > _skip_function;
+};
+
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/detail/supported_types.hpp b/boost/gil/extension/io/pnm/detail/supported_types.hpp
new file mode 100644
index 0000000000..7bede91402
--- /dev/null
+++ b/boost/gil/extension/io/pnm/detail/supported_types.hpp
@@ -0,0 +1,146 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_SUPPORTED_TYPES_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_SUPPORTED_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/gil/channel.hpp>
+#include <boost/gil/color_base.hpp>
+
+namespace boost { namespace gil { namespace detail {
+
+// Read Support
+
+template< pnm_image_type::type ASCII_Type
+ , pnm_image_type::type Binary_Type
+ >
+struct pnm_rw_support_base
+{
+ static const pnm_image_type::type _asc_type = ASCII_Type;
+ static const pnm_image_type::type _bin_type = Binary_Type;
+};
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct pnm_read_support : read_support_false
+ , pnm_rw_support_base< 0
+ , 0
+ > {};
+
+template< typename BitField, bool Mutable >
+struct pnm_read_support< packed_dynamic_channel_reference< BitField
+ , 1
+ , Mutable
+ >
+ , gray_t
+ > : read_support_true
+ , pnm_rw_support_base< pnm_image_type::mono_asc_t::value
+ , pnm_image_type::mono_bin_t::value
+ > {};
+
+template<>
+struct pnm_read_support<uint8_t
+ , gray_t
+ > : read_support_true
+ , pnm_rw_support_base< pnm_image_type::gray_asc_t::value
+ , pnm_image_type::gray_bin_t::value
+ > {};
+
+
+template<>
+struct pnm_read_support<uint8_t
+ , rgb_t
+ > : read_support_true
+ , pnm_rw_support_base< pnm_image_type::color_asc_t::value
+ , pnm_image_type::color_bin_t::value
+ > {};
+
+// Write support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct pnm_write_support : write_support_false
+{};
+
+template< typename BitField, bool Mutable >
+struct pnm_write_support< packed_dynamic_channel_reference< BitField
+ , 1
+ , Mutable
+ >
+ , gray_t
+ > : write_support_true
+ , pnm_rw_support_base< pnm_image_type::mono_asc_t::value
+ , pnm_image_type::mono_bin_t::value
+ > {};
+
+
+template<>
+struct pnm_write_support<uint8_t
+ , gray_t
+ > : write_support_true
+ , pnm_rw_support_base< pnm_image_type::gray_asc_t::value
+ , pnm_image_type::gray_bin_t::value
+ > {};
+
+
+template<>
+struct pnm_write_support<uint8_t
+ , rgb_t
+ > : write_support_true
+ , pnm_rw_support_base< pnm_image_type::color_asc_t::value
+ , pnm_image_type::color_bin_t::value
+ > {};
+
+} // namespace detail
+
+template< typename Pixel >
+struct is_read_supported< Pixel
+ , pnm_tag
+ >
+ : mpl::bool_< detail::pnm_read_support< typename channel_type < Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ >
+{
+ typedef detail::pnm_read_support< typename channel_type < Pixel >::type
+ , typename color_space_type< Pixel >::type
+ > parent_t;
+
+ static const pnm_image_type::type _asc_type = parent_t::_asc_type;
+ static const pnm_image_type::type _bin_type = parent_t::_bin_type;
+};
+
+template< typename Pixel >
+struct is_write_supported< Pixel
+ , pnm_tag
+ >
+ : mpl::bool_< detail::pnm_write_support< typename channel_type < Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ > {};
+
+} // namespace gil
+} // namespace boost
+
+
+#endif
diff --git a/boost/gil/extension/io/pnm/detail/write.hpp b/boost/gil/extension/io/pnm/detail/write.hpp
new file mode 100644
index 0000000000..f92307c9c8
--- /dev/null
+++ b/boost/gil/extension/io/pnm/detail/write.hpp
@@ -0,0 +1,268 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <cstdlib>
+#include <string>
+
+#include <boost/gil/extension/io/pnm/tags.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+
+#include <boost/gil/extension/io/pnm/detail/writer_backend.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+namespace detail {
+
+struct pnm_write_is_supported
+{
+ template< typename View >
+ struct apply
+ : public is_write_supported< typename get_pixel_type< View >::type
+ , pnm_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+///
+/// PNM Writer
+///
+template< typename Device >
+class writer< Device
+ , pnm_tag
+ >
+ : public writer_backend< Device
+ , pnm_tag
+ >
+{
+private:
+ typedef writer_backend< Device, pnm_tag > backend_t;
+
+public:
+
+ writer( const Device& io_dev
+ , const image_write_info< pnm_tag >& info
+ )
+ : backend_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename View >
+ void apply( const View& view )
+ {
+ typedef typename get_pixel_type< View >::type pixel_t;
+
+ std::size_t width = view.width();
+ std::size_t height = view.height();
+
+ std::size_t chn = num_channels< View >::value;
+ std::size_t pitch = chn * width;
+
+ unsigned int type = get_type< num_channels< View >::value >( is_bit_aligned< pixel_t >() );
+
+ // write header
+
+ // Add a white space at each string so read_int() can decide when a numbers ends.
+
+ std::string str( "P" );
+ str += std::to_string( type ) + std::string( " " );
+ this->_io_dev.print_line( str );
+
+ str.clear();
+ str += std::to_string( width ) + std::string( " " );
+ this->_io_dev.print_line( str );
+
+ str.clear();
+ str += std::to_string( height ) + std::string( " " );
+ this->_io_dev.print_line( str );
+
+ if( type != pnm_image_type::mono_bin_t::value )
+ {
+ this->_io_dev.print_line( "255 ");
+ }
+
+ // write data
+ write_data( view
+ , pitch
+ , typename is_bit_aligned< pixel_t >::type()
+ );
+ }
+
+private:
+
+ template< int Channels >
+ unsigned int get_type( mpl::true_ /* is_bit_aligned */ )
+ {
+ return boost::mpl::if_c< Channels == 1
+ , pnm_image_type::mono_bin_t
+ , pnm_image_type::color_bin_t
+ >::type::value;
+ }
+
+ template< int Channels >
+ unsigned int get_type( mpl::false_ /* is_bit_aligned */ )
+ {
+ return boost::mpl::if_c< Channels == 1
+ , pnm_image_type::gray_bin_t
+ , pnm_image_type::color_bin_t
+ >::type::value;
+ }
+
+ template< typename View >
+ void write_data( const View& src
+ , std::size_t pitch
+ , const mpl::true_& // bit_aligned
+ )
+ {
+ BOOST_STATIC_ASSERT(( is_same< View
+ , typename gray1_image_t::view_t
+ >::value
+ ));
+
+ byte_vector_t row( pitch / 8 );
+
+ typedef typename View::x_iterator x_it_t;
+ x_it_t row_it = x_it_t( &( *row.begin() ));
+
+ detail::negate_bits< byte_vector_t
+ , mpl::true_
+ > neg;
+
+ detail::mirror_bits< byte_vector_t
+ , mpl::true_
+ > mirror;
+
+
+ for( typename View::y_coord_t y = 0; y < src.height(); ++y )
+ {
+ std::copy( src.row_begin( y )
+ , src.row_end( y )
+ , row_it
+ );
+
+ mirror( row );
+ neg ( row );
+
+ this->_io_dev.write( &row.front()
+ , pitch / 8
+ );
+ }
+ }
+
+ template< typename View >
+ void write_data( const View& src
+ , std::size_t pitch
+ , const mpl::false_& // bit_aligned
+ )
+ {
+ std::vector< pixel< typename channel_type< View >::type
+ , layout<typename color_space_type< View >::type >
+ >
+ > buf( src.width() );
+
+ // typedef typename View::value_type pixel_t;
+ // typedef typename view_type_from_pixel< pixel_t >::type view_t;
+
+ //view_t row = interleaved_view( src.width()
+ // , 1
+ // , reinterpret_cast< pixel_t* >( &buf.front() )
+ // , pitch
+ // );
+
+ byte_t* row_addr = reinterpret_cast< byte_t* >( &buf.front() );
+
+ for( typename View::y_coord_t y = 0
+ ; y < src.height()
+ ; ++y
+ )
+ {
+ //copy_pixels( subimage_view( src
+ // , 0
+ // , (int) y
+ // , (int) src.width()
+ // , 1
+ // )
+ // , row
+ // );
+
+ std::copy( src.row_begin( y )
+ , src.row_end ( y )
+ , buf.begin()
+ );
+
+ this->_io_dev.write( row_addr, pitch );
+ }
+ }
+};
+
+///
+/// PNM Writer
+///
+template< typename Device >
+class dynamic_image_writer< Device
+ , pnm_tag
+ >
+ : public writer< Device
+ , pnm_tag
+ >
+{
+ typedef writer< Device
+ , pnm_tag
+ > parent_t;
+
+public:
+
+ dynamic_image_writer( const Device& io_dev
+ , const image_write_info< pnm_tag >& info
+ )
+ : parent_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename Views >
+ void apply( const any_image_view< Views >& views )
+ {
+ detail::dynamic_io_fnobj< detail::pnm_write_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( views, op );
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/detail/writer_backend.hpp b/boost/gil/extension/io/pnm/detail/writer_backend.hpp
new file mode 100644
index 0000000000..38672e6f71
--- /dev/null
+++ b/boost/gil/extension/io/pnm/detail/writer_backend.hpp
@@ -0,0 +1,66 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_DETAIL_WRITER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/pnm/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// PNM Writer Backend
+///
+template< typename Device >
+struct writer_backend< Device
+ , pnm_tag
+ >
+{
+public:
+
+ typedef pnm_tag format_tag_t;
+
+public:
+
+ writer_backend( const Device& io_dev
+ , const image_write_info< pnm_tag >& info
+ )
+ : _io_dev( io_dev )
+ , _info( info )
+ {}
+
+public:
+
+ Device _io_dev;
+
+ image_write_info< pnm_tag > _info;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/old.hpp b/boost/gil/extension/io/pnm/old.hpp
new file mode 100644
index 0000000000..a9a1529ca0
--- /dev/null
+++ b/boost/gil/extension/io/pnm/old.hpp
@@ -0,0 +1,181 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_OLD_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_OLD_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/pnm.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup PNM_IO
+/// \brief Returns the width and height of the PNM file at the specified location.
+/// Throws std::ios_base::failure if the location does not correspond to a valid PNM file
+template< typename String >
+inline
+point2< std::ptrdiff_t > pnm_read_dimensions( const String& filename )
+{
+ typedef typename get_reader_backend< String
+ , pnm_tag
+ >::type backend_t;
+
+ backend_t backend = read_image_info( filename
+ , pnm_tag()
+ );
+
+ return point2< std::ptrdiff_t >( backend._info._width
+ , backend._info._height
+ );
+}
+
+
+/// \ingroup PNM_IO
+/// \brief Loads the image specified by the given pnm image file name into the given view.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the PNM library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid PNM file, or if its color space or channel depth are not
+/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void pnm_read_view( const String& filename
+ , const View& view
+ )
+{
+ read_view( filename
+ , view
+ , pnm_tag()
+ );
+}
+
+/// \ingroup PNM_IO
+/// \brief Allocates a new image whose dimensions are determined by the given pnm image file, and loads the pixels into it.
+/// Triggers a compile assert if the image color space or channel depth are not supported by the PNM library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid PNM file, or if its color space or channel depth are not
+/// compatible with the ones specified by Image
+template< typename String
+ , typename Image
+ >
+inline
+void pnm_read_image( const String& filename
+ , Image& img
+ )
+{
+ read_image( filename
+ , img
+ , pnm_tag()
+ );
+}
+
+/// \ingroup PNM_IO
+/// \brief Loads and color-converts the image specified by the given pnm image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid PNM file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ , typename CC
+ >
+inline
+void pnm_read_and_convert_view( const String& filename
+ , const View& view
+ , CC cc
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , cc
+ , pnm_tag()
+ );
+}
+
+/// \ingroup PNM_IO
+/// \brief Loads and color-converts the image specified by the given pnm image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid PNM file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void pnm_read_and_convert_view( const String& filename
+ , const View& view
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , pnm_tag()
+ );
+}
+
+/// \ingroup PNM_IO
+/// \brief Allocates a new image whose dimensions are determined by the given pnm image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid PNM file
+template< typename String
+ , typename Image
+ , typename CC
+ >
+inline
+void pnm_read_and_convert_image( const String& filename
+ , Image& img
+ , CC cc
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , cc
+ , pnm_tag()
+ );
+}
+
+/// \ingroup PNM_IO
+/// \brief Allocates a new image whose dimensions are determined by the given pnm image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid PNM file
+template< typename String
+ , typename Image
+ >
+inline
+void pnm_read_and_convert_image( const String filename
+ , Image& img
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , pnm_tag()
+ );
+}
+
+
+/// \ingroup PNM_IO
+/// \brief Saves the view to a pnm file specified by the given pnm image file name.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the PNM library or by the I/O extension.
+/// Throws std::ios_base::failure if it fails to create the file.
+template< typename String
+ , typename View
+ >
+inline
+void pnm_write_view( const String& filename
+ , const View& view
+ )
+{
+ write_view( filename
+ , view
+ , pnm_tag()
+ );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/read.hpp b/boost/gil/extension/io/pnm/read.hpp
new file mode 100644
index 0000000000..67ec2635d8
--- /dev/null
+++ b/boost/gil/extension/io/pnm/read.hpp
@@ -0,0 +1,41 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/pnm/tags.hpp>
+#include <boost/gil/extension/io/pnm/detail/supported_types.hpp>
+#include <boost/gil/extension/io/pnm/detail/read.hpp>
+#include <boost/gil/extension/io/pnm/detail/scanline_read.hpp>
+
+#include <boost/gil/io/get_reader.hpp>
+#include <boost/gil/io/make_backend.hpp>
+#include <boost/gil/io/make_reader.hpp>
+#include <boost/gil/io/make_dynamic_image_reader.hpp>
+#include <boost/gil/io/make_scanline_reader.hpp>
+
+#include <boost/gil/io/read_image.hpp>
+#include <boost/gil/io/read_view.hpp>
+#include <boost/gil/io/read_image_info.hpp>
+#include <boost/gil/io/read_and_convert_image.hpp>
+#include <boost/gil/io/read_and_convert_view.hpp>
+
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/pnm/tags.hpp b/boost/gil/extension/io/pnm/tags.hpp
new file mode 100644
index 0000000000..2151c373ed
--- /dev/null
+++ b/boost/gil/extension/io/pnm/tags.hpp
@@ -0,0 +1,106 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_TAGS_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_TAGS_HPP
+
+#define BOOST_GIL_EXTENSION_IO_PNM_READ_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/integral_c.hpp>
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil {
+
+/// Defines pnm tag.
+struct pnm_tag : format_tag {};
+
+/// see http://en.wikipedia.org/wiki/Portable_Bitmap_File_Format for reference
+
+/// Defines type for image type property.
+struct pnm_image_type : property_base< uint32_t >
+{
+ typedef boost::mpl::integral_c< type, 1 > mono_asc_t;
+ typedef boost::mpl::integral_c< type, 2 > gray_asc_t;
+ typedef boost::mpl::integral_c< type, 3 > color_asc_t;
+
+ typedef boost::mpl::integral_c< type, 4 > mono_bin_t;
+ typedef boost::mpl::integral_c< type, 5 > gray_bin_t;
+ typedef boost::mpl::integral_c< type, 6 > color_bin_t;
+};
+
+/// Defines type for image width property.
+struct pnm_image_width : property_base< uint32_t > {};
+
+/// Defines type for image height property.
+struct pnm_image_height : property_base< uint32_t > {};
+
+/// Defines type for image max value property.
+struct pnm_image_max_value : property_base< uint32_t > {};
+
+/// Read information for pnm images.
+///
+/// The structure is returned when using read_image_info.
+template<>
+struct image_read_info< pnm_tag >
+{
+ /// The image type.
+ pnm_image_type::type _type;
+ /// The image width.
+ pnm_image_width::type _width;
+ /// The image height.
+ pnm_image_height::type _height;
+ /// The image max value.
+ pnm_image_max_value::type _max_value;
+};
+
+/// Read settings for pnm images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< pnm_tag > : public image_read_settings_base
+{
+ /// Default constructor
+ image_read_settings< pnm_tag >()
+ : image_read_settings_base()
+ {}
+
+ /// Constructor
+ /// \param top_left Top left coordinate for reading partial image.
+ /// \param dim Dimensions for reading partial image.
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ {}
+};
+
+/// Write information for pnm images.
+///
+/// The structure can be used for write_view() function.
+template<>
+struct image_write_info< pnm_tag >
+{
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/pnm/write.hpp b/boost/gil/extension/io/pnm/write.hpp
new file mode 100644
index 0000000000..1a90483cd8
--- /dev/null
+++ b/boost/gil/extension/io/pnm/write.hpp
@@ -0,0 +1,31 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_PNM_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_PNM_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/pnm/tags.hpp>
+#include <boost/gil/extension/io/pnm/detail/supported_types.hpp>
+#include <boost/gil/extension/io/pnm/detail/write.hpp>
+
+#include <boost/gil/io/make_writer.hpp>
+#include <boost/gil/io/make_dynamic_image_writer.hpp>
+
+#include <boost/gil/io/write_view.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/raw.hpp b/boost/gil/extension/io/raw.hpp
new file mode 100644
index 0000000000..c3a3626c75
--- /dev/null
+++ b/boost/gil/extension/io/raw.hpp
@@ -0,0 +1,24 @@
+/*
+ Copyright 2013 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Olivier tournaire \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/raw/read.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/raw/detail/device.hpp b/boost/gil/extension/io/raw/detail/device.hpp
new file mode 100644
index 0000000000..7f93336d51
--- /dev/null
+++ b/boost/gil/extension/io/raw/detail/device.hpp
@@ -0,0 +1,143 @@
+/*
+ Copyright 2007-2012 Olivier Tournaire, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_DETAIL_DEVICE_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_DEVICE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Olivier Tournaire \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+
+#include <memory>
+
+namespace boost { namespace gil { namespace detail {
+
+class raw_device_base
+{
+public:
+
+ ///
+ /// Constructor
+ ///
+ raw_device_base()
+ : _processor_ptr( new LibRaw )
+ {}
+
+ // iparams getters
+ std::string get_camera_manufacturer() { return std::string(_processor_ptr.get()->imgdata.idata.make); }
+ std::string get_camera_model() { return std::string(_processor_ptr.get()->imgdata.idata.model); }
+ unsigned get_raw_count() { return _processor_ptr.get()->imgdata.idata.raw_count; }
+ unsigned get_dng_version() { return _processor_ptr.get()->imgdata.idata.dng_version; }
+ int get_colors() { return _processor_ptr.get()->imgdata.idata.colors; }
+ unsigned get_filters() { return _processor_ptr.get()->imgdata.idata.filters; }
+ std::string get_cdesc() { return std::string(_processor_ptr.get()->imgdata.idata.cdesc); }
+
+ // image_sizes getters
+ unsigned short get_raw_width() { return _processor_ptr.get()->imgdata.sizes.raw_width; }
+ unsigned short get_raw_height() { return _processor_ptr.get()->imgdata.sizes.raw_height; }
+ unsigned short get_image_width() { return _processor_ptr.get()->imgdata.sizes.width; }
+ unsigned short get_image_height() { return _processor_ptr.get()->imgdata.sizes.height; }
+ unsigned short get_top_margin() { return _processor_ptr.get()->imgdata.sizes.top_margin; }
+ unsigned short get_left_margin() { return _processor_ptr.get()->imgdata.sizes.left_margin; }
+ unsigned short get_iwidth() { return _processor_ptr.get()->imgdata.sizes.iwidth; }
+ unsigned short get_iheight() { return _processor_ptr.get()->imgdata.sizes.iheight; }
+ double get_pixel_aspect() { return _processor_ptr.get()->imgdata.sizes.pixel_aspect; }
+ int get_flip() { return _processor_ptr.get()->imgdata.sizes.flip; }
+
+ // colordata getters
+ // TODO
+
+ // imgother getters
+ float get_iso_speed() { return _processor_ptr.get()->imgdata.other.iso_speed; }
+ float get_shutter() { return _processor_ptr.get()->imgdata.other.shutter; }
+ float get_aperture() { return _processor_ptr.get()->imgdata.other.aperture; }
+ float get_focal_len() { return _processor_ptr.get()->imgdata.other.focal_len; }
+ time_t get_timestamp() { return _processor_ptr.get()->imgdata.other.timestamp; }
+ unsigned int get_shot_order() { return _processor_ptr.get()->imgdata.other.shot_order; }
+ unsigned* get_gpsdata() { return _processor_ptr.get()->imgdata.other.gpsdata; }
+ std::string get_desc() { return std::string(_processor_ptr.get()->imgdata.other.desc); }
+ std::string get_artist() { return std::string(_processor_ptr.get()->imgdata.other.artist); }
+
+ std::string get_version() { return std::string(_processor_ptr.get()->version()); }
+ std::string get_unpack_function_name() { return std::string(_processor_ptr.get()->unpack_function_name()); }
+
+ void get_mem_image_format(int *widthp, int *heightp, int *colorsp, int *bpp) { _processor_ptr.get()->get_mem_image_format(widthp, heightp, colorsp, bpp); }
+
+ int unpack() { return _processor_ptr.get()->unpack(); }
+ int dcraw_process() { return _processor_ptr.get()->dcraw_process(); }
+ libraw_processed_image_t* dcraw_make_mem_image(int* error_code=NULL) { return _processor_ptr.get()->dcraw_make_mem_image(error_code); }
+
+protected:
+
+ using libraw_ptr_t = std::shared_ptr<LibRaw>;
+ libraw_ptr_t _processor_ptr;
+};
+
+/*!
+ *
+ * file_stream_device specialization for raw images
+ */
+template<>
+class file_stream_device< raw_tag > : public raw_device_base
+{
+public:
+
+ struct read_tag {};
+
+ ///
+ /// Constructor
+ ///
+ file_stream_device( std::string const& file_name
+ , read_tag = read_tag()
+ )
+ {
+ io_error_if( _processor_ptr.get()->open_file( file_name.c_str() ) != LIBRAW_SUCCESS
+ , "file_stream_device: failed to open file"
+ );
+ }
+
+ ///
+ /// Constructor
+ ///
+ file_stream_device( const char* file_name
+ , read_tag = read_tag()
+ )
+ {
+ io_error_if( _processor_ptr.get()->open_file( file_name ) != LIBRAW_SUCCESS
+ , "file_stream_device: failed to open file"
+ );
+ }
+};
+
+template< typename FormatTag >
+struct is_adaptable_input_device< FormatTag
+ , LibRaw
+ , void
+ >
+ : mpl::true_
+{
+ typedef file_stream_device< FormatTag > device_type;
+};
+
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/raw/detail/is_allowed.hpp b/boost/gil/extension/io/raw/detail/is_allowed.hpp
new file mode 100644
index 0000000000..852378abae
--- /dev/null
+++ b/boost/gil/extension/io/raw/detail/is_allowed.hpp
@@ -0,0 +1,57 @@
+/*
+ Copyright 2009 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_DETAIL_IS_ALLOWED_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_IS_ALLOWED_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Olivier Tournaire \n
+///
+/// \date 2011 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/io/base.hpp>
+#include <iostream>
+
+namespace boost { namespace gil { namespace detail {
+
+template< typename View >
+bool is_allowed( const image_read_info< raw_tag >& info
+ , mpl::true_ // is read_and_no_convert
+ )
+{
+ typedef typename get_pixel_type< View >::type pixel_t;
+ typedef typename num_channels< pixel_t >::value_type num_channel_t;
+ typedef typename channel_traits< typename element_type< typename View::value_type >::type >::value_type channel_t;
+
+ const num_channel_t dst_samples_per_pixel = num_channels< pixel_t >::value;
+ const unsigned int dst_bits_per_pixel = detail::unsigned_integral_num_bits< channel_t >::value;
+ const bool is_type_signed = boost::is_signed< channel_t >::value;
+
+ return( dst_samples_per_pixel == info._samples_per_pixel &&
+ dst_bits_per_pixel == static_cast<unsigned int>(info._bits_per_pixel) &&
+ !is_type_signed );
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< raw_tag >& /* info */
+ , mpl::false_ // is read_and_convert
+ )
+{
+ return true;
+}
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/raw/detail/read.hpp b/boost/gil/extension/io/raw/detail/read.hpp
new file mode 100644
index 0000000000..6406d6575e
--- /dev/null
+++ b/boost/gil/extension/io/raw/detail/read.hpp
@@ -0,0 +1,259 @@
+/*
+ Copyright 2012 Olivier Tournaire, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Olivier Tournaire, Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <cstdio>
+#include <vector>
+#include <boost/gil/extension/io/raw/tags.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/raw/detail/is_allowed.hpp>
+#include <boost/gil/extension/io/raw/detail/device.hpp>
+#include <boost/gil/extension/io/raw/detail/reader_backend.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+#define BUILD_INTERLEAVED_VIEW(color_layout, bits_per_pixel) \
+{ \
+ color_layout##bits_per_pixel##_view_t build = boost::gil::interleaved_view(processed_image->width, \
+ processed_image->height, \
+ (color_layout##bits_per_pixel##_pixel_t*)processed_image->data, \
+ processed_image->colors*processed_image->width*processed_image->bits/8); \
+ this->_cc_policy.read( build.begin(), build.end(), dst_view.begin() ); \
+} \
+
+
+template< typename Device
+ , typename ConversionPolicy
+ >
+class reader< Device
+ , raw_tag
+ , ConversionPolicy
+ >
+ : public reader_base< raw_tag
+ , ConversionPolicy
+ >
+ , public reader_backend< Device
+ , raw_tag
+ >
+{
+private:
+
+ typedef reader< Device
+ , raw_tag
+ , ConversionPolicy
+ > this_t;
+
+ typedef typename ConversionPolicy::color_converter_type cc_t;
+
+public:
+
+ typedef reader_backend< Device, raw_tag > backend_t;
+
+public:
+
+ //
+ // Constructor
+ //
+ reader( const Device& io_dev
+ , const image_read_settings< raw_tag >& settings
+ )
+ : backend_t( io_dev
+ , settings
+ )
+ {}
+
+ //
+ // Constructor
+ //
+ reader( const Device& io_dev
+ , const cc_t& cc
+ , const image_read_settings< raw_tag >& settings
+ )
+ : reader_base< raw_tag
+ , ConversionPolicy
+ >( cc )
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename View >
+ void apply( const View& dst_view )
+ {
+ if( this->_info._valid == false )
+ {
+ io_error( "Image header was not read." );
+ }
+
+ typedef typename is_same< ConversionPolicy
+ , detail::read_and_no_convert
+ >::type is_read_and_convert_t;
+
+ io_error_if( !detail::is_allowed< View >( this->_info
+ , is_read_and_convert_t()
+ )
+ , "Image types aren't compatible."
+ );
+
+ // TODO: better error handling based on return code
+ int return_code = this->_io_dev.unpack();
+ io_error_if( return_code != LIBRAW_SUCCESS, "Unable to unpack image" );
+ this->_info._unpack_function_name = this->_io_dev.get_unpack_function_name();
+
+ return_code = this->_io_dev.dcraw_process();
+ io_error_if( return_code != LIBRAW_SUCCESS, "Unable to emulate dcraw behavior to process image" );
+
+ libraw_processed_image_t* processed_image = this->_io_dev.dcraw_make_mem_image(&return_code);
+ io_error_if( return_code != LIBRAW_SUCCESS, "Unable to dcraw_make_mem_image" );
+
+ if(processed_image->colors!=1 && processed_image->colors!=3)
+ io_error( "Image is neither gray nor RGB" );
+
+ if(processed_image->bits!=8 && processed_image->bits!=16)
+ io_error( "Image is neither 8bit nor 16bit" );
+
+ // TODO Olivier Tournaire
+ // Here, we should use a metafunction to reduce code size and avoid a (compile time) macro
+ if(processed_image->bits==8)
+ {
+ if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 8); }
+ else { BUILD_INTERLEAVED_VIEW(rgb, 8); }
+ }
+ else if(processed_image->bits==16)
+ {
+ if(processed_image->colors==1){ BUILD_INTERLEAVED_VIEW(gray, 16); }
+ else { BUILD_INTERLEAVED_VIEW(rgb, 16); }
+ }
+ }
+};
+
+namespace detail {
+
+struct raw_read_is_supported
+{
+ template< typename View >
+ struct apply : public is_read_supported< typename get_pixel_type< View >::type
+ , raw_tag
+ >
+ {};
+};
+
+struct raw_type_format_checker
+{
+ raw_type_format_checker( const image_read_info< raw_tag >& info )
+ : _info( info )
+ {}
+
+ template< typename Image >
+ bool apply()
+ {
+ typedef typename Image::view_t view_t;
+
+ return is_allowed< view_t >( _info
+ , mpl::true_()
+ );
+ }
+
+private:
+ ///todo: do we need this here. Should be part of reader_backend
+ const image_read_info< raw_tag >& _info;
+};
+
+} // namespace detail
+
+///
+/// RAW Dynamic Reader
+///
+template< typename Device >
+class dynamic_image_reader< Device
+ , raw_tag
+ >
+ : public reader< Device
+ , raw_tag
+ , detail::read_and_no_convert
+ >
+{
+ typedef reader< Device
+ , raw_tag
+ , detail::read_and_no_convert
+ > parent_t;
+
+public:
+
+ dynamic_image_reader( const Device& io_dev
+ , const image_read_settings< raw_tag >& settings
+ )
+ : parent_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename Images >
+ void apply( any_image< Images >& images )
+ {
+ detail::raw_type_format_checker format_checker( this->_info );
+
+ if( !construct_matched( images
+ , format_checker
+ ))
+ {
+ std::ostringstream error_message;
+ error_message << "No matching image type between those of the given any_image and that of the file.\n";
+ error_message << "Image type must be {gray||rgb}{8||16} unsigned for RAW image files.";
+ io_error( error_message.str().c_str() );
+ }
+ else
+ {
+ if( !this->_info._valid )
+ this->read_header();
+ this->init_image(images, this->_settings);
+
+ detail::dynamic_io_fnobj< detail::raw_read_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( view( images )
+ , op
+ );
+ }
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/raw/detail/reader_backend.hpp b/boost/gil/extension/io/raw/detail/reader_backend.hpp
new file mode 100644
index 0000000000..ad03a946f7
--- /dev/null
+++ b/boost/gil/extension/io/raw/detail/reader_backend.hpp
@@ -0,0 +1,151 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_READER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/raw/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// RAW Backend
+///
+template< typename Device >
+struct reader_backend< Device
+ , raw_tag
+ >
+{
+public:
+
+ typedef raw_tag format_tag_t;
+
+public:
+
+ reader_backend( const Device& io_dev
+ , const image_read_settings< raw_tag >& settings
+ )
+ : _io_dev ( io_dev )
+ , _settings( settings )
+ , _info()
+ , _scanline_length( 0 )
+ {
+ read_header();
+
+ if( _settings._dim.x == 0 )
+ {
+ _settings._dim.x = _info._width;
+ }
+
+ if( _settings._dim.y == 0 )
+ {
+ _settings._dim.y = _info._height;
+ }
+ }
+
+ void read_header()
+ {
+ _io_dev.get_mem_image_format( &_info._width
+ , &_info._height
+ , &_info._samples_per_pixel
+ , &_info._bits_per_pixel
+ );
+
+ // iparams
+ _info._camera_manufacturer = _io_dev.get_camera_manufacturer();
+ _info._camera_model = _io_dev.get_camera_model();
+ _info._raw_images_count = _io_dev.get_raw_count();
+ _info._dng_version = _io_dev.get_dng_version();
+ _info._number_colors = _io_dev.get_colors();
+ //_io_dev.get_filters();
+ _info._colors_description = _io_dev.get_cdesc();
+
+ // image_sizes
+ _info._raw_width = _io_dev.get_raw_width();
+ _info._raw_height = _io_dev.get_raw_height();
+ _info._visible_width = _io_dev.get_image_width();
+ _info._visible_height = _io_dev.get_image_height();
+ _info._top_margin = _io_dev.get_top_margin();
+ _info._left_margin = _io_dev.get_left_margin();
+ _info._output_width = _io_dev.get_iwidth();
+ _info._output_height = _io_dev.get_iheight();
+ _info._pixel_aspect = _io_dev.get_pixel_aspect();
+ _info._flip = _io_dev.get_flip();
+
+ // imgother
+ _info._iso_speed = _io_dev.get_iso_speed();
+ _info._shutter = _io_dev.get_shutter();
+ _info._aperture = _io_dev.get_aperture();
+ _info._focal_length = _io_dev.get_focal_len();
+ _info._timestamp = _io_dev.get_timestamp();
+ _info._shot_order = static_cast< uint16_t >( _io_dev.get_shot_order() );
+ //_io_dev.get_gpsdata();
+ _info._image_description = _io_dev.get_desc();
+ _info._artist = _io_dev.get_artist();
+
+ _info._libraw_version = _io_dev.get_version();
+
+ _info._valid = true;
+ }
+
+ /// Check if image is large enough.
+ void check_image_size( const point_t& img_dim )
+ {
+ if( _settings._dim.x > 0 )
+ {
+ if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
+ }
+
+
+ if( _settings._dim.y > 0 )
+ {
+ if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
+ }
+ }
+
+public:
+
+ Device _io_dev;
+
+ image_read_settings< raw_tag > _settings;
+ image_read_info< raw_tag > _info;
+
+ std::size_t _scanline_length;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/raw/detail/supported_types.hpp b/boost/gil/extension/io/raw/detail/supported_types.hpp
new file mode 100644
index 0000000000..4175db9571
--- /dev/null
+++ b/boost/gil/extension/io/raw/detail/supported_types.hpp
@@ -0,0 +1,84 @@
+/*
+ Copyright 2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_DETAIL_SUPPORTED_TYPES_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_DETAIL_SUPPORTED_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Olivier Tournaire \n
+///
+/// \date 2011 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/gil/channel.hpp>
+#include <boost/gil/color_base.hpp>
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil { namespace detail {
+
+// Read support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct raw_read_support : read_support_false {};
+
+template<>
+struct raw_read_support<uint8_t
+ , gray_t
+ > : read_support_true {};
+
+template<>
+struct raw_read_support<uint16_t
+ , gray_t
+ > : read_support_true {};
+
+template<>
+struct raw_read_support<uint8_t
+ , rgb_t
+ > : read_support_true {};
+
+template<>
+struct raw_read_support<uint16_t
+ , rgb_t
+ > : read_support_true {};
+
+// Write support
+
+struct raw_write_support : write_support_false {};
+
+} // namespace detail
+
+template< typename Pixel >
+struct is_read_supported< Pixel,
+ raw_tag
+ >
+ : mpl::bool_< detail::raw_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported > {};
+
+template< typename Pixel >
+struct is_write_supported< Pixel
+ , raw_tag
+ >
+ : mpl::bool_< detail::raw_write_support::is_supported >
+{};
+
+} // namespace gil
+} // namespace boost
+
+
+#endif
diff --git a/boost/gil/extension/io/raw/read.hpp b/boost/gil/extension/io/raw/read.hpp
new file mode 100644
index 0000000000..f670d68576
--- /dev/null
+++ b/boost/gil/extension/io/raw/read.hpp
@@ -0,0 +1,40 @@
+/*
+ Copyright 2013 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Olivier Tournaire \n
+///
+/// \date 2011 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/raw/tags.hpp>
+#include <boost/gil/extension/io/raw/detail/supported_types.hpp>
+#include <boost/gil/extension/io/raw/detail/read.hpp>
+
+#include <boost/gil/io/get_reader.hpp>
+#include <boost/gil/io/make_backend.hpp>
+#include <boost/gil/io/make_reader.hpp>
+#include <boost/gil/io/make_dynamic_image_reader.hpp>
+#include <boost/gil/io/make_scanline_reader.hpp>
+
+#include <boost/gil/io/read_image_info.hpp>
+#include <boost/gil/io/read_view.hpp>
+#include <boost/gil/io/read_image.hpp>
+#include <boost/gil/io/read_and_convert_image.hpp>
+#include <boost/gil/io/read_and_convert_view.hpp>
+
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/raw/tags.hpp b/boost/gil/extension/io/raw/tags.hpp
new file mode 100644
index 0000000000..684a24cbe0
--- /dev/null
+++ b/boost/gil/extension/io/raw/tags.hpp
@@ -0,0 +1,216 @@
+/*
+ Copyright 2013 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_TAGS_HPP
+#define BOOST_GIL_EXTENSION_IO_RAW_TAGS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief All supported raw tags by the gil io extension.
+/// \author Olivier Tournaire \n
+///
+/// \date 2011 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#endif
+
+#include <libraw/libraw.h>
+
+#ifndef BOOST_GIL_EXTENSION_IO_RAW_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil {
+
+/// Defines tiff tag.
+struct raw_tag : format_tag {};
+
+/// Defines type for image width property.
+struct raw_image_width : property_base< int32_t > {};
+
+/// Defines type for image height property.
+struct raw_image_height : property_base< int32_t > {};
+
+/// Defines type for samples per pixel property.
+struct raw_samples_per_pixel : property_base< int32_t > {};
+
+/// Defines type for bits per pixel property.
+struct raw_bits_per_pixel : property_base< int32_t > {};
+
+/// Defines type for camera manufacturer.
+struct raw_camera_manufacturer : property_base< std::string > {};
+
+/// Defines type for camera model.
+struct raw_camera_model : property_base< std::string > {};
+
+/// Defines type for raw images count.
+struct raw_raw_images_count : property_base< unsigned > {};
+
+/// Defines type for dng version.
+struct raw_dng_version : property_base< unsigned > {};
+
+/// Defines type for number of colors.
+struct raw_number_colors : property_base< int32_t > {};
+
+/// Defines type for colors description.
+struct raw_colors_description : property_base< std::string > {};
+
+/// Defines type for raw height.
+struct raw_raw_height : property_base< uint16_t > {};
+
+/// Defines type for raw width.
+struct raw_raw_width : property_base< uint16_t > {};
+
+/// Defines type for visible height.
+struct raw_visible_height : property_base< uint16_t > {};
+
+/// Defines type for visible width.
+struct raw_visible_width : property_base< uint16_t > {};
+
+/// Defines type for top margin.
+struct raw_top_margin : property_base< uint16_t > {};
+
+/// Defines type for left margin.
+struct raw_left_margin : property_base< uint16_t > {};
+
+/// Defines type for output height.
+struct raw_output_height : property_base< uint16_t > {};
+
+/// Defines type for output width.
+struct raw_output_width : property_base< uint16_t > {};
+
+/// Defines type for pixel aspect.
+struct raw_pixel_aspect : property_base< double > {};
+
+/// Defines type for image orientation.
+struct raw_flip : property_base< uint32_t > {};
+
+/// Defines type for iso speed.
+struct raw_iso_speed : property_base< float > {};
+
+/// Defines type for shutter.
+struct raw_shutter : property_base< float > {};
+
+/// Defines type for aperture.
+struct raw_aperture : property_base< float > {};
+
+/// Defines type for focal length.
+struct raw_focal_length : property_base< float > {};
+
+/// Defines type for timestamp.
+struct raw_timestamp : property_base< time_t > {};
+
+/// Defines type for shot order.
+struct raw_shot_order : property_base< uint16_t > {};
+
+/// Defines type for image description.
+struct raw_image_description : property_base< std::string > {};
+
+/// Defines type for artist.
+struct raw_artist : property_base< std::string > {};
+
+/// Defines type for libraw version.
+struct raw_libraw_version : property_base< std::string > {};
+
+/// Defines type for unpack function name.
+struct raw_unpack_function_name : property_base< std::string > {};
+
+/// Read information for raw images.
+///
+/// The structure is returned when using read_image_info.
+template<>
+struct image_read_info< raw_tag >
+{
+ /// Default contructor.
+ image_read_info< raw_tag >()
+ : _valid( false )
+ {}
+
+ // Here, width and height of the image are the ones of the output height (ie after having been processed by dcraw emulator)
+ raw_image_width::type _width;
+ raw_image_height::type _height;
+ raw_samples_per_pixel::type _samples_per_pixel;
+ raw_bits_per_pixel::type _bits_per_pixel;
+
+ raw_camera_manufacturer::type _camera_manufacturer;
+ raw_camera_model::type _camera_model;
+
+ raw_raw_images_count::type _raw_images_count;
+ raw_dng_version::type _dng_version;
+ raw_number_colors::type _number_colors;
+ raw_colors_description::type _colors_description;
+
+ raw_raw_width::type _raw_width;
+ raw_raw_height::type _raw_height;
+ raw_visible_width::type _visible_width;
+ raw_visible_height::type _visible_height;
+ raw_top_margin::type _top_margin;
+ raw_left_margin::type _left_margin;
+ raw_output_width::type _output_width;
+ raw_output_height::type _output_height;
+ raw_pixel_aspect::type _pixel_aspect;
+ raw_flip::type _flip;
+
+ raw_iso_speed::type _iso_speed;
+ raw_shutter::type _shutter;
+ raw_aperture::type _aperture;
+ raw_focal_length::type _focal_length;
+ raw_timestamp::type _timestamp;
+ raw_shot_order::type _shot_order;
+ raw_image_description::type _image_description;
+ raw_artist::type _artist;
+
+ raw_libraw_version::type _libraw_version;
+ raw_unpack_function_name::type _unpack_function_name;
+
+ /// Used internaly to identify if the header has been read.
+ bool _valid;
+};
+
+/// Read settings for raw images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< raw_tag > : public image_read_settings_base
+{
+ /// Default constructor
+ image_read_settings()
+ : image_read_settings_base()
+ {}
+
+ /// Constructor
+ /// \param top_left Top left coordinate for reading partial image.
+ /// \param dim Dimensions for reading partial image.
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ {}
+};
+
+/// Write information for raw images.
+///
+/// The structure can be used for write_view() function.
+template<>
+struct image_write_info< raw_tag >
+{
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa.hpp b/boost/gil/extension/io/targa.hpp
new file mode 100644
index 0000000000..8ff4cb9302
--- /dev/null
+++ b/boost/gil/extension/io/targa.hpp
@@ -0,0 +1,25 @@
+/*
+ Copyright 2010 Kenneth Riddile
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/targa/read.hpp>
+#include <boost/gil/extension/io/targa/write.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/targa/detail/is_allowed.hpp b/boost/gil/extension/io/targa/detail/is_allowed.hpp
new file mode 100644
index 0000000000..0033ba6e54
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/is_allowed.hpp
@@ -0,0 +1,64 @@
+/*
+ Copyright 2010 Kenneth Riddile
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_IS_ALLOWED_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_IS_ALLOWED_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil { namespace detail {
+
+template< typename View >
+bool is_allowed( const image_read_info< targa_tag >& info
+ , mpl::true_ // is read_and_no_convert
+ )
+{
+ targa_depth::type src_bits_per_pixel = 0;
+
+ switch( info._bits_per_pixel )
+ {
+ case 24:
+ case 32:
+ {
+ src_bits_per_pixel = info._bits_per_pixel;
+ break;
+ }
+ default:
+ {
+ io_error( "Pixel size not supported." );
+ break;
+ }
+ }
+
+ typedef typename channel_traits< typename element_type< typename View::value_type >::type >::value_type channel_t;
+ targa_depth::type dst_bits_per_pixel = detail::unsigned_integral_num_bits< channel_t >::value * num_channels< View >::value;
+
+ return ( dst_bits_per_pixel == src_bits_per_pixel );
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< targa_tag >& /* info */
+ , mpl::false_ // is read_and_convert
+ )
+{
+ return true;
+}
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/detail/read.hpp b/boost/gil/extension/io/targa/detail/read.hpp
new file mode 100644
index 0000000000..b208a679f4
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/read.hpp
@@ -0,0 +1,417 @@
+/*
+ Copyright 2012 Kenneth Riddile, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile, Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/gil/extension/io/targa/tags.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/targa/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/targa/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// Targa Reader
+///
+template< typename Device
+ , typename ConversionPolicy
+ >
+class reader< Device
+ , targa_tag
+ , ConversionPolicy
+ >
+ : public reader_base< targa_tag
+ , ConversionPolicy
+ >
+ , public reader_backend< Device
+ , targa_tag
+ >
+{
+private:
+
+ typedef reader< Device
+ , targa_tag
+ , ConversionPolicy
+ > this_t;
+
+ typedef typename ConversionPolicy::color_converter_type cc_t;
+
+public:
+
+ typedef reader_backend< Device, targa_tag > backend_t;
+
+public:
+
+ reader( const Device& io_dev
+ , const image_read_settings< targa_tag >& settings
+ )
+ : reader_base< targa_tag
+ , ConversionPolicy
+ >()
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ reader( const Device& io_dev
+ , const cc_t& cc
+ , const image_read_settings< targa_tag >& settings
+ )
+ : reader_base< targa_tag
+ , ConversionPolicy
+ >( cc )
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename View >
+ void apply( const View& dst_view )
+ {
+ typedef typename is_same< ConversionPolicy
+ , detail::read_and_no_convert
+ >::type is_read_and_convert_t;
+
+ io_error_if( !detail::is_allowed< View >( this->_info, is_read_and_convert_t() )
+ , "Image types aren't compatible."
+ );
+
+ switch( this->_info._image_type )
+ {
+ case targa_image_type::_rgb:
+ {
+ if( this->_info._color_map_type != targa_color_map_type::_rgb )
+ {
+ io_error( "Inconsistent color map type and image type in targa file." );
+ }
+
+ if( this->_info._color_map_length != 0 )
+ {
+ io_error( "Non-indexed targa files containing a palette are not supported." );
+ }
+
+ switch( this->_info._bits_per_pixel )
+ {
+ case 24:
+ {
+ this->_scanline_length = this->_info._width * ( this->_info._bits_per_pixel / 8 );
+
+ if( this->_info._screen_origin_bit )
+ {
+ read_data< bgr8_view_t >( flipped_up_down_view( dst_view ) );
+ }
+ else
+ {
+ read_data< bgr8_view_t >( dst_view );
+ }
+
+ break;
+ }
+ case 32:
+ {
+ this->_scanline_length = this->_info._width * ( this->_info._bits_per_pixel / 8 );
+
+ if( this->_info._screen_origin_bit )
+ {
+ read_data< bgra8_view_t >( flipped_up_down_view( dst_view ) );
+ }
+ else
+ {
+ read_data< bgra8_view_t >( dst_view );
+ }
+
+ break;
+ }
+ default:
+ {
+ io_error( "Unsupported bit depth in targa file." );
+ break;
+ }
+ }
+
+ break;
+ }
+ case targa_image_type::_rle_rgb:
+ {
+ if( this->_info._color_map_type != targa_color_map_type::_rgb )
+ {
+ io_error( "Inconsistent color map type and image type in targa file." );
+ }
+
+ if( this->_info._color_map_length != 0 )
+ {
+ io_error( "Non-indexed targa files containing a palette are not supported." );
+ }
+
+ switch( this->_info._bits_per_pixel )
+ {
+ case 24:
+ {
+ if( this->_info._screen_origin_bit )
+ {
+ read_rle_data< bgr8_view_t >( flipped_up_down_view( dst_view ) );
+ }
+ else
+ {
+ read_rle_data< bgr8_view_t >( dst_view );
+ }
+ break;
+ }
+ case 32:
+ {
+ if( this->_info._screen_origin_bit )
+ {
+ read_rle_data< bgra8_view_t >( flipped_up_down_view( dst_view ) );
+ }
+ else
+ {
+ read_rle_data< bgra8_view_t >( dst_view );
+ }
+ break;
+ }
+ default:
+ {
+ io_error( "Unsupported bit depth in targa file." );
+ break;
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ io_error( "Unsupported image type in targa file." );
+ break;
+ }
+ }
+ }
+
+private:
+
+ // 8-8-8 BGR
+ // 8-8-8-8 BGRA
+ template< typename View_Src, typename View_Dst >
+ void read_data( const View_Dst& view )
+ {
+ byte_vector_t row( this->_info._width * (this->_info._bits_per_pixel / 8) );
+
+ // jump to first scanline
+ this->_io_dev.seek( static_cast< long >( this->_info._offset ));
+
+ View_Src v = interleaved_view( this->_info._width,
+ 1,
+ reinterpret_cast<typename View_Src::value_type*>( &row.front() ),
+ this->_info._width * num_channels< View_Src >::value
+ );
+
+ typename View_Src::x_iterator beg = v.row_begin( 0 ) + this->_settings._top_left.x;
+ typename View_Src::x_iterator end = beg + this->_settings._dim.x;
+
+ // read bottom up since targa origin is bottom left
+ for( std::ptrdiff_t y = this->_settings._dim.y - 1; y > -1; --y )
+ {
+ // @todo: For now we're reading the whole scanline which is
+ // slightly inefficient. Later versions should try to read
+ // only the bytes which are necessary.
+ this->_io_dev.read( &row.front(), row.size() );
+ this->_cc_policy.read( beg, end, view.row_begin(y) );
+ }
+ }
+
+ // 8-8-8 BGR
+ // 8-8-8-8 BGRA
+ template< typename View_Src, typename View_Dst >
+ void read_rle_data( const View_Dst& view )
+ {
+ targa_depth::type bytes_per_pixel = this->_info._bits_per_pixel / 8;
+ size_t image_size = this->_info._width * this->_info._height * bytes_per_pixel;
+ byte_vector_t image_data( image_size );
+
+ this->_io_dev.seek( static_cast< long >( this->_info._offset ));
+
+ for( size_t pixel = 0; pixel < image_size; )
+ {
+ targa_offset::type current_byte = this->_io_dev.read_uint8();
+
+ if( current_byte & 0x80 ) // run length chunk (high bit = 1)
+ {
+ uint8_t chunk_length = current_byte - 127;
+ uint8_t pixel_data[4];
+ for( size_t channel = 0; channel < bytes_per_pixel; ++channel )
+ {
+ pixel_data[channel] = this->_io_dev.read_uint8();
+ }
+
+ // Repeat the next pixel chunk_length times
+ for( uint8_t i = 0; i < chunk_length; ++i, pixel += bytes_per_pixel )
+ {
+ memcpy( &image_data[pixel], pixel_data, bytes_per_pixel );
+ }
+ }
+ else // raw chunk
+ {
+ uint8_t chunk_length = current_byte + 1;
+
+ // Write the next chunk_length pixels directly
+ size_t pixels_written = chunk_length * bytes_per_pixel;
+ this->_io_dev.read( &image_data[pixel], pixels_written );
+ pixel += pixels_written;
+ }
+ }
+
+ View_Src v = flipped_up_down_view( interleaved_view( this->_info._width,
+ this->_info._height,
+ reinterpret_cast<typename View_Src::value_type*>( &image_data.front() ),
+ this->_info._width * num_channels< View_Src >::value ) );
+
+ for( std::ptrdiff_t y = 0; y != this->_settings._dim.y; ++y )
+ {
+ typename View_Src::x_iterator beg = v.row_begin( y ) + this->_settings._top_left.x;
+ typename View_Src::x_iterator end = beg + this->_settings._dim.x;
+ this->_cc_policy.read( beg, end, view.row_begin(y) );
+ }
+ }
+};
+
+namespace detail {
+
+class targa_type_format_checker
+{
+public:
+
+ targa_type_format_checker( const targa_depth::type& bpp )
+ : _bpp( bpp )
+ {}
+
+ template< typename Image >
+ bool apply()
+ {
+ if( _bpp < 32 )
+ {
+ return pixels_are_compatible< typename Image::value_type, rgb8_pixel_t >::value
+ ? true
+ : false;
+ }
+ else
+ {
+ return pixels_are_compatible< typename Image::value_type, rgba8_pixel_t >::value
+ ? true
+ : false;
+ }
+ }
+
+private:
+
+ // to avoid C4512
+ targa_type_format_checker& operator=( const targa_type_format_checker& ) { return *this; }
+
+private:
+
+ const targa_depth::type _bpp;
+};
+
+struct targa_read_is_supported
+{
+ template< typename View >
+ struct apply : public is_read_supported< typename get_pixel_type< View >::type
+ , targa_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+///
+/// Targa Dynamic Image Reader
+///
+template< typename Device >
+class dynamic_image_reader< Device
+ , targa_tag
+ >
+ : public reader< Device
+ , targa_tag
+ , detail::read_and_no_convert
+ >
+{
+ typedef reader< Device
+ , targa_tag
+ , detail::read_and_no_convert
+ > parent_t;
+
+public:
+
+ dynamic_image_reader( const Device& io_dev
+ , const image_read_settings< targa_tag >& settings
+ )
+ : parent_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename Images >
+ void apply( any_image< Images >& images )
+ {
+ detail::targa_type_format_checker format_checker( this->_info._bits_per_pixel );
+
+ if( !construct_matched( images
+ , format_checker
+ ))
+ {
+ io_error( "No matching image type between those of the given any_image and that of the file" );
+ }
+ else
+ {
+ this->init_image( images
+ , this->_settings
+ );
+
+ detail::dynamic_io_fnobj< detail::targa_read_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( view( images )
+ , op
+ );
+ }
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/detail/reader_backend.hpp b/boost/gil/extension/io/targa/detail/reader_backend.hpp
new file mode 100644
index 0000000000..cbf216aacd
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/reader_backend.hpp
@@ -0,0 +1,175 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_READER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/targa/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// Targa Backend
+///
+template< typename Device >
+struct reader_backend< Device
+ , targa_tag
+ >
+{
+public:
+
+ typedef targa_tag format_tag_t;
+
+public:
+
+ reader_backend( const Device& io_dev
+ , const image_read_settings< targa_tag >& settings
+ )
+ : _io_dev ( io_dev )
+ , _scanline_length(0)
+ , _settings( settings )
+ , _info()
+ {
+ read_header();
+
+ if( _settings._dim.x == 0 )
+ {
+ _settings._dim.x = _info._width;
+ }
+
+ if( _settings._dim.y == 0 )
+ {
+ _settings._dim.y = _info._height;
+ }
+ }
+
+ void read_header()
+ {
+ _info._header_size = targa_header_size::_size;
+
+ _info._offset = _io_dev.read_uint8() + _info._header_size;
+
+ _info._color_map_type = _io_dev.read_uint8();
+ _info._image_type = _io_dev.read_uint8();
+
+ _info._color_map_start = _io_dev.read_uint16();
+ _info._color_map_length = _io_dev.read_uint16();
+ _info._color_map_depth = _io_dev.read_uint8();
+
+ _info._x_origin = _io_dev.read_uint16();
+ _info._y_origin = _io_dev.read_uint16();
+
+ _info._width = _io_dev.read_uint16();
+ _info._height = _io_dev.read_uint16();
+
+ if( _info._width < 1 || _info._height < 1 )
+ {
+ io_error( "Invalid dimension for targa file" );
+ }
+
+ _info._bits_per_pixel = _io_dev.read_uint8();
+ if( _info._bits_per_pixel != 24 && _info._bits_per_pixel != 32 )
+ {
+ io_error( "Unsupported bit depth for targa file" );
+ }
+
+ _info._descriptor = _io_dev.read_uint8();
+
+ // According to TGA specs, http://www.gamers.org/dEngine/quake3/TGA.txt,
+ // the image descriptor byte is:
+ //
+ // For Data Type 1, This entire byte should be set to 0.
+ if (_info._image_type == 1 && _info._descriptor != 0)
+ {
+ io_error("Unsupported descriptor for targa file");
+ }
+ else if (_info._bits_per_pixel == 24)
+ {
+ // Bits 3-0 - For the Targa 24, it should be 0.
+ if ((_info._descriptor & 0x0FU) != 0)
+ {
+ io_error("Unsupported descriptor for targa file");
+ }
+ }
+ else if (_info._bits_per_pixel == 32)
+ {
+ // Bits 3-0 - For Targa 32, it should be 8.
+ if (_info._descriptor != 8 && _info._descriptor != 40)
+ {
+ io_error("Unsupported descriptor for targa file");
+ }
+ }
+ else
+ {
+ io_error("Unsupported descriptor for targa file");
+ }
+
+ if (_info._descriptor & 32)
+ {
+ _info._screen_origin_bit = true;
+ }
+
+ _info._valid = true;
+ }
+
+ /// Check if image is large enough.
+ void check_image_size( const point_t& img_dim )
+ {
+ if( _settings._dim.x > 0 )
+ {
+ if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
+ }
+
+
+ if( _settings._dim.y > 0 )
+ {
+ if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
+ }
+ }
+
+public:
+
+ Device _io_dev;
+
+ std::size_t _scanline_length;
+
+ image_read_settings< targa_tag > _settings;
+ image_read_info< targa_tag > _info;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/detail/scanline_read.hpp b/boost/gil/extension/io/targa/detail/scanline_read.hpp
new file mode 100644
index 0000000000..7fbd0b05b0
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/scanline_read.hpp
@@ -0,0 +1,167 @@
+/*
+ Copyright 2012 Kenneth Riddile and Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_SCANLINE_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_SCANLINE_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile and Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/scanline_read_iterator.hpp>
+#include <boost/gil/io/typedefs.hpp>
+
+#include <boost/gil/extension/io/targa/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/targa/detail/is_allowed.hpp>
+
+namespace boost { namespace gil {
+
+///
+/// Targa Scanline Reader
+///
+template< typename Device >
+class scanline_reader< Device
+ , targa_tag
+ >
+ : public reader_backend< Device
+ , targa_tag
+ >
+{
+public:
+
+
+ typedef targa_tag tag_t;
+ typedef reader_backend < Device, tag_t > backend_t;
+ typedef scanline_reader< Device, tag_t > this_t;
+ typedef scanline_read_iterator< this_t > iterator_t;
+
+public:
+
+ //
+ // Constructor
+ //
+ scanline_reader( Device& device
+ , const image_read_settings< targa_tag >& settings
+ )
+ : backend_t( device
+ , settings
+ )
+ {
+ initialize();
+ }
+
+ /// Read part of image defined by View and return the data.
+ void read( byte_t* dst, int pos )
+ {
+ // jump to scanline
+ long offset = this->_info._offset
+ + ( this->_info._height - 1 - pos ) * static_cast< long >( this->_scanline_length );
+
+ this->_io_dev.seek( offset );
+
+
+ read_row( dst );
+ }
+
+ /// Skip over a scanline.
+ void skip( byte_t*, int )
+ {
+ this->_io_dev.seek( static_cast<long>( this->_scanline_length )
+ , SEEK_CUR
+ );
+ }
+
+ iterator_t begin() { return iterator_t( *this ); }
+ iterator_t end() { return iterator_t( *this, this->_info._height ); }
+
+private:
+
+ void initialize()
+ {
+ if( this->_info._color_map_type != targa_color_map_type::_rgb )
+ {
+ io_error( "scanline reader cannot read indexed targa files." );
+ }
+
+ if( this->_info._image_type != targa_image_type::_rgb )
+ {
+ io_error( "scanline reader cannot read this targa image type." );
+ }
+
+ switch( this->_info._image_type )
+ {
+ case targa_image_type::_rgb:
+ {
+ if( this->_info._color_map_type != targa_color_map_type::_rgb )
+ {
+ io_error( "Inconsistent color map type and image type in targa file." );
+ }
+
+ if( this->_info._color_map_length != 0 )
+ {
+ io_error( "Non-indexed targa files containing a palette are not supported." );
+ }
+
+ if( this->_info._screen_origin_bit )
+ {
+ io_error( "scanline reader cannot read targa files which have screen origin bit set." );
+ }
+
+ switch( this->_info._bits_per_pixel )
+ {
+ case 24:
+ case 32:
+ {
+ this->_scanline_length = this->_info._width * ( this->_info._bits_per_pixel / 8 );
+
+ // jump to first scanline
+ this->_io_dev.seek( static_cast< long >( this->_info._offset ));
+
+ break;
+ }
+ default:
+ {
+ io_error( "Unsupported bit depth in targa file." );
+ break;
+ }
+ }
+
+ break;
+ }
+ default:
+ {
+ io_error( "Unsupported image type in targa file." );
+ break;
+ }
+ }
+ }
+
+ void read_row( byte_t* dst )
+ {
+ this->_io_dev.read( dst, this->_scanline_length );
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/detail/supported_types.hpp b/boost/gil/extension/io/targa/detail/supported_types.hpp
new file mode 100644
index 0000000000..0cefcb4a5b
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/supported_types.hpp
@@ -0,0 +1,110 @@
+/*
+ Copyright 2010 Kenneth Riddile
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_SUPPORTED_TYPES_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_SUPPORTED_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/gil/channel.hpp>
+#include <boost/gil/color_base.hpp>
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil { namespace detail {
+
+// Read support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct targa_read_support : read_support_false
+{
+ static const targa_depth::type bpp = 0;
+};
+
+template<>
+struct targa_read_support<uint8_t
+ , rgb_t
+ > : read_support_true
+{
+ static const targa_depth::type bpp = 24;
+};
+
+
+template<>
+struct targa_read_support<uint8_t
+ , rgba_t
+ > : read_support_true
+{
+ static const targa_depth::type bpp = 32;
+};
+
+
+// Write support
+
+template< typename Channel
+ , typename ColorSpace
+ >
+struct targa_write_support : write_support_false
+{};
+
+template<>
+struct targa_write_support<uint8_t
+ , rgb_t
+ > : write_support_true {};
+
+template<>
+struct targa_write_support<uint8_t
+ , rgba_t
+ > : write_support_true {};
+
+} // namespace detail
+
+
+template< typename Pixel >
+struct is_read_supported< Pixel
+ , targa_tag
+ >
+ : mpl::bool_< detail::targa_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ >
+{
+ typedef detail::targa_read_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ > parent_t;
+
+ static const typename targa_depth::type bpp = parent_t::bpp;
+};
+
+template< typename Pixel >
+struct is_write_supported< Pixel
+ , targa_tag
+ >
+ : mpl::bool_< detail::targa_write_support< typename channel_type< Pixel >::type
+ , typename color_space_type< Pixel >::type
+ >::is_supported
+ > {};
+
+} // namespace gil
+} // namespace boost
+
+
+#endif
diff --git a/boost/gil/extension/io/targa/detail/write.hpp b/boost/gil/extension/io/targa/detail/write.hpp
new file mode 100644
index 0000000000..223c1b2161
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/write.hpp
@@ -0,0 +1,197 @@
+/*
+ Copyright 2010-2012 Kenneth Riddile, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile, Christian Henning \n
+///
+/// \date 2010-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <vector>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+
+#include <boost/gil/extension/io/targa/tags.hpp>
+
+#include <boost/gil/extension/io/targa/detail/writer_backend.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+namespace detail {
+
+template < int N > struct get_targa_view_type {};
+template <> struct get_targa_view_type< 3 > { typedef bgr8_view_t type; };
+template <> struct get_targa_view_type< 4 > { typedef bgra8_view_t type; };
+
+struct targa_write_is_supported
+{
+ template< typename View >
+ struct apply
+ : public is_write_supported< typename get_pixel_type< View >::type
+ , targa_tag
+ >
+ {};
+};
+
+} // detail
+
+///
+/// TARGA Writer
+///
+template< typename Device >
+class writer< Device
+ , targa_tag
+ >
+ : public writer_backend< Device
+ , targa_tag
+ >
+{
+private:
+ typedef writer_backend< Device, targa_tag > backend_t;
+
+public:
+
+ writer( const Device& io_dev
+ , const image_write_info< targa_tag >& info
+ )
+ : backend_t( io_dev
+ , info
+ )
+ {}
+
+ template<typename View>
+ void apply( const View& view )
+ {
+ write( view );
+ }
+
+private:
+
+ template< typename View >
+ void write( const View& view )
+ {
+ uint8_t bit_depth = static_cast<uint8_t>( num_channels<View>::value * 8 );
+
+ // write the TGA header
+ this->_io_dev.write_uint8( 0 ); // offset
+ this->_io_dev.write_uint8( targa_color_map_type::_rgb );
+ this->_io_dev.write_uint8( targa_image_type::_rgb );
+ this->_io_dev.write_uint16( 0 ); // color map start
+ this->_io_dev.write_uint16( 0 ); // color map length
+ this->_io_dev.write_uint8( 0 ); // color map depth
+ this->_io_dev.write_uint16( 0 ); // x origin
+ this->_io_dev.write_uint16( 0 ); // y origin
+ this->_io_dev.write_uint16( static_cast<uint16_t>( view.width() ) ); // width in pixels
+ this->_io_dev.write_uint16( static_cast<uint16_t>( view.height() ) ); // height in pixels
+ this->_io_dev.write_uint8( bit_depth );
+
+ if( 32 == bit_depth )
+ {
+ this->_io_dev.write_uint8( 8 ); // 8-bit alpha channel descriptor
+ }
+ else
+ {
+ this->_io_dev.write_uint8( 0 );
+ }
+
+ write_image< View
+ , typename detail::get_targa_view_type< num_channels< View >::value >::type
+ >( view );
+ }
+
+
+ template< typename View
+ , typename TGA_View
+ >
+ void write_image( const View& view )
+ {
+ size_t row_size = view.width() * num_channels<View>::value;
+ byte_vector_t buffer( row_size );
+ std::fill( buffer.begin(), buffer.end(), 0 );
+
+
+ TGA_View row = interleaved_view( view.width()
+ , 1
+ , reinterpret_cast<typename TGA_View::value_type*>( &buffer.front() )
+ , row_size
+ );
+
+ for( typename View::y_coord_t y = view.height() - 1; y > -1; --y )
+ {
+ copy_pixels( subimage_view( view
+ , 0
+ , static_cast<int>( y )
+ , static_cast<int>( view.width() )
+ , 1
+ )
+ , row
+ );
+
+ this->_io_dev.write( &buffer.front(), row_size );
+ }
+
+ }
+};
+
+///
+/// TARGA Dynamic Image Writer
+///
+template< typename Device >
+class dynamic_image_writer< Device
+ , targa_tag
+ >
+ : public writer< Device
+ , targa_tag
+ >
+{
+ typedef writer< Device
+ , targa_tag
+ > parent_t;
+
+public:
+
+ dynamic_image_writer( const Device& io_dev
+ , const image_write_info< targa_tag >& info
+ )
+ : parent_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename Views >
+ void apply( const any_image_view< Views >& views )
+ {
+ detail::dynamic_io_fnobj< detail::targa_write_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( views, op );
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // gil
+} // boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/detail/writer_backend.hpp b/boost/gil/extension/io/targa/detail/writer_backend.hpp
new file mode 100644
index 0000000000..0dfec2c185
--- /dev/null
+++ b/boost/gil/extension/io/targa/detail/writer_backend.hpp
@@ -0,0 +1,66 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_WRITER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_DETAIL_WRITER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/targa/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// TARGA Writer Backend
+///
+template< typename Device >
+struct writer_backend< Device
+ , targa_tag
+ >
+{
+public:
+
+ typedef targa_tag format_tag_t;
+
+public:
+
+ writer_backend( const Device& io_dev
+ , const image_write_info< targa_tag >& info
+ )
+ : _io_dev( io_dev )
+ , _info( info )
+ {}
+
+public:
+
+ Device _io_dev;
+
+ image_write_info< targa_tag > _info;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/old.hpp b/boost/gil/extension/io/targa/old.hpp
new file mode 100644
index 0000000000..05a3d680b5
--- /dev/null
+++ b/boost/gil/extension/io/targa/old.hpp
@@ -0,0 +1,181 @@
+/*
+ Copyright 2010 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_OLD_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_OLD_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/targa.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup BMP_IO
+/// \brief Returns the width and height of the BMP file at the specified location.
+/// Throws std::ios_base::failure if the location does not correspond to a valid BMP file
+template< typename String >
+inline
+point2< std::ptrdiff_t > targa_read_dimensions( const String& filename )
+{
+ typedef typename get_reader_backend< String
+ , targa_tag
+ >::type backend_t;
+
+ backend_t backend = read_image_info( filename
+ , targa_tag()
+ );
+
+ return point2< std::ptrdiff_t >( backend._info._width
+ , backend._info._height
+ );
+}
+
+
+/// \ingroup BMP_IO
+/// \brief Loads the image specified by the given targa image file name into the given view.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the BMP library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its color space or channel depth are not
+/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void targa_read_view( const String& filename
+ , const View& view
+ )
+{
+ read_view( filename
+ , view
+ , targa_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Allocates a new image whose dimensions are determined by the given bmp image file, and loads the pixels into it.
+/// Triggers a compile assert if the image color space or channel depth are not supported by the BMP library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its color space or channel depth are not
+/// compatible with the ones specified by Image
+template< typename String
+ , typename Image
+ >
+inline
+void targa_read_image( const String& filename
+ , Image& img
+ )
+{
+ read_image( filename
+ , img
+ , targa_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Loads and color-converts the image specified by the given targa image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ , typename CC
+ >
+inline
+void targa_read_and_convert_view( const String& filename
+ , const View& view
+ , CC cc
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , cc
+ , targa_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Loads and color-converts the image specified by the given targa image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid BMP file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void targa_read_and_convert_view( const String& filename
+ , const View& view
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , targa_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Allocates a new image whose dimensions are determined by the given targa image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid BMP file
+template< typename String
+ , typename Image
+ , typename CC
+ >
+inline
+void targa_read_and_convert_image( const String& filename
+ , Image& img
+ , CC cc
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , cc
+ , targa_tag()
+ );
+}
+
+/// \ingroup BMP_IO
+/// \brief Allocates a new image whose dimensions are determined by the given targa image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid BMP file
+template< typename String
+ , typename Image
+ >
+inline
+void targa_read_and_convert_image( const String filename
+ , Image& img
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , targa_tag()
+ );
+}
+
+
+/// \ingroup BMP_IO
+/// \brief Saves the view to a targa file specified by the given targa image file name.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the BMP library or by the I/O extension.
+/// Throws std::ios_base::failure if it fails to create the file.
+template< typename String
+ , typename View
+ >
+inline
+void targa_write_view( const String& filename
+ , const View& view
+ )
+{
+ write_view( filename
+ , view
+ , targa_tag()
+ );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/read.hpp b/boost/gil/extension/io/targa/read.hpp
new file mode 100644
index 0000000000..41caaa7d58
--- /dev/null
+++ b/boost/gil/extension/io/targa/read.hpp
@@ -0,0 +1,41 @@
+/*
+ Copyright 2010-2012 Kenneth Riddile and Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile and Christian Henning \n
+///
+/// \date 2010-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/targa/tags.hpp>
+#include <boost/gil/extension/io/targa/detail/supported_types.hpp>
+#include <boost/gil/extension/io/targa/detail/read.hpp>
+#include <boost/gil/extension/io/targa/detail/scanline_read.hpp>
+
+#include <boost/gil/io/get_reader.hpp>
+#include <boost/gil/io/make_backend.hpp>
+#include <boost/gil/io/make_reader.hpp>
+#include <boost/gil/io/make_dynamic_image_reader.hpp>
+#include <boost/gil/io/make_scanline_reader.hpp>
+
+#include <boost/gil/io/read_image.hpp>
+#include <boost/gil/io/read_view.hpp>
+#include <boost/gil/io/read_image_info.hpp>
+#include <boost/gil/io/read_and_convert_image.hpp>
+#include <boost/gil/io/read_and_convert_view.hpp>
+
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/targa/tags.hpp b/boost/gil/extension/io/targa/tags.hpp
new file mode 100644
index 0000000000..dce128b32c
--- /dev/null
+++ b/boost/gil/extension/io/targa/tags.hpp
@@ -0,0 +1,177 @@
+/*
+ Copyright 2010 Kenneth Riddile
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_TAGS_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_TAGS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil {
+
+/// Defines targa tag.
+struct targa_tag : format_tag {};
+
+/// See http://en.wikipedia.org/wiki/Truevision_TGA#Header for reference.
+/// http://local.wasp.uwa.edu.au/~pbourke/dataformats/tga/
+
+
+/// Defines type for header sizes.
+struct targa_header_size : property_base< uint8_t >
+{
+ static const type _size = 18; /// Constant size for targa file header size.
+};
+
+/// Defines type for offset value.
+struct targa_offset : property_base< uint8_t > {};
+
+/// Defines type for color map type property.
+struct targa_color_map_type : property_base< uint8_t >
+{
+ static const type _rgb = 0;
+ static const type _indexed = 1;
+};
+
+/// Defines type for image type property.
+struct targa_image_type : property_base< uint8_t >
+{
+ static const type _none = 0; /// no image data
+ static const type _indexed = 1; /// indexed
+ static const type _rgb = 2; /// RGB
+ static const type _greyscale = 3; /// greyscale
+ static const type _rle_indexed = 9; /// indexed with RLE compression
+ static const type _rle_rgb = 10; /// RGB with RLE compression
+ static const type _rle_greyscale = 11; /// greyscale with RLE compression
+};
+
+/// Defines type for color map start property.
+struct targa_color_map_start : property_base< uint16_t > {};
+
+/// Defines type for color map length property.
+struct targa_color_map_length : property_base< uint16_t > {};
+
+/// Defines type for color map bit depth property.
+struct targa_color_map_depth : property_base< uint8_t > {};
+
+/// Defines type for origin x and y value properties.
+struct targa_origin_element : property_base< uint16_t > {};
+
+/// Defines type for image dimension properties.
+struct targa_dimension : property_base< uint16_t > {};
+
+/// Defines type for image bit depth property.
+struct targa_depth : property_base< uint8_t > {};
+
+/// Defines type for image descriptor property.
+struct targa_descriptor : property_base< uint8_t > {};
+
+struct targa_screen_origin_bit : property_base< bool > {};
+
+/// Read information for targa images.
+///
+/// The structure is returned when using read_image_info.
+template<>
+struct image_read_info< targa_tag >
+{
+ /// Default contructor.
+ image_read_info< targa_tag >()
+ : _screen_origin_bit(false)
+ , _valid( false )
+ {}
+
+ /// The size of this header:
+ targa_header_size::type _header_size;
+
+ /// The offset, i.e. starting address, of the byte where the targa data can be found.
+ targa_offset::type _offset;
+
+ /// The type of color map used by the image, i.e. RGB or indexed.
+ targa_color_map_type::type _color_map_type;
+
+ /// The type of image data, i.e compressed, indexed, uncompressed RGB, etc.
+ targa_image_type::type _image_type;
+
+ /// Index of first entry in the color map table.
+ targa_color_map_start::type _color_map_start;
+
+ /// Number of entries in the color map table.
+ targa_color_map_length::type _color_map_length;
+
+ /// Bit depth for each color map entry.
+ targa_color_map_depth::type _color_map_depth;
+
+ /// X coordinate of the image origin.
+ targa_origin_element::type _x_origin;
+
+ /// Y coordinate of the image origin.
+ targa_origin_element::type _y_origin;
+
+ /// Width of the image in pixels.
+ targa_dimension::type _width;
+
+ /// Height of the image in pixels.
+ targa_dimension::type _height;
+
+ /// Bit depth of the image.
+ targa_depth::type _bits_per_pixel;
+
+ /// The targa image descriptor.
+ targa_descriptor::type _descriptor;
+
+ // false: Origin in lower left-hand corner.
+ // true: Origin in upper left-hand corner.
+ targa_screen_origin_bit::type _screen_origin_bit;
+
+ /// Used internally to identify if the header has been read.
+ bool _valid;
+};
+
+/// Read settings for targa images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< targa_tag > : public image_read_settings_base
+{
+ /// Default constructor
+ image_read_settings()
+ : image_read_settings_base()
+ {}
+
+ /// Constructor
+ /// \param top_left Top left coordinate for reading partial image.
+ /// \param dim Dimensions for reading partial image.
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ {}
+};
+
+/// Write information for targa images.
+///
+/// The structure can be used for write_view() function.
+template<>
+struct image_write_info< targa_tag >
+{
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/targa/write.hpp b/boost/gil/extension/io/targa/write.hpp
new file mode 100644
index 0000000000..3edecc7d63
--- /dev/null
+++ b/boost/gil/extension/io/targa/write.hpp
@@ -0,0 +1,31 @@
+/*
+ Copyright 2010 Kenneth Riddile
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TARGA_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_TARGA_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Kenneth Riddile \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/targa/tags.hpp>
+#include <boost/gil/extension/io/targa/detail/supported_types.hpp>
+#include <boost/gil/extension/io/targa/detail//write.hpp>
+
+#include <boost/gil/io/make_writer.hpp>
+#include <boost/gil/io/make_dynamic_image_writer.hpp>
+
+#include <boost/gil/io/write_view.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/tiff.hpp b/boost/gil/extension/io/tiff.hpp
new file mode 100644
index 0000000000..0d7e6c8cd5
--- /dev/null
+++ b/boost/gil/extension/io/tiff.hpp
@@ -0,0 +1,25 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/tiff/read.hpp>
+#include <boost/gil/extension/io/tiff/write.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/device.hpp b/boost/gil/extension/io/tiff/detail/device.hpp
new file mode 100644
index 0000000000..aebc9846c8
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/device.hpp
@@ -0,0 +1,489 @@
+/*
+ Copyright 2007-2008 Andreas Pokorny, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_DEVICE_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_DEVICE_HPP
+
+#include <algorithm>
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Andreas Pokorny, Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#endif
+
+#include <tiff.h>
+#include <tiffio.h>
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#include <tiffio.hxx>
+
+#include <boost/mpl/size.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/extension/io/tiff/detail/log.hpp>
+
+#include <memory>
+
+namespace boost { namespace gil { namespace detail {
+
+template <int n_args>
+struct get_property_f {
+ template <typename Property>
+ bool call_me(typename Property:: type& value, std::shared_ptr<TIFF>& file);
+};
+
+template <int n_args>
+struct set_property_f {
+ template <typename Property>
+ bool call_me(const typename Property:: type& value, std::shared_ptr<TIFF>& file) const;
+};
+
+template <> struct get_property_f <1>
+{
+ // For single-valued properties
+ template <typename Property>
+ bool call_me(typename Property::type & value, std::shared_ptr<TIFF>& file) const
+ {
+ // @todo: defaulted, really?
+ return (1 == TIFFGetFieldDefaulted( file.get()
+ , Property:: tag
+ , & value));
+ }
+};
+
+template <> struct get_property_f <2>
+{
+ // Specialisation for multi-valued properties. @todo: add one of
+ // these for the three-parameter fields too.
+ template <typename Property>
+ bool call_me(typename Property:: type & vs, std::shared_ptr<TIFF>& file) const
+ {
+ typename mpl:: at <typename Property:: arg_types, mpl::int_<0> >:: type length;
+ typename mpl:: at <typename Property:: arg_types, mpl::int_<1> >:: type pointer;
+ if (1 == TIFFGetFieldDefaulted( file.get()
+ , Property:: tag
+ , & length
+ , & pointer)) {
+ std:: copy_n (static_cast <typename Property:: type:: const_pointer> (pointer), length, std:: back_inserter (vs));
+ return true;
+ } else
+ return false;
+ }
+};
+
+template <> struct set_property_f <1>
+{
+ // For single-valued properties
+ template <typename Property>
+ inline
+ bool call_me(typename Property:: type const & value, std::shared_ptr<TIFF>& file) const
+ {
+ return (1 == TIFFSetField( file.get()
+ , Property:: tag
+ , value));
+ }
+};
+
+template <> struct set_property_f <2>
+{
+ // Specialisation for multi-valued properties. @todo: add one
+ // of these for the three-parameter fields too. Actually we
+ // will need further templation / specialisation for the
+ // two-element fields which aren't a length and a data buffer
+ // (e.g. http://www.awaresystems.be/imaging/tiff/tifftags/dotrange.html
+ // )
+ template <typename Property>
+ inline
+ bool call_me(typename Property:: type const & values, std::shared_ptr<TIFF>& file) const
+ {
+ typename mpl:: at <typename Property:: arg_types, mpl::int_<0> >:: type const length = values. size ();
+ typename mpl:: at <typename Property:: arg_types, mpl::int_<1> >:: type const pointer = & (values. front ());
+ return (1 == TIFFSetField( file.get()
+ , Property:: tag
+ , length
+ , pointer));
+ }
+};
+
+template< typename Log >
+class tiff_device_base
+{
+public:
+ using tiff_file_t = std::shared_ptr<TIFF>;
+
+ tiff_device_base()
+ {}
+
+ tiff_device_base( TIFF* tiff_file )
+ : _tiff_file( tiff_file
+ , TIFFClose )
+ {}
+
+ template <typename Property>
+ bool get_property( typename Property::type& value )
+ {
+ return get_property_f <mpl:: size <typename Property:: arg_types>::value > ().template call_me<Property>(value, _tiff_file);
+ }
+
+ template <typename Property>
+ inline
+ bool set_property( const typename Property::type& value )
+ {
+ // http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
+ return set_property_f <mpl:: size <typename Property:: arg_types>::value > ().template call_me<Property> (value, _tiff_file);
+ }
+
+ // TIFFIsByteSwapped returns a non-zero value if the image data was in a different
+ // byte-order than the host machine. Zero is returned if the TIFF file and local
+ // host byte-orders are the same. Note that TIFFReadTile(), TIFFReadStrip() and TIFFReadScanline()
+ // functions already normally perform byte swapping to local host order if needed.
+ bool are_bytes_swapped()
+ {
+ return ( TIFFIsByteSwapped( _tiff_file.get() )) ? true : false;
+ }
+
+ bool is_tiled() const
+ {
+ return ( TIFFIsTiled( _tiff_file.get() )) ? true : false;
+ }
+
+ unsigned int get_default_strip_size()
+ {
+ return TIFFDefaultStripSize( _tiff_file.get()
+ , 0 );
+ }
+
+ std::size_t get_scanline_size()
+ {
+ return TIFFScanlineSize( _tiff_file.get() );
+ }
+
+ std::size_t get_tile_size()
+ {
+ return TIFFTileSize( _tiff_file.get() );
+ }
+
+
+ int get_field_defaulted( uint16_t*& red
+ , uint16_t*& green
+ , uint16_t*& blue
+ )
+ {
+ return TIFFGetFieldDefaulted( _tiff_file.get()
+ , TIFFTAG_COLORMAP
+ , &red
+ , &green
+ , &blue
+ );
+ }
+
+ template< typename Buffer >
+ void read_scanline( Buffer& buffer
+ , std::ptrdiff_t row
+ , tsample_t plane
+ )
+ {
+ io_error_if( TIFFReadScanline( _tiff_file.get()
+ , reinterpret_cast< tdata_t >( &buffer.front() )
+ , (uint32) row
+ , plane ) == -1
+ , "Read error."
+ );
+ }
+
+ void read_scanline( byte_t* buffer
+ , std::ptrdiff_t row
+ , tsample_t plane
+ )
+ {
+ io_error_if( TIFFReadScanline( _tiff_file.get()
+ , reinterpret_cast< tdata_t >( buffer )
+ , (uint32) row
+ , plane ) == -1
+ , "Read error."
+ );
+ }
+
+ template< typename Buffer >
+ void read_tile( Buffer& buffer
+ , std::ptrdiff_t x
+ , std::ptrdiff_t y
+ , std::ptrdiff_t z
+ , tsample_t plane
+ )
+ {
+ if( TIFFReadTile( _tiff_file.get()
+ , reinterpret_cast< tdata_t >( &buffer.front() )
+ , (uint32) x
+ , (uint32) y
+ , (uint32) z
+ , plane
+ ) == -1 )
+ {
+ std::ostringstream oss;
+ oss << "Read tile error (" << x << "," << y << "," << z << "," << plane << ").";
+ io_error(oss.str().c_str());
+ }
+ }
+
+ template< typename Buffer >
+ void write_scaline( Buffer& buffer
+ , uint32 row
+ , tsample_t plane
+ )
+ {
+ io_error_if( TIFFWriteScanline( _tiff_file.get()
+ , &buffer.front()
+ , row
+ , plane
+ ) == -1
+ , "Write error"
+ );
+ }
+
+ void write_scaline( byte_t* buffer
+ , uint32 row
+ , tsample_t plane
+ )
+ {
+ io_error_if( TIFFWriteScanline( _tiff_file.get()
+ , buffer
+ , row
+ , plane
+ ) == -1
+ , "Write error"
+ );
+ }
+
+ template< typename Buffer >
+ void write_tile( Buffer& buffer
+ , uint32 x
+ , uint32 y
+ , uint32 z
+ , tsample_t plane
+ )
+ {
+ if( TIFFWriteTile( _tiff_file.get()
+ , &buffer.front()
+ , x
+ , y
+ , z
+ , plane
+ ) == -1 )
+ {
+ std::ostringstream oss;
+ oss << "Write tile error (" << x << "," << y << "," << z << "," << plane << ").";
+ io_error(oss.str().c_str());
+ }
+ }
+
+ void set_directory( tdir_t directory )
+ {
+ io_error_if( TIFFSetDirectory( _tiff_file.get()
+ , directory
+ ) != 1
+ , "Failing to set directory"
+ );
+ }
+
+ // return false if the given tile width or height is not TIFF compliant (multiple of 16) or larger than image size, true otherwise
+ bool check_tile_size( tiff_tile_width::type& width
+ , tiff_tile_length::type& height
+
+ )
+ {
+ bool result = true;
+ uint32 tw = static_cast< uint32 >( width );
+ uint32 th = static_cast< uint32 >( height );
+
+ TIFFDefaultTileSize( _tiff_file.get()
+ , &tw
+ , &th
+ );
+
+ if(width==0 || width%16!=0)
+ {
+ width = tw;
+ result = false;
+ }
+ if(height==0 || height%16!=0)
+ {
+ height = th;
+ result = false;
+ }
+ return result;
+ }
+
+protected:
+
+ tiff_file_t _tiff_file;
+
+ Log _log;
+};
+
+/*!
+ *
+ * file_stream_device specialization for tiff images, which are based on TIFF*.
+ */
+template<>
+class file_stream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
+{
+public:
+
+ struct read_tag {};
+ struct write_tag {};
+
+ file_stream_device( std::string const& file_name, read_tag )
+ {
+ TIFF* tiff;
+
+ io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "r" )) == NULL
+ , "file_stream_device: failed to open file" );
+
+ _tiff_file = tiff_file_t( tiff, TIFFClose );
+ }
+
+ file_stream_device( std::string const& file_name, write_tag )
+ {
+ TIFF* tiff;
+
+ io_error_if( ( tiff = TIFFOpen( file_name.c_str(), "w" )) == NULL
+ , "file_stream_device: failed to open file" );
+
+ _tiff_file = tiff_file_t( tiff, TIFFClose );
+ }
+
+ file_stream_device( TIFF* tiff_file )
+ : tiff_device_base( tiff_file )
+ {}
+};
+
+/*!
+ *
+ * ostream_device specialization for tiff images.
+ */
+template<>
+class ostream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
+{
+public:
+ ostream_device( std::ostream & out )
+ : _out( out )
+ {
+ TIFF* tiff;
+
+ io_error_if( ( tiff = TIFFStreamOpen( ""
+ , &_out
+ )
+ ) == NULL
+ , "ostream_device: failed to stream"
+ );
+
+ _tiff_file = tiff_file_t( tiff, TIFFClose );
+ }
+
+private:
+ ostream_device& operator=( const ostream_device& ) { return *this; }
+
+private:
+
+ std::ostream& _out;
+};
+
+/*!
+ *
+ * ostream_device specialization for tiff images.
+ */
+template<>
+class istream_device< tiff_tag > : public tiff_device_base< tiff_no_log >
+{
+public:
+ istream_device( std::istream & in )
+ : _in( in )
+ {
+ TIFF* tiff;
+
+ io_error_if( ( tiff = TIFFStreamOpen( ""
+ , &_in
+ )
+ ) == NULL
+ , "istream_device: failed to stream"
+ );
+
+ _tiff_file = tiff_file_t( tiff, TIFFClose );
+ }
+
+private:
+ istream_device& operator=( const istream_device& ) { return *this; }
+
+private:
+
+ std::istream& _in;
+};
+
+/*
+template< typename T, typename D >
+struct is_adaptable_input_device< tiff_tag, T, D > : mpl::false_{};
+*/
+
+template< typename FormatTag >
+struct is_adaptable_input_device< FormatTag
+ , TIFF*
+ , void
+ >
+ : mpl::true_
+{
+ typedef file_stream_device< FormatTag > device_type;
+};
+
+template< typename FormatTag >
+struct is_adaptable_output_device< FormatTag
+ , TIFF*
+ , void
+ >
+ : mpl::true_
+{
+ typedef file_stream_device< FormatTag > device_type;
+};
+
+
+template < typename Channel > struct sample_format : public mpl::int_<SAMPLEFORMAT_UINT> {};
+template<> struct sample_format<uint8_t> : public mpl::int_<SAMPLEFORMAT_UINT> {};
+template<> struct sample_format<uint16_t> : public mpl::int_<SAMPLEFORMAT_UINT> {};
+template<> struct sample_format<uint32_t> : public mpl::int_<SAMPLEFORMAT_UINT> {};
+template<> struct sample_format<float32_t> : public mpl::int_<SAMPLEFORMAT_IEEEFP> {};
+template<> struct sample_format<double> : public mpl::int_<SAMPLEFORMAT_IEEEFP> {};
+template<> struct sample_format<int8_t> : public mpl::int_<SAMPLEFORMAT_INT> {};
+template<> struct sample_format<int16_t> : public mpl::int_<SAMPLEFORMAT_INT> {};
+template<> struct sample_format<int32_t> : public mpl::int_<SAMPLEFORMAT_INT> {};
+
+template <typename Channel> struct photometric_interpretation {};
+template<> struct photometric_interpretation< gray_t > : public mpl::int_< PHOTOMETRIC_MINISBLACK > {};
+template<> struct photometric_interpretation< rgb_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
+template<> struct photometric_interpretation< rgba_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
+template<> struct photometric_interpretation< cmyk_t > : public mpl::int_< PHOTOMETRIC_SEPARATED > {};
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/is_allowed.hpp b/boost/gil/extension/io/tiff/detail/is_allowed.hpp
new file mode 100644
index 0000000000..d88413a63e
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/is_allowed.hpp
@@ -0,0 +1,226 @@
+/*
+ Copyright 2008 Christian Henning, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/for_each.hpp>
+
+#include <boost/gil/io/base.hpp>
+
+namespace boost { namespace gil { namespace detail {
+
+typedef std::vector< tiff_bits_per_sample::type > channel_sizes_t;
+
+template< typename View, typename Channel, typename Enable = void > struct Format_Type {};
+
+// is_bit_aligned< View >
+template< typename View, typename Channel > struct Format_Type< View
+ , Channel
+ , typename boost::enable_if< typename is_bit_aligned< typename get_pixel_type< View >::type >::type >::type
+ >
+{
+ static const int value = SAMPLEFORMAT_UINT;
+};
+
+// is_not_bit_aligned< View > && is_unsigned< Channel >
+template< typename View, typename Channel > struct Format_Type< View
+ , Channel
+ , typename boost::enable_if< mpl::and_< mpl::not_< typename is_bit_aligned< typename get_pixel_type< View >::type >::type >
+ , is_unsigned< Channel >
+ >
+ >::type
+ >
+{
+ static const int value = SAMPLEFORMAT_UINT;
+};
+
+// is_not_bit_aligned< View > && is_signed< Channel >
+template< typename View, typename Channel > struct Format_Type< View
+ , Channel
+ , typename boost::enable_if< mpl::and_< mpl::not_< typename is_bit_aligned< typename get_pixel_type< View >::type >::type >
+ , is_signed< Channel >
+ >
+ >::type
+ >
+{
+ static const int value = SAMPLEFORMAT_INT;
+};
+
+// is_not_bit_aligned< View > && is_floating_point< Channel >
+template< typename View, typename Channel > struct Format_Type< View
+ , Channel
+ , typename boost::enable_if< mpl::and_< mpl::not_< typename is_bit_aligned< typename get_pixel_type< View >::type >::type >
+ , is_floating_point< Channel >
+ >
+ >::type
+ >
+{
+ static const int value = SAMPLEFORMAT_IEEEFP;
+};
+
+//template< typename Channel >
+//int format_value( mpl::true_ ) // is_bit_aligned
+//{
+// return SAMPLEFORMAT_UINT;
+//}
+//
+//template< typename Channel >
+//int format_value( mpl::false_ ) // is_bit_aligned
+//{
+// if( is_unsigned< Channel >::value )
+// {
+// return SAMPLEFORMAT_UINT;
+// }
+//
+// if( is_signed< Channel >::value )
+// {
+// return SAMPLEFORMAT_INT;
+// }
+//
+// else if( is_floating_point< Channel >::value )
+// {
+// return SAMPLEFORMAT_IEEEFP;
+// }
+//
+// io_error( "Unkown channel format." );
+//}
+
+// The following two functions look the same but are different since one is using
+// a pixel_t as template parameter whereas the other is using reference_t.
+template< typename View >
+bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
+ , mpl::false_ // is_bit_aligned
+ , mpl::true_ // is_homogeneous
+ )
+{
+ typedef typename View::value_type pixel_t;
+ typedef typename channel_traits<
+ typename element_type< pixel_t >::type >::value_type channel_t;
+
+ unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
+
+ return ( s == channel_sizes[0] );
+}
+
+
+template< typename View >
+bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
+ , mpl::true_ // is_bit_aligned
+ , mpl::true_ // is_homogeneous
+ )
+{
+ typedef typename View::reference ref_t;
+
+ typedef typename channel_traits< typename element_type< ref_t >::type >::value_type channel_t;
+ channel_t c;
+
+ unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
+
+ return ( s == channel_sizes[0] );
+}
+
+struct compare_channel_sizes_fn
+{
+ compare_channel_sizes_fn( uint16_t* a )
+ : _a( a )
+ , _b( true )
+ {}
+
+ template< typename ChannelSize >
+ void operator()( ChannelSize x)
+ {
+ if( x != *_a++ )
+ {
+ _b = false;
+ }
+ }
+
+ uint16_t* _a;
+ bool _b;
+};
+
+template< typename T >
+struct channel_sizes_type {};
+
+template< typename B, typename C, typename L, bool M >
+struct channel_sizes_type< bit_aligned_pixel_reference< B, C, L, M > > { typedef C type; };
+
+template< typename B, typename C, typename L, bool M >
+struct channel_sizes_type< const bit_aligned_pixel_reference< B, C, L, M > > { typedef C type; };
+
+template< typename View >
+bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
+ , mpl::true_ // is_bit_aligned
+ , mpl::false_ // is_homogeneous
+ )
+{
+ // loop through all channels and compare
+
+ typedef typename View::reference ref_t;
+ typedef typename channel_sizes_type< ref_t >::type cs_t;
+
+ compare_channel_sizes_fn fn( &channel_sizes.front() );
+ mpl::for_each< cs_t >( fn );
+
+ return fn._b;
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< tiff_tag >& info
+ , mpl::true_ // is read_and_no_convert
+ )
+{
+ channel_sizes_t channel_sizes( info._samples_per_pixel
+ , info._bits_per_sample
+ );
+
+ typedef typename get_pixel_type< View >::type pixel_t;
+ typedef typename channel_traits<
+ typename element_type< pixel_t >::type >::value_type channel_t;
+
+ typedef typename num_channels< pixel_t >::value_type num_channel_t;
+
+ const num_channel_t dst_samples_per_pixel = num_channels< pixel_t >::value;
+
+ //const num_channel_t dst_sample_format = format_value< channel_t >( typename is_bit_aligned< pixel_t >::type() );
+ const num_channel_t dst_sample_format = Format_Type<View, channel_t>::value;
+
+
+ return ( dst_samples_per_pixel == info._samples_per_pixel
+ && compare_channel_sizes< View >( channel_sizes
+ , typename is_bit_aligned< pixel_t >::type()
+ , typename is_homogeneous< pixel_t >::type()
+ )
+ && dst_sample_format == info._sample_format
+ );
+}
+
+template< typename View >
+bool is_allowed( const image_read_info< tiff_tag >& /* info */
+ , mpl::false_ // is read_and_no_convert
+ )
+{
+ return true;
+}
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/log.hpp b/boost/gil/extension/io/tiff/detail/log.hpp
new file mode 100644
index 0000000000..965a576d28
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/log.hpp
@@ -0,0 +1,77 @@
+/*
+ Copyright 2009 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_LOG_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_LOG_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2009 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+extern "C" {
+#include "tiffio.h"
+}
+
+#include <iostream>
+
+namespace boost { namespace gil {
+
+class tiff_no_log
+{
+public:
+
+ tiff_no_log()
+ {
+ TIFFSetErrorHandler ( NULL );
+ TIFFSetWarningHandler( NULL );
+ }
+};
+
+class console_log
+{
+public:
+
+ console_log()
+ {
+ TIFFSetErrorHandler ( console_log::error );
+ TIFFSetWarningHandler( console_log::warning );
+ }
+
+private:
+
+ static void error( const char* /* module */
+ , const char* fmt
+ , va_list ap
+ )
+ {
+ char buf[1000];
+ sprintf(buf, fmt, ap);
+ std::cout << "error: " << buf << std::endl;
+ }
+
+ static void warning( char const* /* module */
+ , char const* fmt
+ , va_list ap
+ )
+ {
+ char buf[1000];
+ sprintf(buf, fmt, ap);
+ std::cout << "warning: " << fmt << std::endl;
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/read.hpp b/boost/gil/extension/io/tiff/detail/read.hpp
new file mode 100644
index 0000000000..2471ff544e
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/read.hpp
@@ -0,0 +1,801 @@
+/*
+ Copyright 2007-2012 Christian Henning, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_READER_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_READER_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#endif
+
+#include <tiff.h>
+#include <tiffio.h>
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <boost/static_assert.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/reader_base.hpp>
+
+#include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/tiff/detail/device.hpp>
+#include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
+
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+template < int K >
+struct plane_recursion
+{
+ template< typename View
+ , typename Device
+ , typename ConversionPolicy
+ >
+ static
+ void read_plane( const View& dst_view
+ , reader< Device
+ , tiff_tag
+ , ConversionPolicy >* p
+ )
+ {
+ typedef typename kth_channel_view_type< K, View >::type plane_t;
+ plane_t plane = kth_channel_view<K>( dst_view );
+
+ p->template read_data< detail::row_buffer_helper_view< plane_t > >( plane, K );
+
+ plane_recursion< K - 1 >::read_plane( dst_view, p );
+ }
+};
+
+template <>
+struct plane_recursion< -1 >
+{
+ template< typename View
+ , typename Device
+ , typename ConversionPolicy
+ >
+ static
+ void read_plane( const View& /* dst_view */
+ , reader< Device
+ , tiff_tag
+ , ConversionPolicy
+ >* /* p */
+ )
+ {}
+};
+
+///
+/// Tiff Reader
+///
+template< typename Device
+ , typename ConversionPolicy
+ >
+class reader< Device
+ , tiff_tag
+ , ConversionPolicy
+ >
+ : public reader_base< tiff_tag
+ , ConversionPolicy >
+
+ , public reader_backend< Device
+ , tiff_tag
+ >
+{
+private:
+
+ typedef reader< Device
+ , tiff_tag
+ , ConversionPolicy
+ > this_t;
+
+ typedef typename ConversionPolicy::color_converter_type cc_t;
+
+public:
+
+ typedef reader_backend< Device, tiff_tag > backend_t;
+
+public:
+
+ reader( const Device& io_dev
+ , const image_read_settings< tiff_tag >& settings
+ )
+ : reader_base< tiff_tag
+ , ConversionPolicy
+ >()
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ reader( const Device& io_dev
+ , const typename ConversionPolicy::color_converter_type& cc
+ , const image_read_settings< tiff_tag >& settings
+ )
+ : reader_base< tiff_tag
+ , ConversionPolicy
+ >( cc )
+ , backend_t( io_dev
+ , settings
+ )
+ {}
+
+ // only works for homogeneous image types
+ template< typename View >
+ void apply( View& dst_view )
+ {
+ if( this->_info._photometric_interpretation == PHOTOMETRIC_PALETTE )
+ {
+ this->_scanline_length = this->_info._width
+ * num_channels< rgb16_view_t >::value
+ * sizeof( channel_type<rgb16_view_t>::type );
+
+ // Steps:
+ // 1. Read indices. It's an array of grayX_pixel_t.
+ // 2. Read palette. It's an array of rgb16_pixel_t.
+ // 3. ??? Create virtual image or transform the two arrays
+ // into a rgb16_image_t object. The latter might
+ // be a good first solution.
+
+ switch( this->_info._bits_per_sample )
+ {
+ case 1: { read_palette_image< gray1_image_t >( dst_view ); break; }
+ case 2: { read_palette_image< gray2_image_t >( dst_view ); break; }
+ case 4: { read_palette_image< gray4_image_t >( dst_view ); break; }
+ case 8: { read_palette_image< gray8_image_t >( dst_view ); break; }
+ case 16: { read_palette_image< gray16_image_t >( dst_view ); break; }
+
+ default: { io_error( "Not supported palette " ); }
+ }
+
+ return;
+
+ }
+ else
+ {
+ this->_scanline_length = this->_io_dev.get_scanline_size();
+
+ // In case we only read the image the user's type and
+ // the tiff type need to compatible. Which means:
+ // color_spaces_are_compatible && channels_are_pairwise_compatible
+
+ typedef typename is_same< ConversionPolicy
+ , detail::read_and_no_convert
+ >::type is_read_only;
+
+ io_error_if( !detail::is_allowed< View >( this->_info
+ , is_read_only()
+ )
+ , "Image types aren't compatible."
+ );
+
+ if( this->_info._planar_configuration == PLANARCONFIG_SEPARATE )
+ {
+ plane_recursion< num_channels< View >::value - 1 >::read_plane( dst_view
+ , this
+ );
+ }
+ else if( this->_info._planar_configuration == PLANARCONFIG_CONTIG )
+ {
+ read( dst_view
+ , typename is_read_only::type()
+ );
+ }
+ else
+ {
+ io_error( "Wrong planar configuration setting." );
+ }
+ }
+ }
+
+private:
+
+ template< typename View >
+ void read( View v
+ , mpl::true_ // is_read_only
+ )
+ {
+ read_data< detail::row_buffer_helper_view< View > >( v, 0 );
+ }
+
+ template< typename View >
+ void read( View v
+ , mpl::false_ // is_read_only
+ )
+ {
+ // the read_data function needs to know what gil type the source image is
+ // to have the default color converter function correctly
+
+ switch( this->_info._photometric_interpretation )
+ {
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 1: { read_data< detail::row_buffer_helper_view< gray1_image_t::view_t > >( v, 0 ); break; }
+ case 2: { read_data< detail::row_buffer_helper_view< gray2_image_t::view_t > >( v, 0 ); break; }
+ case 4: { read_data< detail::row_buffer_helper_view< gray4_image_t::view_t > >( v, 0 ); break; }
+ case 8: { read_data< detail::row_buffer_helper_view< gray8_view_t > >( v, 0 ); break; }
+ case 16: { read_data< detail::row_buffer_helper_view< gray16_view_t > >( v, 0 ); break; }
+ case 32: { read_data< detail::row_buffer_helper_view< gray32_view_t > >( v, 0 ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ case PHOTOMETRIC_RGB:
+ {
+ switch( this->_info._samples_per_pixel )
+ {
+ case 3:
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 8: { read_data< detail::row_buffer_helper_view< rgb8_view_t > >( v, 0 ); break; }
+ case 16: { read_data< detail::row_buffer_helper_view< rgb16_view_t > >( v, 0 ); break; }
+ case 32: { read_data< detail::row_buffer_helper_view< rgb32_view_t > >( v, 0 ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 8: { read_data< detail::row_buffer_helper_view< rgba8_view_t > >( v, 0 ); break; }
+ case 16: { read_data< detail::row_buffer_helper_view< rgba16_view_t > >( v, 0 ); break; }
+ case 32: { read_data< detail::row_buffer_helper_view< rgba32_view_t > >( v, 0 ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+ case PHOTOMETRIC_SEPARATED: // CYMK
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 8: { read_data< detail::row_buffer_helper_view< cmyk8_view_t > >( v, 0 ); break; }
+ case 16: { read_data< detail::row_buffer_helper_view< cmyk16_view_t > >( v, 0 ); break; }
+ case 32: { read_data< detail::row_buffer_helper_view< cmyk32_view_t > >( v, 0 ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ default: { io_error( "Image type is not supported." ); }
+ }
+ }
+
+ template< typename PaletteImage
+ , typename View
+ >
+ void read_palette_image( const View& dst_view )
+ {
+ PaletteImage indices( this->_info._width - this->_settings._top_left.x
+ , this->_info._height - this->_settings._top_left.y );
+
+ // read the palette first
+ read_data< detail::row_buffer_helper_view< typename PaletteImage::view_t > >( view( indices ), 0 );
+
+ read_palette_image( dst_view
+ , view( indices )
+ , typename is_same< View, rgb16_view_t >::type() );
+ }
+
+ template< typename View
+ , typename Indices_View
+ >
+ void read_palette_image( const View& dst_view
+ , const Indices_View& indices_view
+ , mpl::true_ // is View rgb16_view_t
+ )
+ {
+ tiff_color_map::red_t red = NULL;
+ tiff_color_map::green_t green = NULL;
+ tiff_color_map::blue_t blue = NULL;
+
+ this->_io_dev.get_field_defaulted( red, green, blue );
+
+ typedef typename channel_traits<
+ typename element_type<
+ typename Indices_View::value_type >::type >::value_type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value();
+
+ rgb16_planar_view_t palette = planar_rgb_view( num_colors
+ , 1
+ , red
+ , green
+ , blue
+ , sizeof(uint16_t) * num_colors );
+
+ for( typename rgb16_view_t::y_coord_t y = 0; y < dst_view.height(); ++y )
+ {
+ typename rgb16_view_t::x_iterator it = dst_view.row_begin( y );
+ typename rgb16_view_t::x_iterator end = dst_view.row_end( y );
+
+ typename Indices_View::x_iterator indices_it = indices_view.row_begin( y );
+
+ for( ; it != end; ++it, ++indices_it )
+ {
+ uint16_t i = gil::at_c<0>( *indices_it );
+
+ *it = palette[i];
+ }
+ }
+ }
+
+ template< typename View
+ , typename Indices_View
+ >
+ inline
+ void read_palette_image( const View& /* dst_view */
+ , const Indices_View& /* indices_view */
+ , mpl::false_ // is View rgb16_view_t
+ )
+ {
+ io_error( "User supplied image type must be rgb16_image_t." );
+ }
+
+ template< typename Buffer >
+ void skip_over_rows( Buffer& buffer
+ , int plane
+ )
+ {
+ if( this->_info._compression != COMPRESSION_NONE )
+ {
+ // Skipping over rows is not possible for compressed images( no random access ). See man
+ // page ( diagnostics section ) for more information.
+ for( std::ptrdiff_t row = 0; row < this->_settings._top_left.y; ++row )
+ {
+ this->_io_dev.read_scanline( buffer
+ , row
+ , static_cast< tsample_t >( plane ));
+ }
+ }
+ }
+
+ template< typename Buffer
+ , typename View
+ >
+ void read_data( const View& dst_view
+ , int /* plane */ )
+ {
+ if( this->_io_dev.is_tiled() )
+ {
+ read_tiled_data< Buffer >( dst_view, 0 );
+ }
+ else
+ {
+ read_stripped_data< Buffer >( dst_view, 0 );
+ }
+ }
+
+
+ template< typename Buffer
+ , typename View
+ >
+ void read_tiled_data( const View& dst_view
+ , int plane
+ )
+ {
+ if( dst_view.width() != this->_info._width
+ || dst_view.height() != this->_info._height
+ )
+ {
+ // read a subimage
+ read_tiled_data_subimage< Buffer >( dst_view, plane );
+ }
+ else
+ {
+ // read full image
+ read_tiled_data_full< Buffer >( dst_view, plane );
+ }
+ }
+
+ template< typename Buffer
+ , typename View
+ >
+ void read_tiled_data_subimage( const View& dst_view
+ , int plane
+ )
+ {
+ ///@todo: why is
+ /// typedef Buffer row_buffer_helper_t;
+ /// not working? I get compiler error with MSVC10.
+ /// read_stripped_data IS working.
+ typedef detail::row_buffer_helper_view< View > row_buffer_helper_t;
+
+ typedef typename row_buffer_helper_t::iterator_t it_t;
+
+ tiff_image_width::type image_width = this->_info._width;
+ tiff_image_height::type image_height = this->_info._height;
+
+ tiff_tile_width::type tile_width = this->_info._tile_width;
+ tiff_tile_length::type tile_height = this->_info._tile_length;
+
+ std::ptrdiff_t subimage_x = this->_settings._top_left.x;
+ std::ptrdiff_t subimage_y = this->_settings._top_left.y;
+
+ std::ptrdiff_t subimage_width = this->_settings._dim.x;
+ std::ptrdiff_t subimage_height = this->_settings._dim.y;
+
+ row_buffer_helper_t row_buffer_helper(this->_io_dev.get_tile_size(), true );
+
+ for( unsigned int y = 0; y < image_height; y += tile_height )
+ {
+ for( unsigned int x = 0; x < image_width; x += tile_width )
+ {
+ uint32_t current_tile_width = ( x + tile_width < image_width ) ? tile_width : image_width - x;
+ uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;
+
+ this->_io_dev.read_tile( row_buffer_helper.buffer()
+ , x
+ , y
+ , 0
+ , static_cast< tsample_t >( plane )
+ );
+
+ // these are all whole image coordinates
+ point_t tile_top_left ( x, y );
+ point_t tile_lower_right( x + current_tile_width - 1, y + current_tile_length - 1 );
+
+ point_t view_top_left ( subimage_x, subimage_y );
+ point_t view_lower_right( subimage_x + subimage_width - 1
+ , subimage_y + subimage_height - 1 );
+
+ if( tile_top_left.x > view_lower_right.x
+ || tile_top_left.y > view_lower_right.y
+ || tile_lower_right.x < view_top_left.x
+ || tile_lower_right.y < view_top_left.y
+ )
+ {
+ // current tile and dst_view do not overlap
+ continue;
+ }
+ else
+ {
+ // dst_view is overlapping the current tile
+
+ // next is to define the portion in the tile that needs to be copied
+
+ // get the whole image coordinates
+ std::ptrdiff_t img_x0 = ( tile_top_left.x >= view_top_left.x ) ? tile_top_left.x : view_top_left.x;
+ std::ptrdiff_t img_y0 = ( tile_top_left.y >= view_top_left.y ) ? tile_top_left.y : view_top_left.y;
+
+ std::ptrdiff_t img_x1 = ( tile_lower_right.x <= view_lower_right.x ) ? tile_lower_right.x : view_lower_right.x;
+ std::ptrdiff_t img_y1 = ( tile_lower_right.y <= view_lower_right.y ) ? tile_lower_right.y : view_lower_right.y;
+
+ // convert to tile coordinates
+ std::ptrdiff_t tile_x0 = img_x0 - x;
+ std::ptrdiff_t tile_y0 = img_y0 - y;
+ std::ptrdiff_t tile_x1 = img_x1 - x;
+ std::ptrdiff_t tile_y1 = img_y1 - y;
+
+ assert( tile_x0 >= 0 && tile_y0 >= 0 && tile_x1 >= 0 && tile_y1 >= 0 );
+ assert( tile_x0 <= img_x1 && tile_y0 <= img_y1 );
+ assert( tile_x0 < tile_width && tile_y0 < tile_height && tile_x1 < tile_width && tile_y1 < tile_height );
+
+ std::ptrdiff_t tile_subimage_view_width = tile_x1 - tile_x0 + 1;
+ std::ptrdiff_t tile_subimage_view_height = tile_y1 - tile_y0 + 1;
+
+ // convert to dst_view coordinates
+ std::ptrdiff_t dst_x0 = img_x0 - subimage_x;
+ std::ptrdiff_t dst_y0 = img_y0 - subimage_y;
+ assert( dst_x0 >= 0 && dst_y0 >= 0 );
+
+ View dst_subimage_view = subimage_view( dst_view
+ , (int) dst_x0
+ , (int) dst_y0
+ , (int) tile_subimage_view_width
+ , (int) tile_subimage_view_height
+ );
+
+ // the row_buffer is a 1D array which represents a 2D image. We cannot
+ // use interleaved_view here, since row_buffer could be bit_aligned.
+ // Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
+ // for bit_aligned pixels.
+
+ for( std::ptrdiff_t dst_row = 0; dst_row < dst_subimage_view.height(); ++dst_row )
+ {
+ std::ptrdiff_t tile_row = dst_row + tile_y0;
+
+ // jump to the beginning of the current tile row
+ it_t begin = row_buffer_helper.begin() + tile_row * tile_width;
+
+ begin += tile_x0;
+ it_t end = begin + dst_subimage_view.width();
+
+ this->_cc_policy.read( begin
+ , end
+ , dst_subimage_view.row_begin( dst_row )
+ );
+ } //for
+ }
+ } // for
+ } // for
+ }
+
+ template< typename Buffer
+ , typename View
+ >
+ void read_tiled_data_full( const View& dst_view
+ , int plane
+ )
+ {
+ ///@todo: why is
+ /// typedef Buffer row_buffer_helper_t;
+ /// not working? I get compiler error with MSVC10.
+ /// read_stripped_data IS working.
+ typedef detail::row_buffer_helper_view< View > row_buffer_helper_t;
+
+ typedef typename row_buffer_helper_t::iterator_t it_t;
+
+ tiff_image_width::type image_width = this->_info._width;
+ tiff_image_height::type image_height = this->_info._height;
+
+ tiff_tile_width::type tile_width = this->_info._tile_width;
+ tiff_tile_length::type tile_height = this->_info._tile_length;
+
+ row_buffer_helper_t row_buffer_helper(this->_io_dev.get_tile_size(), true );
+
+ for( unsigned int y = 0; y < image_height; y += tile_height )
+ {
+ for( unsigned int x = 0; x < image_width; x += tile_width )
+ {
+ uint32_t current_tile_width = ( x + tile_width < image_width ) ? tile_width : image_width - x;
+ uint32_t current_tile_length = ( y + tile_height < image_height ) ? tile_height : image_height - y;
+
+ this->_io_dev.read_tile( row_buffer_helper.buffer()
+ , x
+ , y
+ , 0
+ , static_cast< tsample_t >( plane )
+ );
+
+ View dst_subimage_view = subimage_view( dst_view
+ , x
+ , y
+ , current_tile_width
+ , current_tile_length
+ );
+
+ // the row_buffer is a 1D array which represents a 2D image. We cannot
+ // use interleaved_view here, since row_buffer could be bit_aligned.
+ // Interleaved_view's fourth parameter "rowsize_in_bytes" doesn't work
+ // for bit_aligned pixels.
+
+ for( int row = 0; row < dst_subimage_view.height(); ++row )
+ {
+ it_t begin = row_buffer_helper.begin() + row * tile_width;
+ it_t end = begin + dst_subimage_view.width();
+
+ this->_cc_policy.read( begin
+ , end
+ , dst_subimage_view.row_begin( row )
+ );
+ } //for
+ } // for
+ } // for
+ }
+
+ template< typename Buffer
+ , typename View
+ >
+ void read_stripped_data( const View& dst_view
+ , int plane )
+ {
+ typedef typename is_bit_aligned< typename View::value_type >::type is_view_bit_aligned_t;
+
+ //typedef detail::row_buffer_helper_view< View > row_buffer_helper_t;
+ typedef Buffer row_buffer_helper_t;
+
+ typedef typename row_buffer_helper_t::iterator_t it_t;
+
+ std::size_t size_to_allocate = buffer_size< typename View::value_type >( dst_view.width()
+ , is_view_bit_aligned_t() );
+ row_buffer_helper_t row_buffer_helper( size_to_allocate, true );
+
+ it_t begin = row_buffer_helper.begin();
+
+ it_t first = begin + this->_settings._top_left.x;
+ it_t last = first + this->_settings._dim.x; // one after last element
+
+ // I don't think tiff allows for random access of row, that's why we need
+ // to read and discard rows when reading subimages.
+ skip_over_rows( row_buffer_helper.buffer()
+ , plane
+ );
+
+ std::ptrdiff_t row = this->_settings._top_left.y;
+ std::ptrdiff_t row_end = row + this->_settings._dim.y;
+ std::ptrdiff_t dst_row = 0;
+
+ for(
+ ; row < row_end
+ ; ++row, ++dst_row
+ )
+ {
+ this->_io_dev.read_scanline( row_buffer_helper.buffer()
+ , row
+ , static_cast< tsample_t >( plane )
+ );
+
+ this->_cc_policy.read( first
+ , last
+ , dst_view.row_begin( dst_row ));
+ }
+ }
+
+ template< typename Pixel >
+ std::size_t buffer_size( std::size_t width
+ , mpl::false_ // is_bit_aligned
+ )
+ {
+ std::size_t scanline_size_in_bytes = this->_io_dev.get_scanline_size();
+
+ std::size_t element_size = sizeof( Pixel );
+
+ std::size_t ret = std::max( width
+ , (( scanline_size_in_bytes + element_size - 1 ) / element_size )
+ );
+
+ return ret;
+ }
+
+ template< typename Pixel >
+ std::size_t buffer_size( std::size_t /* width */
+ , mpl::true_ // is_bit_aligned
+ )
+ {
+ return this->_io_dev.get_scanline_size();
+ }
+
+private:
+
+ template < int K > friend struct plane_recursion;
+};
+
+namespace detail {
+
+struct tiff_type_format_checker
+{
+ tiff_type_format_checker( const image_read_info< tiff_tag >& info )
+ : _info( info )
+ {}
+
+ template< typename Image >
+ bool apply()
+ {
+ typedef typename Image::view_t view_t;
+
+ return is_allowed< view_t >( _info
+ , mpl::true_()
+ );
+ }
+
+private:
+ tiff_type_format_checker& operator=( const tiff_type_format_checker& ) { return *this; }
+
+private:
+
+ const image_read_info< tiff_tag > _info;
+};
+
+struct tiff_read_is_supported
+{
+ template< typename View >
+ struct apply : public is_read_supported< typename get_pixel_type< View >::type
+ , tiff_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+
+///
+/// Tiff Dynamic Image Reader
+///
+template< typename Device >
+class dynamic_image_reader< Device
+ , tiff_tag
+ >
+ : public reader< Device
+ , tiff_tag
+ , detail::read_and_no_convert
+ >
+{
+ typedef reader< Device
+ , tiff_tag
+ , detail::read_and_no_convert
+ > parent_t;
+
+public:
+
+ dynamic_image_reader( const Device& io_dev
+ , const image_read_settings< tiff_tag >& settings
+ )
+ : parent_t( io_dev
+ , settings
+ )
+ {}
+
+ template< typename Images >
+ void apply( any_image< Images >& images )
+ {
+ detail::tiff_type_format_checker format_checker( this->_info );
+
+ if( !construct_matched( images
+ , format_checker
+ ))
+ {
+ io_error( "No matching image type between those of the given any_image and that of the file" );
+ }
+ else
+ {
+ this->init_image( images
+ , this->_settings
+ );
+
+ detail::dynamic_io_fnobj< detail::tiff_read_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( view( images )
+ , op
+ );
+ }
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/reader_backend.hpp b/boost/gil/extension/io/tiff/detail/reader_backend.hpp
new file mode 100644
index 0000000000..d2a308f7d7
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/reader_backend.hpp
@@ -0,0 +1,173 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_READER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_READER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/tiff/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// TIFF Backend
+///
+template< typename Device >
+struct reader_backend< Device
+ , tiff_tag
+ >
+{
+public:
+
+ typedef tiff_tag format_tag_t;
+
+public:
+
+ reader_backend( const Device& io_dev
+ , const image_read_settings< tiff_tag >& settings
+ )
+ : _io_dev ( io_dev )
+ , _settings( settings )
+ , _info()
+
+ , _scanline_length( 0 )
+
+ , _red ( NULL )
+ , _green( NULL )
+ , _blue ( NULL )
+ {
+ init_multipage_read( settings );
+
+ read_header();
+
+ if( _settings._dim.x == 0 )
+ {
+ _settings._dim.x = _info._width;
+ }
+
+ if( _settings._dim.y == 0 )
+ {
+ _settings._dim.y = _info._height;
+ }
+ }
+
+ void read_header()
+ {
+ io_error_if( _io_dev.template get_property<tiff_image_width> ( _info._width ) == false
+ , "cannot read tiff tag." );
+ io_error_if( _io_dev.template get_property<tiff_image_height> ( _info._height ) == false
+ , "cannot read tiff tag." );
+ io_error_if( _io_dev.template get_property<tiff_compression> ( _info._compression ) == false
+ , "cannot read tiff tag." );
+ io_error_if( _io_dev.template get_property<tiff_samples_per_pixel> ( _info._samples_per_pixel ) == false
+ , "cannot read tiff tag." );
+ io_error_if( _io_dev.template get_property<tiff_bits_per_sample> ( _info._bits_per_sample ) == false
+ , "cannot read tiff tag." );
+ io_error_if( _io_dev.template get_property<tiff_sample_format> ( _info._sample_format ) == false
+ , "cannot read tiff tag." );
+ io_error_if( _io_dev.template get_property<tiff_planar_configuration> ( _info._planar_configuration ) == false
+ , "cannot read tiff tag." );
+ io_error_if( _io_dev.template get_property<tiff_photometric_interpretation>( _info._photometric_interpretation ) == false
+ , "cannot read tiff tag." );
+
+ _info._is_tiled = false;
+
+ // Tile tags
+ if( _io_dev.is_tiled() )
+ {
+ _info._is_tiled = true;
+
+ io_error_if( !_io_dev.template get_property< tiff_tile_width >( _info._tile_width )
+ , "cannot read tiff_tile_width tag." );
+ io_error_if( !_io_dev.template get_property< tiff_tile_length >( _info._tile_length )
+ , "cannot read tiff_tile_length tag." );
+ }
+
+ io_error_if( _io_dev.template get_property<tiff_resolution_unit>( _info._resolution_unit) == false
+ , "cannot read tiff tag");
+ io_error_if( _io_dev. template get_property<tiff_x_resolution>( _info._x_resolution ) == false
+ , "cannot read tiff tag" );
+ io_error_if( _io_dev. template get_property<tiff_y_resolution>( _info._y_resolution ) == false
+ , "cannot read tiff tag" );
+
+ /// optional and non-baseline properties below here
+ _io_dev. template get_property <tiff_icc_profile> ( _info._icc_profile );
+ }
+
+ /// Check if image is large enough.
+ void check_image_size( const point_t& img_dim )
+ {
+ if( _settings._dim.x > 0 )
+ {
+ if( img_dim.x < _settings._dim.x ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( (tiff_image_width::type) img_dim.x < _info._width ) { io_error( "Supplied image is too small" ); }
+ }
+
+
+ if( _settings._dim.y > 0 )
+ {
+ if( img_dim.y < _settings._dim.y ) { io_error( "Supplied image is too small" ); }
+ }
+ else
+ {
+ if( (tiff_image_height::type) img_dim.y < _info._height ) { io_error( "Supplied image is too small" ); }
+ }
+ }
+
+private:
+
+ void init_multipage_read( const image_read_settings< tiff_tag >& settings )
+ {
+ if( settings._directory > 0 )
+ {
+ _io_dev.set_directory( settings._directory );
+ }
+ }
+
+public:
+
+ Device _io_dev;
+
+ image_read_settings< tiff_tag > _settings;
+ image_read_info< tiff_tag > _info;
+
+ std::size_t _scanline_length;
+
+ // palette
+ tiff_color_map::red_t _red;
+ tiff_color_map::green_t _green;
+ tiff_color_map::blue_t _blue;
+
+ rgb16_planar_view_t _palette;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/scanline_read.hpp b/boost/gil/extension/io/tiff/detail/scanline_read.hpp
new file mode 100644
index 0000000000..7e7e2cc8b7
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/scanline_read.hpp
@@ -0,0 +1,465 @@
+/*
+ Copyright 2007-2012 Christian Henning, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_SCANLINE_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_SCANLINE_READ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#endif
+
+#include <tiff.h>
+#include <tiffio.h>
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+#include <boost/function.hpp>
+#include <boost/static_assert.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/conversion_policies.hpp>
+#include <boost/gil/io/bit_operations.hpp>
+#include <boost/gil/io/row_buffer_helper.hpp>
+#include <boost/gil/io/device.hpp>
+#include <boost/gil/io/reader_base.hpp>
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>
+#include <boost/gil/extension/io/tiff/detail/device.hpp>
+#include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
+
+
+namespace boost { namespace gil {
+
+///
+/// TIFF scanline reader
+///
+template< typename Device >
+class scanline_reader< Device
+ , tiff_tag
+ >
+ : public reader_backend< Device
+ , tiff_tag
+ >
+{
+public:
+
+
+ typedef tiff_tag tag_t;
+ typedef reader_backend < Device, tag_t > backend_t;
+ typedef scanline_reader< Device, tag_t > this_t;
+ typedef scanline_read_iterator< this_t > iterator_t;
+
+public:
+
+ scanline_reader( Device& device
+ , const image_read_settings< tiff_tag >& settings
+ )
+ : backend_t( device
+ , settings
+ )
+ {
+ initialize();
+ }
+
+ /// Read part of image defined by View and return the data.
+ void read( byte_t* dst, int pos )
+ {
+ _read_function( this, dst, pos );
+ }
+
+ /// Skip over a scanline.
+ void skip( byte_t* dst, int pos )
+ {
+ this->_read_function( this, dst, pos );
+ }
+
+ iterator_t begin() { return iterator_t( *this ); }
+ iterator_t end() { return iterator_t( *this, this->_info._height ); }
+
+private:
+
+ void initialize()
+ {
+ io_error_if( this->_info._is_tiled
+ , "scanline_reader doesn't support tiled tiff images."
+ );
+
+ if( this->_info._photometric_interpretation == PHOTOMETRIC_PALETTE )
+ {
+
+ this->_scanline_length = this->_info._width
+ * num_channels< rgb16_view_t >::value
+ * sizeof( channel_type<rgb16_view_t>::type );
+
+ this->_io_dev.get_field_defaulted( this->_red
+ , this->_green
+ , this->_blue
+ );
+
+ _buffer = std::vector< byte_t >( this->_io_dev.get_scanline_size() );
+
+ switch( this->_info._bits_per_sample )
+ {
+ case 1:
+ {
+ typedef channel_type< get_pixel_type< gray1_image_t::view_t >::type >::type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value() + 1;
+
+ this->_palette = planar_rgb_view( num_colors
+ , 1
+ , this->_red
+ , this->_green
+ , this->_blue
+ , sizeof(uint16_t) * num_colors
+ );
+
+ _read_function = boost::mem_fn( &this_t::read_1_bit_index_image );
+
+ break;
+ }
+
+ case 2:
+ {
+ typedef channel_type< get_pixel_type< gray2_image_t::view_t >::type >::type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value() + 1;
+
+ this->_palette = planar_rgb_view( num_colors
+ , 1
+ , this->_red
+ , this->_green
+ , this->_blue
+ , sizeof(uint16_t) * num_colors
+ );
+
+ _read_function = boost::mem_fn( &this_t::read_2_bits_index_image );
+
+ break;
+ }
+ case 4:
+ {
+ typedef channel_type< get_pixel_type< gray4_image_t::view_t >::type >::type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value() + 1;
+
+ this->_palette = planar_rgb_view( num_colors
+ , 1
+ , this->_red
+ , this->_green
+ , this->_blue
+ , sizeof(uint16_t) * num_colors
+ );
+
+ _read_function = boost::mem_fn( &this_t::read_4_bits_index_image );
+
+ break;
+ }
+
+ case 8:
+ {
+ typedef channel_type< get_pixel_type< gray8_image_t::view_t >::type >::type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value() + 1;
+
+ this->_palette = planar_rgb_view( num_colors
+ , 1
+ , this->_red
+ , this->_green
+ , this->_blue
+ , sizeof(uint16_t) * num_colors
+ );
+
+ _read_function = boost::mem_fn( &this_t::read_8_bits_index_image );
+
+ break;
+ }
+
+ case 16:
+ {
+ typedef channel_type< get_pixel_type< gray16_image_t::view_t >::type >::type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value() + 1;
+
+ this->_palette = planar_rgb_view( num_colors
+ , 1
+ , this->_red
+ , this->_green
+ , this->_blue
+ , sizeof(uint16_t) * num_colors
+ );
+
+ _read_function = boost::mem_fn( &this_t::read_16_bits_index_image );
+
+ break;
+ }
+
+ case 24:
+ {
+ typedef channel_type< get_pixel_type< gray24_image_t::view_t >::type >::type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value() + 1;
+
+ this->_palette = planar_rgb_view( num_colors
+ , 1
+ , this->_red
+ , this->_green
+ , this->_blue
+ , sizeof(uint16_t) * num_colors
+ );
+
+ _read_function = boost::mem_fn( &this_t::read_24_bits_index_image );
+
+ break;
+ }
+
+ case 32:
+ {
+ typedef channel_type< get_pixel_type< gray32_image_t::view_t >::type >::type channel_t;
+
+ int num_colors = channel_traits< channel_t >::max_value() + 1;
+
+ this->_palette = planar_rgb_view( num_colors
+ , 1
+ , this->_red
+ , this->_green
+ , this->_blue
+ , sizeof(uint16_t) * num_colors
+ );
+
+ _read_function = boost::mem_fn( &this_t::read_32_bits_index_image );
+
+ break;
+ }
+ default: { io_error( "Not supported palette " ); }
+ }
+ }
+ else
+ {
+ this->_scanline_length = this->_io_dev.get_scanline_size();
+
+ if( this->_info._planar_configuration == PLANARCONFIG_SEPARATE )
+ {
+ io_error( "scanline_reader doesn't support planar tiff images." );
+ }
+ else if( this->_info._planar_configuration == PLANARCONFIG_CONTIG )
+ {
+
+ // the read_data function needs to know what gil type the source image is
+ // to have the default color converter function correctly
+
+ switch( this->_info._photometric_interpretation )
+ {
+ case PHOTOMETRIC_MINISWHITE:
+ case PHOTOMETRIC_MINISBLACK:
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 6:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ case 16:
+ case 24:
+ case 32: { _read_function = boost::mem_fn( &this_t::read_row ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ case PHOTOMETRIC_RGB:
+ {
+ switch( this->_info._samples_per_pixel )
+ {
+ case 3:
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 2:
+ case 4:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ case 16:
+ case 24:
+ case 32: { _read_function = boost::mem_fn( &this_t::read_row ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ case 4:
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 2:
+ case 4:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ case 16:
+ case 24:
+ case 32: { _read_function = boost::mem_fn( &this_t::read_row ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+ case PHOTOMETRIC_SEPARATED: // CYMK
+ {
+ switch( this->_info._bits_per_sample )
+ {
+ case 2:
+ case 4:
+ case 8:
+ case 10:
+ case 12:
+ case 14:
+ case 16:
+ case 24:
+ case 32: { _read_function = boost::mem_fn( &this_t::read_row ); break; }
+ default: { io_error( "Image type is not supported." ); }
+ }
+
+ break;
+ }
+
+ default: { io_error( "Image type is not supported." ); }
+ }
+ }
+ else
+ {
+ io_error( "Wrong planar configuration setting." );
+ }
+ }
+ }
+
+ template< typename Src_View >
+ void read_n_bits_row( byte_t* dst, int pos )
+ {
+ typedef rgb16_view_t dst_view_t;
+
+ this->_io_dev.read_scanline( _buffer
+ , pos
+ , 0
+ );
+
+ Src_View src_view = interleaved_view( this->_info._width
+ , 1
+ , (typename Src_View::x_iterator) &_buffer.front()
+ , this->_scanline_length
+ );
+
+ dst_view_t dst_view = interleaved_view( this->_info._width
+ , 1
+ , (typename dst_view_t::value_type*) dst
+ , num_channels< dst_view_t >::value * 2 * this->_info._width
+ );
+
+
+ typename Src_View::x_iterator src_it = src_view.row_begin( 0 );
+ typename dst_view_t::x_iterator dst_it = dst_view.row_begin( 0 );
+
+ for( dst_view_t::x_coord_t i = 0
+ ; i < this->_info._width
+ ; ++i, src_it++, dst_it++
+ )
+ {
+ auto const c = static_cast<std::uint16_t>(get_color(*src_it, gray_color_t()));
+ *dst_it = this->_palette[c];
+ }
+ }
+
+ void read_1_bit_index_image( byte_t* dst, int pos )
+ {
+ read_n_bits_row< gray1_image_t::view_t >( dst, pos );
+ }
+
+ void read_2_bits_index_image( byte_t* dst, int pos )
+ {
+ read_n_bits_row< gray2_image_t::view_t >( dst, pos );
+ }
+
+ void read_4_bits_index_image( byte_t* dst, int pos )
+ {
+ read_n_bits_row< gray4_image_t::view_t >( dst, pos );
+ }
+
+ void read_8_bits_index_image( byte_t* dst, int pos )
+ {
+ read_n_bits_row< gray8_image_t::view_t >( dst, pos );
+ }
+
+ void read_16_bits_index_image( byte_t* dst, int pos )
+ {
+ read_n_bits_row< gray16_image_t::view_t >( dst, pos );
+ }
+
+ void read_24_bits_index_image( byte_t* dst, int pos )
+ {
+ read_n_bits_row< gray24_image_t::view_t >( dst, pos );
+ }
+
+ void read_32_bits_index_image( byte_t* dst, int pos )
+ {
+ read_n_bits_row< gray32_image_t::view_t >( dst, pos );
+ }
+
+ void read_row(byte_t* dst, int pos )
+ {
+ this->_io_dev.read_scanline( dst
+ , pos
+ , 0
+ );
+ }
+
+private:
+
+ std::vector< byte_t > _buffer;
+
+ detail::mirror_bits< std::vector< byte_t >, mpl::true_ > _mirror_bites;
+
+ boost::function< void ( this_t*, byte_t*, int ) > _read_function;
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/supported_types.hpp b/boost/gil/extension/io/tiff/detail/supported_types.hpp
new file mode 100644
index 0000000000..7e08dffb55
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/supported_types.hpp
@@ -0,0 +1,62 @@
+/*
+ Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_SUPPORTED_TYPES_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_SUPPORTED_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/not.hpp>
+#include <boost/type_traits/is_same.hpp>
+
+#include <boost/gil/channel.hpp>
+#include <boost/gil/color_base.hpp>
+
+namespace boost{ namespace gil {
+
+namespace detail {
+
+// Read support
+
+// TIFF virtually supports everything
+struct tiff_read_support : read_support_true
+{};
+
+
+// Write support
+
+struct tiff_write_support : write_support_true
+{};
+
+} // namespace detail
+
+template< typename Pixel >
+struct is_read_supported< Pixel
+ , tiff_tag
+ >
+ : mpl::bool_< detail::tiff_read_support::is_supported > {};
+
+template< typename Pixel >
+struct is_write_supported< Pixel
+ , tiff_tag
+ >
+ : mpl::bool_< detail::tiff_write_support::is_supported >
+{};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/write.hpp b/boost/gil/extension/io/tiff/detail/write.hpp
new file mode 100644
index 0000000000..06b72858d8
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/write.hpp
@@ -0,0 +1,463 @@
+/*
+ Copyright 2007-2012 Christian Henning, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Lubomir Bourdev \n
+///
+/// \date 2007-2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+extern "C" {
+#include "tiff.h"
+#include "tiffio.h"
+}
+
+#include <algorithm>
+#include <string>
+#include <vector>
+#include <boost/static_assert.hpp>
+
+#include <boost/gil/premultiply.hpp>
+
+#include <boost/gil/extension/io/tiff/tags.hpp>
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/io/device.hpp>
+
+#include <boost/gil/extension/io/tiff/detail/writer_backend.hpp>
+#include <boost/gil/extension/io/tiff/detail/device.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+namespace detail {
+
+template <typename PixelReference>
+struct my_interleaved_pixel_iterator_type_from_pixel_reference
+{
+private:
+ typedef typename remove_reference< PixelReference >::type::value_type pixel_t;
+public:
+ typedef typename iterator_type_from_pixel< pixel_t
+ , false
+ , false
+ , true
+ >::type type;
+};
+
+
+template< typename Channel
+ , typename Layout
+ , bool Mutable
+ >
+struct my_interleaved_pixel_iterator_type_from_pixel_reference< const bit_aligned_pixel_reference< byte_t
+ , Channel
+ , Layout
+ , Mutable
+ >
+ >
+ : public iterator_type_from_pixel< const bit_aligned_pixel_reference< uint8_t
+ , Channel
+ , Layout
+ , Mutable
+ >
+ ,false
+ ,false
+ ,true
+ > {};
+
+struct tiff_write_is_supported
+{
+ template< typename View >
+ struct apply
+ : public is_write_supported< typename get_pixel_type< View >::type
+ , tiff_tag
+ >
+ {};
+};
+
+} // namespace detail
+
+///
+/// TIFF Writer
+///
+template < typename Device, typename Log >
+class writer< Device
+ , tiff_tag
+ , Log
+ >
+ : public writer_backend< Device
+ , tiff_tag
+ >
+{
+private:
+ typedef writer_backend< Device, tiff_tag > backend_t;
+public:
+
+ writer( const Device& io_dev
+ , const image_write_info< tiff_tag >& info
+ )
+ : backend_t( io_dev
+ , info
+ )
+ {}
+
+ template<typename View>
+ void apply( const View& view )
+ {
+ write_view( view );
+ }
+
+private:
+
+ template< typename View >
+ void write_view( const View& view )
+ {
+ typedef typename View::value_type pixel_t;
+ // get the type of the first channel (heterogeneous pixels might be broken for now!)
+ typedef typename channel_traits< typename element_type< pixel_t >::type >::value_type channel_t;
+ tiff_bits_per_sample::type bits_per_sample = detail::unsigned_integral_num_bits< channel_t >::value;
+
+ tiff_samples_per_pixel::type samples_per_pixel = num_channels< pixel_t >::value;
+
+ this->write_header( view );
+
+ if( this->_info._is_tiled == false )
+ {
+ write_data( view
+ , (view.width() * samples_per_pixel * bits_per_sample + 7) / 8
+ , typename is_bit_aligned< pixel_t >::type()
+ );
+ }
+ else
+ {
+ tiff_tile_width::type tw = this->_info._tile_width;
+ tiff_tile_length::type th = this->_info._tile_length;
+
+ if(!this->_io_dev.check_tile_size( tw, th ))
+ {
+ io_error( "Tile sizes need to be multiples of 16." );
+ }
+
+ // tile related tags
+ this->_io_dev.template set_property<tiff_tile_width> ( tw );
+ this->_io_dev.template set_property<tiff_tile_length>( th );
+
+ write_tiled_data( view
+ , tw
+ , th
+ , typename is_bit_aligned< pixel_t >::type()
+ );
+ }
+ }
+
+ //////////////////////////////
+
+ template<typename View>
+ void write_bit_aligned_view_to_dev( const View& view
+ , const std::size_t row_size_in_bytes
+ , const mpl::true_& // has_alpha
+ )
+ {
+ byte_vector_t row( row_size_in_bytes );
+
+ typedef typename View::x_iterator x_it_t;
+ x_it_t row_it = x_it_t( &(*row.begin()));
+
+ auto pm_view = premultiply_view <typename View:: value_type> (view);
+
+ for( typename View::y_coord_t y = 0; y < pm_view.height(); ++y )
+ {
+ std::copy( pm_view.row_begin( y )
+ , pm_view.row_end( y )
+ , row_it
+ );
+
+
+ this->_io_dev.write_scaline( row
+ , (uint32) y
+ , 0
+ );
+
+ // @todo: do optional bit swapping here if you need to...
+ }
+ }
+
+ template<typename View>
+ void write_bit_aligned_view_to_dev( const View& view
+ , const std::size_t row_size_in_bytes
+ , const mpl::false_& // has_alpha
+ )
+ {
+ byte_vector_t row( row_size_in_bytes );
+
+ typedef typename View::x_iterator x_it_t;
+ x_it_t row_it = x_it_t( &(*row.begin()));
+
+ for( typename View::y_coord_t y = 0; y < view.height(); ++y )
+ {
+ std::copy( view.row_begin( y )
+ , view.row_end( y )
+ , row_it
+ );
+
+
+ this->_io_dev.write_scaline( row
+ , (uint32) y
+ , 0
+ );
+
+ // @todo: do optional bit swapping here if you need to...
+ }
+ }
+
+ /////////////////////////////
+
+ template< typename View >
+ void write_data( const View& view
+ , std::size_t row_size_in_bytes
+ , const mpl::true_& // bit_aligned
+ )
+ {
+ typedef typename color_space_type<typename View::value_type>::type colour_space_t;
+ typedef mpl::bool_<mpl::contains<colour_space_t, alpha_t>::value> has_alpha_t;
+
+ write_bit_aligned_view_to_dev(view, row_size_in_bytes, has_alpha_t());
+
+ }
+
+ template< typename View>
+ void write_tiled_data( const View& view
+ , tiff_tile_width::type tw
+ , tiff_tile_length::type th
+ , const mpl::true_& // bit_aligned
+ )
+ {
+ byte_vector_t row( this->_io_dev.get_tile_size() );
+
+ typedef typename View::x_iterator x_it_t;
+ x_it_t row_it = x_it_t( &(*row.begin()));
+
+ internal_write_tiled_data(view, tw, th, row, row_it);
+ }
+
+ template< typename View >
+ void write_data( const View& view
+ , std::size_t
+ , const mpl::false_& // bit_aligned
+ )
+ {
+ std::vector< pixel< typename channel_type< View >::type
+ , layout<typename color_space_type< View >::type >
+ >
+ > row( view.size() );
+
+ byte_t* row_addr = reinterpret_cast< byte_t* >( &row.front() );
+
+ // @todo: is there an overhead to doing this when there's no
+ // alpha to premultiply by? I'd hope it's optimised out.
+ auto pm_view = premultiply_view <typename View:: value_type> (view);
+
+ for( typename View::y_coord_t y = 0; y < pm_view.height(); ++y )
+ {
+ std::copy( pm_view.row_begin( y )
+ , pm_view.row_end( y )
+ , row.begin()
+ );
+
+ this->_io_dev.write_scaline( row_addr
+ , (uint32) y
+ , 0
+ );
+
+ // @todo: do optional bit swapping here if you need to...
+ }
+ }
+
+ template< typename View >
+ void write_tiled_data( const View& view
+ , tiff_tile_width::type tw
+ , tiff_tile_length::type th
+ , const mpl::false_& // bit_aligned
+ )
+ {
+ byte_vector_t row( this->_io_dev.get_tile_size() );
+
+ typedef typename detail::my_interleaved_pixel_iterator_type_from_pixel_reference< typename View::reference
+ >::type x_iterator;
+ x_iterator row_it = x_iterator( &(*row.begin()));
+
+ internal_write_tiled_data(view, tw, th, row, row_it);
+ }
+
+
+ //////////////////////////////
+
+ template< typename View
+ , typename IteratorType
+ >
+ void write_tiled_view_to_dev( const View& view
+ , IteratorType it
+ , const mpl::true_& // has_alpha
+ )
+ {
+ auto pm_view = premultiply_view <typename View:: value_type>( view );
+
+ std::copy( pm_view.begin()
+ , pm_view.end()
+ , it
+ );
+ }
+
+
+ template< typename View
+ , typename IteratorType
+ >
+ void write_tiled_view_to_dev( const View& view
+ , IteratorType it
+ , const mpl::false_& // has_alpha
+ )
+ {
+ std::copy( view.begin()
+ , view.end()
+ , it
+ );
+ }
+
+ /////////////////////////////
+
+
+
+ template< typename View,
+ typename IteratorType
+ >
+ void internal_write_tiled_data( const View& view
+ , tiff_tile_width::type tw
+ , tiff_tile_length::type th
+ , byte_vector_t& row
+ , IteratorType it
+ )
+ {
+ std::ptrdiff_t i = 0, j = 0;
+ View tile_subimage_view;
+ while( i < view.height() )
+ {
+ while( j < view.width() )
+ {
+ if( j + tw < view.width() && i + th < view.height() )
+ {
+ // a tile is fully included in the image: just copy values
+ tile_subimage_view = subimage_view( view
+ , static_cast< int >( j )
+ , static_cast< int >( i )
+ , static_cast< int >( tw )
+ , static_cast< int >( th )
+ );
+
+ typedef typename color_space_type<typename View::value_type>::type colour_space_t;
+ typedef mpl::bool_<mpl::contains<colour_space_t, alpha_t>::value> has_alpha_t;
+
+ write_tiled_view_to_dev(tile_subimage_view, it, has_alpha_t());
+ }
+ else
+ {
+ std::ptrdiff_t width = view.width();
+ std::ptrdiff_t height = view.height();
+
+ std::ptrdiff_t current_tile_width = ( j + tw < width ) ? tw : width - j;
+ std::ptrdiff_t current_tile_length = ( i + th < height) ? th : height - i;
+
+ tile_subimage_view = subimage_view( view
+ , static_cast< int >( j )
+ , static_cast< int >( i )
+ , static_cast< int >( current_tile_width )
+ , static_cast< int >( current_tile_length )
+ );
+
+ for( typename View::y_coord_t y = 0; y < tile_subimage_view.height(); ++y )
+ {
+ std::copy( tile_subimage_view.row_begin( y )
+ , tile_subimage_view.row_end( y )
+ , it
+ );
+ std::advance(it, tw);
+ }
+
+ it = IteratorType( &(*row.begin()));
+ }
+
+ this->_io_dev.write_tile( row
+ , static_cast< uint32 >( j )
+ , static_cast< uint32 >( i )
+ , 0
+ , 0
+ );
+ j += tw;
+ }
+ j = 0;
+ i += th;
+ }
+ // @todo: do optional bit swapping here if you need to...
+ }
+};
+
+///
+/// TIFF Dynamic Image Writer
+///
+template< typename Device >
+class dynamic_image_writer< Device
+ , tiff_tag
+ >
+ : public writer< Device
+ , tiff_tag
+ >
+{
+ typedef writer< Device
+ , tiff_tag
+ > parent_t;
+
+public:
+
+ dynamic_image_writer( const Device& io_dev
+ , const image_write_info< tiff_tag >& info
+ )
+ : parent_t( io_dev
+ , info
+ )
+ {}
+
+ template< typename Views >
+ void apply( const any_image_view< Views >& views )
+ {
+ detail::dynamic_io_fnobj< detail::tiff_write_is_supported
+ , parent_t
+ > op( this );
+
+ apply_operation( views, op );
+ }
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/detail/writer_backend.hpp b/boost/gil/extension/io/tiff/detail/writer_backend.hpp
new file mode 100644
index 0000000000..c7ed63a3e5
--- /dev/null
+++ b/boost/gil/extension/io/tiff/detail/writer_backend.hpp
@@ -0,0 +1,145 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_WRITER_BACKEND_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_WRITER_BACKEND_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/contains.hpp>
+
+#include <boost/gil/extension/io/tiff/tags.hpp>
+
+namespace boost { namespace gil {
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(push)
+#pragma warning(disable:4512) //assignment operator could not be generated
+#endif
+
+///
+/// TIFF Writer Backend
+///
+template< typename Device >
+struct writer_backend< Device
+ , tiff_tag
+ >
+{
+public:
+
+ typedef tiff_tag format_tag_t;
+
+public:
+
+ writer_backend( const Device& io_dev
+ , const image_write_info< tiff_tag >& info
+ )
+ : _io_dev( io_dev )
+ , _info( info )
+ {}
+
+protected:
+
+ template< typename View >
+ void write_header( const View& view )
+ {
+ typedef typename View::value_type pixel_t;
+
+ // get the type of the first channel (heterogeneous pixels might be broken for now!)
+ typedef typename channel_traits< typename element_type< pixel_t >::type >::value_type channel_t;
+ typedef typename color_space_type< View >::type color_space_t;
+
+ if(! this->_info._photometric_interpretation_user_defined )
+ {
+ // write photometric interpretion - Warning: This value is rather
+ // subjective. The user should better set this value itself. There
+ // is no way to decide if a image is PHOTOMETRIC_MINISWHITE or
+ // PHOTOMETRIC_MINISBLACK. If the user has not manually set it, then
+ // this writer will assume PHOTOMETRIC_MINISBLACK for gray_t images,
+ // PHOTOMETRIC_RGB for rgb_t images, and PHOTOMETRIC_SEPARATED (as
+ // is conventional) for cmyk_t images.
+ this->_info._photometric_interpretation = detail::photometric_interpretation< color_space_t >::value;
+ }
+
+ // write dimensions
+ tiff_image_width::type width = (tiff_image_width::type) view.width();
+ tiff_image_height::type height = (tiff_image_height::type) view.height();
+
+ this->_io_dev.template set_property< tiff_image_width >( width );
+ this->_io_dev.template set_property< tiff_image_height >( height );
+
+ // write planar configuration
+ this->_io_dev.template set_property<tiff_planar_configuration>( this->_info._planar_configuration );
+
+ // write samples per pixel
+ tiff_samples_per_pixel::type samples_per_pixel = num_channels< pixel_t >::value;
+ this->_io_dev.template set_property<tiff_samples_per_pixel>( samples_per_pixel );
+
+ if (mpl:: contains <color_space_t, alpha_t>:: value) {
+ std:: vector <uint16_t> extra_samples {EXTRASAMPLE_ASSOCALPHA};
+ this->_io_dev.template set_property<tiff_extra_samples>( extra_samples );
+ }
+ // write bits per sample
+ // @todo: Settings this value usually requires to write for each sample the bit
+ // value seperately in case they are different, like rgb556.
+ tiff_bits_per_sample::type bits_per_sample = detail::unsigned_integral_num_bits< channel_t >::value;
+ this->_io_dev.template set_property<tiff_bits_per_sample>( bits_per_sample );
+
+ // write sample format
+ tiff_sample_format::type sampl_format = detail::sample_format< channel_t >::type::value;
+ this->_io_dev.template set_property<tiff_sample_format>( sampl_format );
+
+ // write photometric format
+ this->_io_dev.template set_property<tiff_photometric_interpretation>( this->_info._photometric_interpretation );
+
+ // write compression
+ this->_io_dev.template set_property<tiff_compression>( this->_info._compression );
+
+ // write orientation
+ this->_io_dev.template set_property<tiff_orientation>( this->_info._orientation );
+
+ // write rows per strip
+ this->_io_dev.template set_property<tiff_rows_per_strip>( this->_io_dev.get_default_strip_size() );
+
+ // write x, y resolution and units
+ this->_io_dev.template set_property<tiff_resolution_unit>( this->_info._resolution_unit );
+ this->_io_dev.template set_property<tiff_x_resolution>( this->_info._x_resolution );
+ this->_io_dev.template set_property<tiff_y_resolution>( this->_info._y_resolution );
+
+ /// Optional and / or non-baseline tags below here
+
+ // write ICC colour profile, if it's there
+ // http://www.color.org/icc_specs2.xalter
+ if ( 0 != this->_info._icc_profile.size())
+ this->_io_dev.template set_property<tiff_icc_profile>( this->_info._icc_profile );
+ }
+
+
+public:
+
+ Device _io_dev;
+
+ image_write_info< tiff_tag > _info;
+};
+
+#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
+#pragma warning(pop)
+#endif
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/old.hpp b/boost/gil/extension/io/tiff/old.hpp
new file mode 100644
index 0000000000..d0fa548a37
--- /dev/null
+++ b/boost/gil/extension/io/tiff/old.hpp
@@ -0,0 +1,180 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_OLD_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_OLD_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/tiff.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup TIFF_IO
+/// \brief Returns the width and height of the TIFF file at the specified location.
+/// Throws std::ios_base::failure if the location does not correspond to a valid TIFF file
+template< typename String >
+inline
+point2< std::ptrdiff_t > tiff_read_dimensions( const String& filename )
+{
+ typedef typename get_reader_backend< String
+ , tiff_tag
+ >::type backend_t;
+
+ backend_t backend = read_image_info( filename
+ , tiff_tag()
+ );
+
+ return point2< std::ptrdiff_t >( backend._info._width
+ , backend._info._height
+ );
+}
+
+/// \ingroup TIFF_IO
+/// \brief Loads the image specified by the given tiff image file name into the given view.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its color space or channel depth are not
+/// compatible with the ones specified by View, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void tiff_read_view( const String& filename
+ , const View& view
+ )
+{
+ read_view( filename
+ , view
+ , tiff_tag()
+ );
+}
+
+/// \ingroup TIFF_IO
+/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, and loads the pixels into it.
+/// Triggers a compile assert if the image color space or channel depth are not supported by the TIFF library or by the I/O extension.
+/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its color space or channel depth are not
+/// compatible with the ones specified by Image
+template< typename String
+ , typename Image
+ >
+inline
+void tiff_read_image( const String& filename
+ , Image& img
+ )
+{
+ read_image( filename
+ , img
+ , tiff_tag()
+ );
+}
+
+/// \ingroup TIFF_IO
+/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ , typename CC
+ >
+inline
+void tiff_read_and_convert_view( const String& filename
+ , const View& view
+ , CC cc
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , cc
+ , tiff_tag()
+ );
+}
+
+/// \ingroup TIFF_IO
+/// \brief Loads and color-converts the image specified by the given tiff image file name into the given view.
+/// Throws std::ios_base::failure if the file is not a valid TIFF file, or if its dimensions don't match the ones of the view.
+template< typename String
+ , typename View
+ >
+inline
+void tiff_read_and_convert_view( const String& filename
+ , const View& view
+ )
+{
+ read_and_convert_view( filename
+ , view
+ , tiff_tag()
+ );
+}
+
+/// \ingroup TIFF_IO
+/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid TIFF file
+template< typename String
+ , typename Image
+ , typename CC
+ >
+inline
+void tiff_read_and_convert_image( const String& filename
+ , Image& img
+ , CC cc
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , cc
+ , tiff_tag()
+ );
+}
+
+/// \ingroup TIFF_IO
+/// \brief Allocates a new image whose dimensions are determined by the given tiff image file, loads and color-converts the pixels into it.
+/// Throws std::ios_base::failure if the file is not a valid TIFF file
+template< typename String
+ , typename Image
+ >
+inline
+void tiff_read_and_convert_image( const String filename
+ , Image& img
+ )
+{
+ read_and_convert_image( filename
+ , img
+ , tiff_tag()
+ );
+}
+
+
+/// \ingroup TIFF_IO
+/// \brief Saves the view to a tiff file specified by the given tiff image file name.
+/// Triggers a compile assert if the view color space and channel depth are not supported by the TIFF library or by the I/O extension.
+/// Throws std::ios_base::failure if it fails to create the file.
+template< typename String
+ , typename View
+ >
+inline
+void tiff_write_view( const String& filename
+ , const View& view
+ )
+{
+ write_view( filename
+ , view
+ , tiff_tag()
+ );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/read.hpp b/boost/gil/extension/io/tiff/read.hpp
new file mode 100644
index 0000000000..285a8bf331
--- /dev/null
+++ b/boost/gil/extension/io/tiff/read.hpp
@@ -0,0 +1,43 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_READ_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_READ_HPP
+
+#define BOOST_GIL_EXTENSION_IO_TIFF_READ_ENABLED
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/tiff/tags.hpp>
+#include <boost/gil/extension/io/tiff/detail/supported_types.hpp>
+#include <boost/gil/extension/io/tiff/detail/read.hpp>
+#include <boost/gil/extension/io/tiff/detail/scanline_read.hpp>
+
+#include <boost/gil/io/get_reader.hpp>
+#include <boost/gil/io/make_backend.hpp>
+#include <boost/gil/io/make_reader.hpp>
+#include <boost/gil/io/make_dynamic_image_reader.hpp>
+#include <boost/gil/io/make_scanline_reader.hpp>
+
+#include <boost/gil/io/read_view.hpp>
+#include <boost/gil/io/read_image.hpp>
+#include <boost/gil/io/read_image_info.hpp>
+#include <boost/gil/io/read_and_convert_image.hpp>
+#include <boost/gil/io/read_and_convert_view.hpp>
+
+#include <boost/gil/io/scanline_read_iterator.hpp>
+
+#endif
diff --git a/boost/gil/extension/io/tiff/tags.hpp b/boost/gil/extension/io/tiff/tags.hpp
new file mode 100644
index 0000000000..2242e969ea
--- /dev/null
+++ b/boost/gil/extension/io/tiff/tags.hpp
@@ -0,0 +1,359 @@
+/*
+ Copyright 2007-2008 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_TAGS_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_TAGS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief All supported tiff tags by the gil io extension.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/vector.hpp>
+
+// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ extern "C" {
+#endif
+
+#include <tiff.h>
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_C_LIB_COMPILED_AS_CPLUSPLUS
+ }
+#endif
+
+#include <boost/gil/io/base.hpp>
+#include <boost/gil/extension/io/tiff/detail/log.hpp>
+
+namespace boost { namespace gil {
+
+/// Defines tiff tag.
+struct tiff_tag : format_tag {};
+
+/// http://www.awaresystems.be/imaging/tiff/tifftags/baseline.html
+/// http://www.remotesensing.org/libtiff/
+
+/// TIFF property base class
+template< typename T, int Value >
+struct tiff_property_base : property_base< T >
+{
+ /// Tag, needed when reading or writing image properties.
+ static const ttag_t tag = Value;
+ /// The list of argument types used in the interface of LibTIFF
+ /// for
+ /// this property:
+ /// http://www.remotesensing.org/libtiff/man/TIFFGetField.3tiff.html
+ /// http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
+ typedef mpl:: vector <typename property_base <T>:: type> arg_types;
+};
+
+/// baseline tags
+
+/// Defines type for new subfile property.
+struct tiff_new_subfile_type : tiff_property_base< uint32_t, TIFFTAG_SUBFILETYPE > {};
+
+/// Defines type for subfile property.
+struct tiff_subfile_type : tiff_property_base< uint16_t, TIFFTAG_OSUBFILETYPE > {};
+
+/// Defines type for image width property.
+struct tiff_image_width : tiff_property_base< uint32_t, TIFFTAG_IMAGEWIDTH > {};
+
+/// Defines type for image height property.
+struct tiff_image_height : tiff_property_base< uint32_t, TIFFTAG_IMAGELENGTH > {};
+
+/// Defines type for bits per sample property.
+struct tiff_bits_per_sample : tiff_property_base< uint16_t, TIFFTAG_BITSPERSAMPLE > {};
+
+/// Defines type for compression property.
+struct tiff_compression : tiff_property_base< uint16_t, TIFFTAG_COMPRESSION > {};
+
+/// Defines type for photometric interpretation property.
+struct tiff_photometric_interpretation : tiff_property_base< uint16_t, TIFFTAG_PHOTOMETRIC > {};
+
+/// Defines type for threshold property.
+struct tiff_thresholding : tiff_property_base< uint16_t, TIFFTAG_THRESHHOLDING > {};
+
+/// Defines type for cell width property.
+struct tiff_cell_width : tiff_property_base< uint16_t, TIFFTAG_CELLWIDTH > {};
+
+/// Defines type for cell length property.
+struct tiff_cell_length : tiff_property_base< uint16_t, TIFFTAG_CELLLENGTH > {};
+
+/// Defines type for fill order property.
+struct tiff_fill_order : tiff_property_base< std::string, TIFFTAG_FILLORDER > {};
+
+/// Defines type for image description.
+struct tiff_image_description : tiff_property_base< std::string, TIFFTAG_IMAGEDESCRIPTION > {};
+
+/// Defines type for make property.
+struct tiff_make : tiff_property_base< std::string, TIFFTAG_MAKE > {};
+
+/// Defines type for model property.
+struct tiff_model : tiff_property_base< std::string, TIFFTAG_MODEL > {};
+
+/// Defines type for image orientation.
+struct tiff_orientation : tiff_property_base< uint16_t, TIFFTAG_ORIENTATION > {};
+
+/// Defines type for samples per pixel property.
+struct tiff_samples_per_pixel : tiff_property_base< uint16_t, TIFFTAG_SAMPLESPERPIXEL > {};
+
+/// Defines type for rows per strip property.
+struct tiff_rows_per_strip : tiff_property_base< uint32_t, TIFFTAG_ROWSPERSTRIP > {};
+
+/// Defines type for min sample property.
+struct tiff_min_sample_value : tiff_property_base< uint16_t, TIFFTAG_MINSAMPLEVALUE > {};
+
+/// Defines type for max sample property.
+struct tiff_max_sample_value : tiff_property_base< uint16_t, TIFFTAG_MAXSAMPLEVALUE > {};
+
+/// Defines type for x resolution property.
+struct tiff_x_resolution : tiff_property_base< float, TIFFTAG_XRESOLUTION > {};
+
+/// Defines type for y resolution property.
+struct tiff_y_resolution : tiff_property_base< float, TIFFTAG_YRESOLUTION > {};
+
+/// Defines type for resolution unit property.
+enum class tiff_resolution_unit_value: std:: uint16_t {
+ NONE = RESUNIT_NONE,
+ INCH = RESUNIT_INCH,
+ CENTIMETER = RESUNIT_CENTIMETER
+};
+
+struct tiff_resolution_unit : tiff_property_base< tiff_resolution_unit_value, TIFFTAG_RESOLUTIONUNIT > {};
+
+/// Defines type for planar configuration property.
+struct tiff_planar_configuration : tiff_property_base< uint16_t, TIFFTAG_PLANARCONFIG > {};
+
+/// Defines type for gray response unit property.
+struct tiff_gray_response_unit : tiff_property_base< uint16_t, TIFFTAG_GRAYRESPONSEUNIT > {};
+
+/// Defines type for gray response curve property.
+struct tiff_gray_response_curve : tiff_property_base< uint16_t*, TIFFTAG_GRAYRESPONSECURVE > {};
+
+/// Defines type for software vendor property.
+struct tiff_software : tiff_property_base< std::string, TIFFTAG_SOFTWARE > {};
+
+/// Defines type for date time property.
+struct tiff_date_time : tiff_property_base< std::string, TIFFTAG_DATETIME > {};
+
+/// Defines type for artist information property.
+struct tiff_artist : tiff_property_base< std::string, TIFFTAG_ARTIST > {};
+
+/// Defines type for host computer property.
+struct tiff_host_computer : tiff_property_base< std::string, TIFFTAG_HOSTCOMPUTER > {};
+
+/// Helper structure for reading a color mapper.
+struct tiff_color_map
+{
+ typedef uint16_t* red_t;
+ typedef uint16_t* green_t;
+ typedef uint16_t* blue_t;
+
+ static const unsigned int tag = TIFFTAG_COLORMAP;
+};
+
+/// Defines type for extra samples property.
+struct tiff_extra_samples : tiff_property_base< std:: vector <uint16_t>, TIFFTAG_EXTRASAMPLES > {
+ typedef mpl:: vector <uint16_t, uint16_t const *> arg_types;
+};
+
+/// Defines type for copyright property.
+struct tiff_copyright : tiff_property_base< std::string, TIFFTAG_COPYRIGHT > {};
+
+/// non-baseline tags
+
+/// Defines type for sample format property.
+struct tiff_sample_format : tiff_property_base< uint16_t, TIFFTAG_SAMPLEFORMAT > {};
+
+/// Defines type for indexed property.
+/// Not supported yet
+//struct tiff_indexed : tiff_property_base< bool, TIFFTAG_INDEXED > {};
+
+/// Tile related tags
+
+/// Defines type for a (not) tiled tiff image
+struct tiff_is_tiled : tiff_property_base< bool, false > {};
+
+/// Defines type for tile width
+struct tiff_tile_width : tiff_property_base< long, TIFFTAG_TILEWIDTH > {};
+
+/// Defines type for tile length
+struct tiff_tile_length : tiff_property_base< long, TIFFTAG_TILELENGTH > {};
+
+/// Defines the page to read in a multipage tiff file.
+#include <boost/mpl/integral_c.hpp>
+struct tiff_directory : property_base< tdir_t >
+{
+ typedef boost::mpl::integral_c< type, 0 > default_value;
+};
+
+/// Non-baseline tags
+
+/// Defines type for icc profile property.
+struct tiff_icc_profile : tiff_property_base< std:: vector <uint8_t>, TIFFTAG_ICCPROFILE > {
+ typedef mpl:: vector <uint32_t, void const *> arg_types;
+};
+
+/// Read information for tiff images.
+///
+/// The structure is returned when using read_image_info.
+template<>
+struct image_read_info< tiff_tag >
+{
+ image_read_info()
+ : _width( 0 )
+ , _height( 0 )
+
+ , _compression( COMPRESSION_NONE )
+
+ , _bits_per_sample( 0 )
+ , _samples_per_pixel( 0 )
+ , _sample_format( SAMPLEFORMAT_UINT )
+
+ , _planar_configuration( PLANARCONFIG_CONTIG )
+
+ , _photometric_interpretation( PHOTOMETRIC_MINISWHITE )
+
+ , _is_tiled( false )
+
+ , _tile_width ( 0 )
+ , _tile_length( 0 )
+
+ , _x_resolution( 1 )
+ , _y_resolution( 1 )
+ , _resolution_unit( tiff_resolution_unit_value:: NONE )
+
+ , _icc_profile( )
+ {}
+
+ /// The number of rows of pixels in the image.
+ tiff_image_width::type _width;
+ /// The number of columns in the image, i.e., the number of pixels per row.
+ tiff_image_height::type _height;
+
+ /// Compression scheme used on the image data.
+ tiff_compression::type _compression;
+
+ /// Number of bits per component.
+ tiff_bits_per_sample::type _bits_per_sample;
+ /// The number of components per pixel.
+ tiff_samples_per_pixel::type _samples_per_pixel;
+ /// Specifies how to interpret each data sample in a pixel.
+ tiff_sample_format::type _sample_format;
+
+ /// How the components of each pixel are stored.
+ tiff_planar_configuration::type _planar_configuration;
+
+ /// The color space of the image data.
+ tiff_photometric_interpretation::type _photometric_interpretation;
+
+ /// Is tiled?
+ tiff_is_tiled::type _is_tiled;
+ /// Tile width
+ tiff_tile_width::type _tile_width;
+ /// Tile length
+ tiff_tile_length::type _tile_length;
+
+ tiff_x_resolution::type _x_resolution;
+ tiff_y_resolution::type _y_resolution;
+ tiff_resolution_unit::type _resolution_unit;
+
+ tiff_icc_profile:: type _icc_profile;
+};
+
+/// Read settings for tiff images.
+///
+/// The structure can be used for all read_xxx functions, except read_image_info.
+template<>
+struct image_read_settings< tiff_tag > : public image_read_settings_base
+{
+ /// Default constructor
+ image_read_settings< tiff_tag >()
+ : image_read_settings_base()
+ , _directory( tiff_directory::default_value::value )
+ {}
+
+ /// Constructor
+ /// \param top_left Top left coordinate for reading partial image.
+ /// \param dim Dimensions for reading partial image.
+ /// \param directory Defines the page to read in a multipage tiff file.
+ image_read_settings( const point_t& top_left
+ , const point_t& dim
+ , const tiff_directory::type& directory = tiff_directory::default_value::value
+ )
+ : image_read_settings_base( top_left
+ , dim
+ )
+ , _directory( directory )
+ {}
+
+ /// Defines the page to read in a multipage tiff file.
+ tiff_directory::type _directory;
+};
+
+/// Write settings for tiff images.
+///
+/// The structure can be used for all write_xxx functions, except write_image_info.
+template< typename Log >
+struct image_write_info< tiff_tag, Log >
+{
+ /// Default constructor
+ image_write_info()
+ : _photometric_interpretation ( PHOTOMETRIC_MINISBLACK )
+ , _photometric_interpretation_user_defined( false )
+
+ , _compression ( COMPRESSION_NONE )
+ , _orientation ( ORIENTATION_TOPLEFT )
+ , _planar_configuration ( PLANARCONFIG_CONTIG )
+ , _is_tiled ( false )
+ , _tile_width ( 0 )
+ , _tile_length ( 0 )
+ , _x_resolution ( 1 )
+ , _y_resolution ( 1 )
+ , _resolution_unit ( tiff_resolution_unit_value::NONE )
+ , _icc_profile ( )
+ {}
+
+ /// The color space of the image data.
+ tiff_photometric_interpretation::type _photometric_interpretation;
+ bool _photometric_interpretation_user_defined;
+
+ /// Compression scheme used on the image data.
+ tiff_compression::type _compression;
+ /// The orientation of the image with respect to the rows and columns.
+ tiff_orientation::type _orientation;
+ /// How the components of each pixel are stored.
+ tiff_planar_configuration::type _planar_configuration;
+
+ /// Is the image tiled?
+ tiff_is_tiled::type _is_tiled;
+ /// Tiles width
+ tiff_tile_width::type _tile_width;
+ /// Tiles length
+ tiff_tile_length::type _tile_length;
+
+ /// x, y resolution
+ tiff_x_resolution::type _x_resolution;
+ tiff_y_resolution::type _y_resolution;
+ tiff_resolution_unit::type _resolution_unit;
+
+ tiff_icc_profile:: type _icc_profile;
+
+ /// A log to transcript error and warning messages issued by libtiff.
+ Log _log;
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/tiff/write.hpp b/boost/gil/extension/io/tiff/write.hpp
new file mode 100644
index 0000000000..1969a951fe
--- /dev/null
+++ b/boost/gil/extension/io/tiff/write.hpp
@@ -0,0 +1,32 @@
+/*
+ Copyright 2007-2008 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_IO_TIFF_WRITE_HPP
+#define BOOST_GIL_EXTENSION_IO_TIFF_WRITE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning \n
+///
+/// \date 2007-2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/io/tiff/tags.hpp>
+#include <boost/gil/extension/io/tiff/detail/supported_types.hpp>
+#include <boost/gil/extension/io/tiff/detail/write.hpp>
+
+#include <boost/gil/io/make_writer.hpp>
+#include <boost/gil/io/make_dynamic_image_writer.hpp>
+
+#include <boost/gil/io/write_view.hpp>
+
+
+#endif
diff --git a/boost/gil/extension/io/tiff_dynamic_io.hpp b/boost/gil/extension/io/tiff_dynamic_io.hpp
deleted file mode 100644
index bb3c8c3ca7..0000000000
--- a/boost/gil/extension/io/tiff_dynamic_io.hpp
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/io/tiff_io.hpp b/boost/gil/extension/io/tiff_io.hpp
deleted file mode 100644
index 4198a3f984..0000000000
--- a/boost/gil/extension/io/tiff_io.hpp
+++ /dev/null
@@ -1,511 +0,0 @@
-/*
- 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
diff --git a/boost/gil/extension/numeric/affine.hpp b/boost/gil/extension/numeric/affine.hpp
new file mode 100644
index 0000000000..6a77070063
--- /dev/null
+++ b/boost/gil/extension/numeric/affine.hpp
@@ -0,0 +1,93 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP
+
+#include <boost/gil/utilities.hpp> // point2
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief support for affine transformations
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil {
+
+////////////////////////////////////////////////////////////////////////////////////////
+///
+/// Simple matrix to do 2D affine transformations. It is actually 3x3 but the last column is [0 0 1]
+///
+////////////////////////////////////////////////////////////////////////////////////////
+template <typename T>
+class matrix3x2 {
+public:
+ matrix3x2() : a(1), b(0), c(0), d(1), e(0), f(0) {}
+ matrix3x2(T A, T B, T C, T D, T E, T F) : a(A),b(B),c(C),d(D),e(E),f(F) {}
+ matrix3x2(const matrix3x2& mat) : a(mat.a), b(mat.b), c(mat.c), d(mat.d), e(mat.e), f(mat.f) {}
+ matrix3x2& operator=(const matrix3x2& m) { a=m.a; b=m.b; c=m.c; d=m.d; e=m.e; f=m.f; return *this; }
+
+ matrix3x2& operator*=(const matrix3x2& m) { (*this) = (*this)*m; return *this; }
+
+ static matrix3x2 get_rotate(T rads) { T c=std::cos(rads); T s=std::sin(rads); return matrix3x2(c,s,-s,c,0,0); }
+ static matrix3x2 get_translate(const point2<T>& t) { return matrix3x2(1 ,0,0,1 ,t.x,t.y); }
+ static matrix3x2 get_translate(T x, T y) { return matrix3x2(1 ,0,0,1 ,x, y ); }
+ static matrix3x2 get_scale (const point2<T>& s) { return matrix3x2(s.x,0,0,s.y,0 ,0 ); }
+ static matrix3x2 get_scale (T x, T y) { return matrix3x2(x, 0,0,y, 0 ,0 ); }
+ static matrix3x2 get_scale (T s) { return matrix3x2(s ,0,0,s ,0 ,0 ); }
+
+ T a,b,c,d,e,f;
+};
+
+template <typename T> BOOST_FORCEINLINE
+matrix3x2<T> operator*(const matrix3x2<T>& m1, const matrix3x2<T>& m2) {
+ return matrix3x2<T>(
+ m1.a * m2.a + m1.b * m2.c,
+ m1.a * m2.b + m1.b * m2.d,
+ m1.c * m2.a + m1.d * m2.c,
+ m1.c * m2.b + m1.d * m2.d,
+ m1.e * m2.a + m1.f * m2.c + m2.e,
+ m1.e * m2.b + m1.f * m2.d + m2.f );
+}
+
+template <typename T, typename F> BOOST_FORCEINLINE
+point2<F> operator*(const point2<T>& p, const matrix3x2<F>& m) {
+ return point2<F>(m.a*p.x + m.c*p.y + m.e, m.b*p.x + m.d*p.y + m.f);
+}
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// Define affine mapping that transforms the source coordinates by the affine transformation
+////////////////////////////////////////////////////////////////////////////////////////
+/*
+template <typename MapFn>
+concept MappingFunctionConcept {
+ typename mapping_traits<MapFn>::result_type; where PointNDConcept<result_type>;
+
+ template <typename Domain> { where PointNDConcept<Domain> }
+ result_type transform(MapFn&, const Domain& src);
+};
+*/
+
+template <typename T> struct mapping_traits;
+
+template <typename F>
+struct mapping_traits<matrix3x2<F> > {
+ typedef point2<F> result_type;
+};
+
+template <typename F, typename F2> BOOST_FORCEINLINE
+point2<F> transform(const matrix3x2<F>& mat, const point2<F2>& src) { return src * mat; }
+
+} } // namespace boost::gil
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_AFFINE_HPP
diff --git a/boost/gil/extension/numeric/algorithm.hpp b/boost/gil/extension/numeric/algorithm.hpp
new file mode 100644
index 0000000000..b7c175985f
--- /dev/null
+++ b/boost/gil/extension/numeric/algorithm.hpp
@@ -0,0 +1,158 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
+
+/*!
+/// \file
+/// \brief Numeric algorithms
+/// \author Hailin Jin and Lubomir Bourdev \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+*/
+
+#include <cassert>
+#include <iterator>
+#include <algorithm>
+#include <numeric>
+
+#include <boost/gil/gil_config.hpp>
+#include <boost/gil/pixel_iterator.hpp>
+#include <boost/gil/metafunctions.hpp>
+
+namespace boost { namespace gil {
+
+/// \brief Returns the reference proxy associated with a type that has a \p "reference" member typedef.
+///
+/// The reference proxy is the reference type, but with stripped-out C++ reference. It models PixelConcept
+template <typename T>
+struct pixel_proxy : public remove_reference<typename T::reference> {};
+
+/// \brief std::for_each for a pair of iterators
+template <typename Iterator1,typename Iterator2,typename BinaryFunction>
+BinaryFunction for_each(Iterator1 first1,Iterator1 last1,Iterator2 first2,BinaryFunction f) {
+ while(first1!=last1)
+ f(*first1++,*first2++);
+ return f;
+}
+
+template <typename SrcIterator,typename DstIterator>
+inline DstIterator assign_pixels(SrcIterator src,SrcIterator src_end,DstIterator dst) {
+ for_each(src,src_end,dst,pixel_assigns_t<typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type,
+ typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type>());
+ return dst+(src_end-src);
+}
+
+namespace detail {
+template <std::size_t Size>
+struct inner_product_k_t {
+ template <class _InputIterator1, class _InputIterator2, class _Tp,
+ class _BinaryOperation1, class _BinaryOperation2>
+ static _Tp apply(_InputIterator1 __first1,
+ _InputIterator2 __first2, _Tp __init,
+ _BinaryOperation1 __binary_op1,
+ _BinaryOperation2 __binary_op2) {
+ __init = __binary_op1(__init, __binary_op2(*__first1, *__first2));
+ return inner_product_k_t<Size-1>::template apply(__first1+1,__first2+1,__init,
+ __binary_op1, __binary_op2);
+ }
+};
+
+template <>
+struct inner_product_k_t<0> {
+ template <class _InputIterator1, class _InputIterator2, class _Tp,
+ class _BinaryOperation1, class _BinaryOperation2>
+ static _Tp apply(_InputIterator1 __first1,
+ _InputIterator2 __first2, _Tp __init,
+ _BinaryOperation1 __binary_op1,
+ _BinaryOperation2 __binary_op2) {
+ return __init;
+ }
+};
+} // namespace detail
+
+/// static version of std::inner_product
+template <std::size_t Size,
+ class _InputIterator1, class _InputIterator2, class _Tp,
+ class _BinaryOperation1, class _BinaryOperation2>
+BOOST_FORCEINLINE
+_Tp inner_product_k(_InputIterator1 __first1,
+ _InputIterator2 __first2,
+ _Tp __init,
+ _BinaryOperation1 __binary_op1,
+ _BinaryOperation2 __binary_op2) {
+ return detail::inner_product_k_t<Size>::template apply(__first1,__first2,__init,
+ __binary_op1, __binary_op2);
+}
+
+/// \brief 1D un-guarded correlation with a variable-size kernel
+template <typename PixelAccum,typename SrcIterator,typename KernelIterator,typename Integer,typename DstIterator>
+inline DstIterator correlate_pixels_n(SrcIterator src_begin,SrcIterator src_end,
+ KernelIterator ker_begin,Integer ker_size,
+ DstIterator dst_begin) {
+ typedef typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type PIXEL_SRC_REF;
+ typedef typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type PIXEL_DST_REF;
+ typedef typename std::iterator_traits<KernelIterator>::value_type kernel_type;
+ PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
+ while(src_begin!=src_end) {
+ pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
+ std::inner_product(src_begin,src_begin+ker_size,ker_begin,acc_zero,
+ pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
+ pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
+ *dst_begin);
+ ++src_begin; ++dst_begin;
+ }
+ return dst_begin;
+}
+
+/// \brief 1D un-guarded correlation with a fixed-size kernel
+template <std::size_t Size,typename PixelAccum,typename SrcIterator,typename KernelIterator,typename DstIterator>
+inline DstIterator correlate_pixels_k(SrcIterator src_begin,SrcIterator src_end,
+ KernelIterator ker_begin,
+ DstIterator dst_begin) {
+ typedef typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type PIXEL_SRC_REF;
+ typedef typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type PIXEL_DST_REF;
+ typedef typename std::iterator_traits<KernelIterator>::value_type kernel_type;
+ PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
+ while(src_begin!=src_end) {
+ pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
+ inner_product_k<Size>(src_begin,ker_begin,acc_zero,
+ pixel_plus_t<PixelAccum,PixelAccum,PixelAccum>(),
+ pixel_multiplies_scalar_t<PIXEL_SRC_REF,kernel_type,PixelAccum>()),
+ *dst_begin);
+ ++src_begin; ++dst_begin;
+ }
+ return dst_begin;
+}
+
+/// \brief destination is set to be product of the source and a scalar
+template <typename PixelAccum,typename SrcView,typename Scalar,typename DstView>
+inline void view_multiplies_scalar(const SrcView& src,const Scalar& scalar,const DstView& dst) {
+ assert(src.dimensions()==dst.dimensions());
+ typedef typename pixel_proxy<typename SrcView::value_type>::type PIXEL_SRC_REF;
+ typedef typename pixel_proxy<typename DstView::value_type>::type PIXEL_DST_REF;
+ int height=src.height();
+ for(int rr=0;rr<height;++rr) {
+ typename SrcView::x_iterator it_src=src.row_begin(rr);
+ typename DstView::x_iterator it_dst=dst.row_begin(rr);
+ typename SrcView::x_iterator it_src_end=src.row_end(rr);
+ while(it_src!=it_src_end) {
+ pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(
+ pixel_multiplies_scalar_t<PIXEL_SRC_REF,Scalar,PixelAccum>()(*it_src,scalar),
+ *it_dst);
+ ++it_src; ++it_dst;
+ }
+ }
+}
+
+} } // namespace boost::gil
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
diff --git a/boost/gil/extension/numeric/channel_numeric_operations.hpp b/boost/gil/extension/numeric/channel_numeric_operations.hpp
new file mode 100644
index 0000000000..d2407f9814
--- /dev/null
+++ b/boost/gil/extension/numeric/channel_numeric_operations.hpp
@@ -0,0 +1,159 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
+
+/*!
+/// \file
+/// \brief Structures for channel-wise numeric operations
+/// \author Hailin Jin and Lubomir Bourdev \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+/// Currently defined structures:
+/// channel_plus_t (+), channel_minus_t (-),
+/// channel_multiplies_t (*), channel_divides_t (/),
+/// channel_plus_scalar_t (+s), channel_minus_scalar_t (-s),
+/// channel_multiplies_scalar_t (*s), channel_divides_scalar_t (/s),
+/// channel_halves_t (/=2), channel_zeros_t (=0), channel_assigns_t (=)
+*/
+
+#include <functional>
+
+#include <boost/gil/gil_config.hpp>
+#include <boost/gil/channel.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup ChannelNumericOperations
+/// structure for adding one channel to another
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel1,typename Channel2,typename ChannelR>
+struct channel_plus_t : public std::binary_function<Channel1,Channel2,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
+ typename channel_traits<Channel2>::const_reference ch2) const {
+ return ChannelR(ch1)+ChannelR(ch2);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for subtracting one channel from another
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel1,typename Channel2,typename ChannelR>
+struct channel_minus_t : public std::binary_function<Channel1,Channel2,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
+ typename channel_traits<Channel2>::const_reference ch2) const {
+ return ChannelR(ch1)-ChannelR(ch2);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for multiplying one channel to another
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel1,typename Channel2,typename ChannelR>
+struct channel_multiplies_t : public std::binary_function<Channel1,Channel2,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
+ typename channel_traits<Channel2>::const_reference ch2) const {
+ return ChannelR(ch1)*ChannelR(ch2);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for dividing channels
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel1,typename Channel2,typename ChannelR>
+struct channel_divides_t : public std::binary_function<Channel1,Channel2,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel1>::const_reference ch1,
+ typename channel_traits<Channel2>::const_reference ch2) const {
+ return ChannelR(ch1)/ChannelR(ch2);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for adding a scalar to a channel
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel,typename Scalar,typename ChannelR>
+struct channel_plus_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
+ const Scalar& s) const {
+ return ChannelR(ch)+ChannelR(s);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for subtracting a scalar from a channel
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel,typename Scalar,typename ChannelR>
+struct channel_minus_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
+ const Scalar& s) const {
+ return ChannelR(ch-s);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for multiplying a scalar to one channel
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel,typename Scalar,typename ChannelR>
+struct channel_multiplies_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
+ const Scalar& s) const {
+ return ChannelR(ch)*ChannelR(s);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for dividing a channel by a scalar
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel,typename Scalar,typename ChannelR>
+struct channel_divides_scalar_t : public std::binary_function<Channel,Scalar,ChannelR> {
+ ChannelR operator()(typename channel_traits<Channel>::const_reference ch,
+ const Scalar& s) const {
+ return ChannelR(ch)/ChannelR(s);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for halving a channel
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel>
+struct channel_halves_t : public std::unary_function<Channel,Channel> {
+ typename channel_traits<Channel>::reference
+ operator()(typename channel_traits<Channel>::reference ch) const {
+ return ch/=2.0;
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for setting a channel to zero
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel>
+struct channel_zeros_t : public std::unary_function<Channel,Channel> {
+ typename channel_traits<Channel>::reference
+ operator()(typename channel_traits<Channel>::reference ch) const {
+ return ch=Channel(0);
+ }
+};
+
+/// \ingroup ChannelNumericOperations
+/// structure for assigning one channel to another
+/// this is a generic implementation; user should specialize it for better performance
+template <typename Channel1,typename Channel2>
+struct channel_assigns_t : public std::binary_function<Channel1,Channel2,Channel2> {
+ typename channel_traits<Channel2>::reference
+ operator()(typename channel_traits<Channel1>::const_reference ch1,
+ typename channel_traits<Channel2>::reference ch2) const {
+ return ch2=Channel2(ch1);
+ }
+};
+
+} } // namespace boost::gil
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
diff --git a/boost/gil/extension/numeric/convolve.hpp b/boost/gil/extension/numeric/convolve.hpp
new file mode 100644
index 0000000000..ba840aec71
--- /dev/null
+++ b/boost/gil/extension/numeric/convolve.hpp
@@ -0,0 +1,219 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
+
+/*!
+/// \file
+/// \brief 2D seperable convolutions and correlations
+///
+/// \author Hailin Jin and Lubomir Bourdev \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+*/
+
+
+#include <cstddef>
+#include <cassert>
+#include <algorithm>
+#include <vector>
+#include <functional>
+
+#include <boost/gil/gil_config.hpp>
+#include <boost/gil/image_view_factory.hpp>
+#include <boost/gil/algorithm.hpp>
+#include <boost/gil/metafunctions.hpp>
+#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
+#include <boost/gil/extension/numeric/algorithm.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup ImageAlgorithms
+/// Boundary options for 1D correlations/convolutions
+enum convolve_boundary_option {
+ convolve_option_output_ignore, /// do nothing to the output
+ convolve_option_output_zero, /// set the output to zero
+ convolve_option_extend_padded, /// assume the source boundaries to be padded already
+ convolve_option_extend_zero, /// assume the source boundaries to be zero
+ convolve_option_extend_constant /// assume the source boundaries to be the boundary value
+};
+
+namespace detail {
+/// compute the correlation of 1D kernel with the rows of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView,typename Correlator>
+void correlate_rows_imp(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option,
+ Correlator correlator) {
+ assert(src.dimensions()==dst.dimensions());
+ assert(ker.size()!=0);
+
+ typedef typename pixel_proxy<typename SrcView::value_type>::type PIXEL_SRC_REF;
+ typedef typename pixel_proxy<typename DstView::value_type>::type PIXEL_DST_REF;
+ typedef typename Kernel::value_type kernel_type;
+
+ if(ker.size()==1) {//reduces to a multiplication
+ view_multiplies_scalar<PixelAccum>(src,*ker.begin(),dst);
+ return;
+ }
+
+ int width=src.width(),height=src.height();
+ PixelAccum acc_zero; pixel_zeros_t<PixelAccum>()(acc_zero);
+ if (width==0) return;
+ if (option==convolve_option_output_ignore || option==convolve_option_output_zero) {
+ typename DstView::value_type dst_zero; pixel_assigns_t<PixelAccum,PIXEL_DST_REF>()(acc_zero,dst_zero);
+ if (width<(int)ker.size()) {
+ if (option==convolve_option_output_zero)
+ fill_pixels(dst,dst_zero);
+ } else {
+ std::vector<PixelAccum> buffer(width);
+ for(int rr=0;rr<height;++rr) {
+ assign_pixels(src.row_begin(rr),src.row_end(rr),&buffer.front());
+ typename DstView::x_iterator it_dst=dst.row_begin(rr);
+ if (option==convolve_option_output_zero)
+ std::fill_n(it_dst,ker.left_size(),dst_zero);
+ it_dst+=ker.left_size();
+ correlator(&buffer.front(),&buffer.front()+width+1-ker.size(),
+ ker.begin(),it_dst);
+ it_dst+=width+1-ker.size();
+ if (option==convolve_option_output_zero)
+ std::fill_n(it_dst,ker.right_size(),dst_zero);
+ }
+ }
+ } else {
+ std::vector<PixelAccum> buffer(width+ker.size()-1);
+ for(int rr=0;rr<height;++rr) {
+ PixelAccum* it_buffer=&buffer.front();
+ if (option==convolve_option_extend_padded) {
+ assign_pixels(src.row_begin(rr)-ker.left_size(),
+ src.row_end(rr)+ker.right_size(),
+ it_buffer);
+ } else if (option==convolve_option_extend_zero) {
+ std::fill_n(it_buffer,ker.left_size(),acc_zero);
+ it_buffer+=ker.left_size();
+ assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
+ it_buffer+=width;
+ std::fill_n(it_buffer,ker.right_size(),acc_zero);
+ } else if (option==convolve_option_extend_constant) {
+ PixelAccum filler;
+ pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(*src.row_begin(rr),filler);
+ std::fill_n(it_buffer,ker.left_size(),filler);
+ it_buffer+=ker.left_size();
+ assign_pixels(src.row_begin(rr),src.row_end(rr),it_buffer);
+ it_buffer+=width;
+ pixel_assigns_t<PIXEL_SRC_REF,PixelAccum>()(src.row_end(rr)[-1],filler);
+ std::fill_n(it_buffer,ker.right_size(),filler);
+ }
+ correlator(&buffer.front(),&buffer.front()+width,
+ ker.begin(),
+ dst.row_begin(rr));
+ }
+ }
+}
+template <typename PixelAccum>
+class correlator_n {
+private:
+ std::size_t _size;
+public:
+ correlator_n(std::size_t size_in) : _size(size_in) {}
+ template <typename SrcIterator,typename KernelIterator,typename DstIterator>
+ void operator()(SrcIterator src_begin,SrcIterator src_end,
+ KernelIterator ker_begin,
+ DstIterator dst_begin) {
+ correlate_pixels_n<PixelAccum>(src_begin,src_end,ker_begin,_size,dst_begin);
+ }
+};
+template <std::size_t Size,typename PixelAccum>
+struct correlator_k {
+public:
+ template <typename SrcIterator,typename KernelIterator,typename DstIterator>
+ void operator()(SrcIterator src_begin,SrcIterator src_end,
+ KernelIterator ker_begin,
+ DstIterator dst_begin){
+ correlate_pixels_k<Size,PixelAccum>(src_begin,src_end,ker_begin,dst_begin);
+ }
+};
+} // namespace detail
+
+/// \ingroup ImageAlgorithms
+///correlate a 1D variable-size kernel along the rows of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void correlate_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_n<PixelAccum>(ker.size()));
+}
+
+/// \ingroup ImageAlgorithms
+///correlate a 1D variable-size kernel along the columns of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void correlate_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ correlate_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
+}
+
+/// \ingroup ImageAlgorithms
+///convolve a 1D variable-size kernel along the rows of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void convolve_rows(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ correlate_rows<PixelAccum>(src,reverse_kernel(ker),dst,option);
+}
+
+/// \ingroup ImageAlgorithms
+///convolve a 1D variable-size kernel along the columns of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void convolve_cols(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ convolve_rows<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
+}
+
+/// \ingroup ImageAlgorithms
+///correlate a 1D fixed-size kernel along the rows of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void correlate_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ detail::correlate_rows_imp<PixelAccum>(src,ker,dst,option,detail::correlator_k<Kernel::static_size,PixelAccum>());
+}
+
+/// \ingroup ImageAlgorithms
+///correlate a 1D fixed-size kernel along the columns of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void correlate_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ correlate_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
+}
+
+/// \ingroup ImageAlgorithms
+///convolve a 1D fixed-size kernel along the rows of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void convolve_rows_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ correlate_rows_fixed<PixelAccum>(src,reverse_kernel(ker),dst,option);
+}
+
+/// \ingroup ImageAlgorithms
+///convolve a 1D fixed-size kernel along the columns of an image
+template <typename PixelAccum,typename SrcView,typename Kernel,typename DstView>
+BOOST_FORCEINLINE
+void convolve_cols_fixed(const SrcView& src, const Kernel& ker, const DstView& dst,
+ convolve_boundary_option option=convolve_option_extend_zero) {
+ convolve_rows_fixed<PixelAccum>(transposed_view(src),ker,transposed_view(dst),option);
+}
+
+} } // namespace boost::gil
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
diff --git a/boost/gil/extension/numeric/kernel.hpp b/boost/gil/extension/numeric/kernel.hpp
new file mode 100644
index 0000000000..012874d72a
--- /dev/null
+++ b/boost/gil/extension/numeric/kernel.hpp
@@ -0,0 +1,104 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
+
+/*!
+/// \file
+/// \brief Definitions of 1D fixed-size and variable-size kernels and related operations
+/// \author Hailin Jin and Lubomir Bourdev \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+*/
+
+#include <cstddef>
+#include <cassert>
+#include <array>
+#include <algorithm>
+#include <vector>
+#include <memory>
+
+#include <boost/gil/gil_config.hpp>
+#include <boost/gil/utilities.hpp>
+
+namespace boost { namespace gil {
+
+namespace detail {
+
+/// \brief kernel adaptor for one-dimensional cores
+/// Core needs to provide size(),begin(),end(),operator[],
+/// value_type,iterator,const_iterator,reference,const_reference
+template <typename Core>
+class kernel_1d_adaptor : public Core {
+private:
+ std::size_t _center;
+public:
+ kernel_1d_adaptor() : _center(0) {}
+ explicit kernel_1d_adaptor(std::size_t center_in) : _center(center_in) {assert(_center<this->size());}
+ kernel_1d_adaptor(std::size_t size_in,std::size_t center_in) :
+ Core(size_in), _center(center_in) {assert(_center<this->size());}
+ kernel_1d_adaptor(const kernel_1d_adaptor& k_in) : Core(k_in), _center(k_in._center) {}
+
+ kernel_1d_adaptor& operator=(const kernel_1d_adaptor& k_in) {
+ Core::operator=(k_in);
+ _center=k_in._center;
+ return *this;
+ }
+ std::size_t left_size() const {assert(_center<this->size());return _center;}
+ std::size_t right_size() const {assert(_center<this->size());return this->size()-_center-1;}
+ std::size_t& center() {return _center;}
+ const std::size_t& center() const {return _center;}
+};
+
+} // namespace detail
+
+/// \brief variable-size kernel
+template <typename T, typename Alloc = std::allocator<T> >
+class kernel_1d : public detail::kernel_1d_adaptor<std::vector<T,Alloc> > {
+ typedef detail::kernel_1d_adaptor<std::vector<T,Alloc> > parent_t;
+public:
+ kernel_1d() {}
+ kernel_1d(std::size_t size_in,std::size_t center_in) : parent_t(size_in,center_in) {}
+ template <typename FwdIterator>
+ kernel_1d(FwdIterator elements, std::size_t size_in, std::size_t center_in) : parent_t(size_in,center_in) {
+ detail::copy_n(elements,size_in,this->begin());
+ }
+ kernel_1d(const kernel_1d& k_in) : parent_t(k_in) {}
+};
+
+/// \brief static-size kernel
+template <typename T,std::size_t Size>
+class kernel_1d_fixed : public detail::kernel_1d_adaptor<std::array<T,Size> > {
+ typedef detail::kernel_1d_adaptor<std::array<T,Size> > parent_t;
+public:
+ kernel_1d_fixed() {}
+ explicit kernel_1d_fixed(std::size_t center_in) : parent_t(center_in) {}
+
+ template <typename FwdIterator>
+ explicit kernel_1d_fixed(FwdIterator elements, std::size_t center_in) : parent_t(center_in) {
+ detail::copy_n(elements,Size,this->begin());
+ }
+ kernel_1d_fixed(const kernel_1d_fixed& k_in) : parent_t(k_in) {}
+};
+
+/// \brief reverse a kernel
+template <typename Kernel>
+inline Kernel reverse_kernel(const Kernel& kernel) {
+ Kernel result(kernel);
+ result.center()=kernel.right_size();
+ std::reverse(result.begin(), result.end());
+ return result;
+}
+
+
+} } // namespace boost::gil
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
diff --git a/boost/gil/extension/numeric/pixel_numeric_operations.hpp b/boost/gil/extension/numeric/pixel_numeric_operations.hpp
new file mode 100644
index 0000000000..f5fc7c3e5a
--- /dev/null
+++ b/boost/gil/extension/numeric/pixel_numeric_operations.hpp
@@ -0,0 +1,182 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
+
+/*!
+/// \file
+/// \brief Structures for pixel-wise numeric operations
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+/// Currently defined structures:
+/// pixel_plus_t (+), pixel_minus_t (-)
+/// pixel_multiplies_scalar_t (*), pixel_divides_scalar_t (/)
+/// pixel_halves_t (/=2), pixel_zeros_t (=0)
+/// pixel_assigns_t (=)
+*/
+
+#include <functional>
+
+#include <boost/gil/gil_config.hpp>
+#include <boost/gil/pixel.hpp>
+#include <boost/gil/color_base_algorithm.hpp>
+
+#include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
+
+namespace boost { namespace gil {
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for adding two pixels
+template <typename PixelRef1, // models pixel concept
+ typename PixelRef2, // models pixel concept
+ typename PixelR> // models pixel value concept
+struct pixel_plus_t {
+ PixelR operator() (const PixelRef1& p1,
+ const PixelRef2& p2) const {
+ PixelR result;
+ static_transform(p1,p2,result,
+ channel_plus_t<typename channel_type<PixelRef1>::type,
+ typename channel_type<PixelRef2>::type,
+ typename channel_type<PixelR>::type>());
+ return result;
+ }
+};
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for subtracting two pixels
+template <typename PixelRef1, // models pixel concept
+ typename PixelRef2, // models pixel concept
+ typename PixelR> // models pixel value concept
+struct pixel_minus_t {
+ PixelR operator() (const PixelRef1& p1,
+ const PixelRef2& p2) const {
+ PixelR result;
+ static_transform(p1,p2,result,
+ channel_minus_t<typename channel_type<PixelRef1>::type,
+ typename channel_type<PixelRef2>::type,
+ typename channel_type<PixelR>::type>());
+ return result;
+ }
+};
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for multiplying scalar to a pixel
+template <typename PixelRef, // models pixel concept
+ typename Scalar, // models a scalar type
+ typename PixelR> // models pixel value concept
+struct pixel_multiplies_scalar_t {
+ PixelR operator () (const PixelRef& p,
+ const Scalar& s) const {
+ PixelR result;
+ static_transform(p,result,
+ std::bind2nd(channel_multiplies_scalar_t<typename channel_type<PixelRef>::type,
+ Scalar,
+ typename channel_type<PixelR>::type>(),s));
+ return result;
+ }
+};
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for dividing two pixels
+template <typename PixelRef1, // models pixel concept
+ typename PixelRef2, // models pixel concept
+ typename PixelR> // models pixel value concept
+struct pixel_multiply_t {
+ PixelR operator() (const PixelRef1& p1,
+ const PixelRef2& p2) const {
+ PixelR result;
+ static_transform(p1,p2,result,
+ channel_multiplies_t<typename channel_type<PixelRef1>::type,
+ typename channel_type<PixelRef2>::type,
+ typename channel_type<PixelR>::type>());
+ return result;
+ }
+};
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for dividing a pixel by a scalar
+template <typename PixelRef, // models pixel concept
+ typename Scalar, // models a scalar type
+ typename PixelR> // models pixel value concept
+struct pixel_divides_scalar_t {
+ PixelR operator () (const PixelRef& p,
+ const Scalar& s) const {
+ PixelR result;
+ static_transform(p,result,
+ std::bind2nd(channel_divides_scalar_t<typename channel_type<PixelRef>::type,
+ Scalar,
+ typename channel_type<PixelR>::type>(),s));
+ return result;
+ }
+};
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for dividing two pixels
+template <typename PixelRef1, // models pixel concept
+ typename PixelRef2, // models pixel concept
+ typename PixelR> // models pixel value concept
+struct pixel_divide_t {
+ PixelR operator() (const PixelRef1& p1,
+ const PixelRef2& p2) const {
+ PixelR result;
+ static_transform(p1,p2,result,
+ channel_divides_t<typename channel_type<PixelRef1>::type,
+ typename channel_type<PixelRef2>::type,
+ typename channel_type<PixelR>::type>());
+ return result;
+ }
+};
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for dividing a pixel by 2
+template <typename PixelRef> // models pixel concept
+struct pixel_halves_t {
+ PixelRef& operator () (PixelRef& p) const {
+ static_for_each(p,channel_halves_t<typename channel_type<PixelRef>::type>());
+ return p;
+ }
+};
+
+/// \ingroup PixelNumericOperations
+/// \brief construct for setting a pixel to zero (for whatever zero means)
+template <typename PixelRef> // models pixel concept
+struct pixel_zeros_t {
+ PixelRef& operator () (PixelRef& p) const {
+ static_for_each(p,channel_zeros_t<typename channel_type<PixelRef>::type>());
+ return p;
+ }
+};
+
+// Hailin: This is how you can do it:
+template <typename Pixel>
+void zero_channels(Pixel& p) {
+ static_for_each(p,channel_zeros_t<typename channel_type<Pixel>::type>());
+}
+
+
+/// \ingroup PixelNumericOperations
+///definition and a generic implementation for casting and assigning a pixel to another
+///user should specialize it for better performance
+template <typename PixelRef, // models pixel concept
+ typename PixelRefR> // models pixel concept
+struct pixel_assigns_t {
+ PixelRefR operator () (const PixelRef& src,
+ PixelRefR& dst) const {
+ static_for_each(src,dst,channel_assigns_t<typename channel_type<PixelRef>::type,
+ typename channel_type<PixelRefR>::type>());
+ return dst;
+ }
+};
+
+} } // namespace boost::gil
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
diff --git a/boost/gil/extension/numeric/resample.hpp b/boost/gil/extension/numeric/resample.hpp
new file mode 100644
index 0000000000..ec619d57a1
--- /dev/null
+++ b/boost/gil/extension/numeric/resample.hpp
@@ -0,0 +1,145 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_RESAMPLE_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_RESAMPLE_HPP
+
+#include <boost/lambda/lambda.hpp>
+#include <boost/lambda/bind.hpp>
+
+#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
+
+#include <boost/gil/extension/numeric/affine.hpp>
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief support for generic image resampling
+/// NOTE: The code is for example use only. It is not optimized for performance
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil {
+
+///////////////////////////////////////////////////////////////////////////
+////
+//// resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
+////
+///////////////////////////////////////////////////////////////////////////
+
+template <typename MapFn> struct mapping_traits {};
+
+/// \brief Set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
+/// \ingroup ImageAlgorithms
+///
+/// The provided implementation works for 2D image views only
+template <typename Sampler, // Models SamplerConcept
+ typename SrcView, // Models RandomAccess2DImageViewConcept
+ typename DstView, // Models MutableRandomAccess2DImageViewConcept
+ typename MapFn> // Models MappingFunctionConcept
+void resample_pixels(const SrcView& src_view, const DstView& dst_view, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
+ typename DstView::point_t dst_dims=dst_view.dimensions();
+ typename DstView::point_t dst_p;
+ typename mapping_traits<MapFn>::result_type src_p;
+
+ for (dst_p.y=0; dst_p.y<dst_dims.y; ++dst_p.y) {
+ typename DstView::x_iterator xit = dst_view.row_begin(dst_p.y);
+ for (dst_p.x=0; dst_p.x<dst_dims.x; ++dst_p.x) {
+ sample(sampler, src_view, transform(dst_to_src, dst_p), xit[dst_p.x]);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////
+////
+//// resample_pixels when one or both image views are run-time instantiated.
+////
+///////////////////////////////////////////////////////////////////////////
+
+namespace detail {
+ template <typename Sampler, typename MapFn>
+ struct resample_pixels_fn : public binary_operation_obj<resample_pixels_fn<Sampler,MapFn> > {
+ MapFn _dst_to_src;
+ Sampler _sampler;
+ resample_pixels_fn(const MapFn& dst_to_src, const Sampler& sampler) : _dst_to_src(dst_to_src), _sampler(sampler) {}
+
+ template <typename SrcView, typename DstView> BOOST_FORCEINLINE void apply_compatible(const SrcView& src, const DstView& dst) const {
+ resample_pixels(src, dst, _dst_to_src, _sampler);
+ }
+ };
+}
+
+/// \brief resample_pixels when the source is run-time specified
+/// If invoked on incompatible views, throws std::bad_cast()
+/// \ingroup ImageAlgorithms
+template <typename Sampler, typename Types1, typename V2, typename MapFn>
+void resample_pixels(const any_image_view<Types1>& src, const V2& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
+ apply_operation(src,bind(detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler), _1, dst));
+}
+
+/// \brief resample_pixels when the destination is run-time specified
+/// If invoked on incompatible views, throws std::bad_cast()
+/// \ingroup ImageAlgorithms
+template <typename Sampler, typename V1, typename Types2, typename MapFn>
+void resample_pixels(const V1& src, const any_image_view<Types2>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
+ apply_operation(dst,bind(detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler), src, _1));
+}
+
+/// \brief resample_pixels when both the source and the destination are run-time specified
+/// If invoked on incompatible views, throws std::bad_cast()
+/// \ingroup ImageAlgorithms
+template <typename Sampler, typename SrcTypes, typename DstTypes, typename MapFn>
+void resample_pixels(const any_image_view<SrcTypes>& src, const any_image_view<DstTypes>& dst, const MapFn& dst_to_src, Sampler sampler=Sampler()) {
+ apply_operation(src,dst,detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler));
+}
+
+///////////////////////////////////////////////////////////////////////////
+////
+//// resample_subimage: copy into the destination a rotated rectangular region from the source, rescaling it to fit into the destination
+////
+///////////////////////////////////////////////////////////////////////////
+
+// Extract into dst the rotated bounds [src_min..src_max] rotated at 'angle' from the source view 'src'
+// The source coordinates are in the coordinate space of the source image
+// Note that the views could also be variants (i.e. any_image_view)
+template <typename Sampler, typename SrcMetaView, typename DstMetaView>
+void resample_subimage(const SrcMetaView& src, const DstMetaView& dst,
+ double src_min_x, double src_min_y,
+ double src_max_x, double src_max_y,
+ double angle, const Sampler& sampler=Sampler()) {
+ double src_width = std::max<double>(src_max_x - src_min_x - 1,1);
+ double src_height = std::max<double>(src_max_y - src_min_y - 1,1);
+ double dst_width = std::max<double>((double)(dst.width()-1),1);
+ double dst_height = std::max<double>((double)(dst.height()-1),1);
+
+ matrix3x2<double> mat =
+ matrix3x2<double>::get_translate(-dst_width/2.0, -dst_height/2.0) *
+ matrix3x2<double>::get_scale(src_width / dst_width, src_height / dst_height)*
+ matrix3x2<double>::get_rotate(-angle)*
+ matrix3x2<double>::get_translate(src_min_x + src_width/2.0, src_min_y + src_height/2.0);
+ resample_pixels(src,dst,mat,sampler);
+}
+
+///////////////////////////////////////////////////////////////////////////
+////
+//// resize_view: Copy the source view into the destination, scaling to fit
+////
+///////////////////////////////////////////////////////////////////////////
+
+template <typename Sampler, typename SrcMetaView, typename DstMetaView>
+void resize_view(const SrcMetaView& src, const DstMetaView& dst, const Sampler& sampler=Sampler()) {
+ resample_subimage(src,dst,0.0,0.0,(double)src.width(),(double)src.height(),0.0,sampler);
+}
+
+} } // namespace boost::gil
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_RESAMPLE_HPP
diff --git a/boost/gil/extension/numeric/sampler.hpp b/boost/gil/extension/numeric/sampler.hpp
new file mode 100644
index 0000000000..494611a314
--- /dev/null
+++ b/boost/gil/extension/numeric/sampler.hpp
@@ -0,0 +1,200 @@
+/*
+ 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).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
+#define BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
+
+#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
+
+#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief Nearest-neighbor and bilinear image samplers.
+/// NOTE: The code is for example use only. It is not optimized for performance
+/// \author Lubomir Bourdev and Hailin Jin \n
+/// Adobe Systems Incorporated
+/// \date 2005-2007 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+namespace boost { namespace gil {
+
+///////////////////////////////////////////////////////////////////////////
+////
+//// resample_pixels: set each pixel in the destination view as the result of a sampling function over the transformed coordinates of the source view
+////
+///////////////////////////////////////////////////////////////////////////
+/*
+template <typename Sampler>
+concept SamplerConcept {
+ template <typename DstP, // Models PixelConcept
+ typename SrcView, // Models RandomAccessNDImageViewConcept
+ typename S_COORDS> // Models PointNDConcept, where S_COORDS::num_dimensions == SrcView::num_dimensions
+ bool sample(const Sampler& s, const SrcView& src, const S_COORDS& p, DstP result);
+};
+*/
+
+/// \brief A sampler that sets the destination pixel to the closest one in the source. If outside the bounds, it doesn't change the destination
+/// \ingroup ImageAlgorithms
+struct nearest_neighbor_sampler {};
+
+template <typename DstP, typename SrcView, typename F>
+bool sample(nearest_neighbor_sampler, const SrcView& src, const point2<F>& p, DstP& result) {
+ typename SrcView::point_t center(iround(p));
+ if (center.x>=0 && center.y>=0 && center.x<src.width() && center.y<src.height()) {
+ result=src(center.x,center.y);
+ return true;
+ }
+ return false;
+}
+
+struct cast_channel_fn {
+ template <typename SrcChannel, typename DstChannel>
+ void operator()(const SrcChannel& src, DstChannel& dst) {
+ typedef typename channel_traits<DstChannel>::value_type dst_value_t;
+ dst = dst_value_t(src);
+ }
+};
+
+template <typename SrcPixel, typename DstPixel>
+void cast_pixel(const SrcPixel& src, DstPixel& dst) {
+ static_for_each(src,dst,cast_channel_fn());
+}
+
+namespace detail {
+
+template <typename Weight>
+struct add_dst_mul_src_channel {
+ Weight _w;
+ add_dst_mul_src_channel(Weight w) : _w(w) {}
+
+ template <typename SrcChannel, typename DstChannel>
+ void operator()(const SrcChannel& src, DstChannel& dst) const {
+ dst += DstChannel(src*_w);
+ }
+};
+
+// dst += DST_TYPE(src * w)
+template <typename SrcP,typename Weight,typename DstP>
+struct add_dst_mul_src {
+ void operator()(const SrcP& src, Weight weight, DstP& dst) const {
+ static_for_each(src,dst, add_dst_mul_src_channel<Weight>(weight));
+// pixel_assigns_t<DstP,DstP&>()(
+// pixel_plus_t<DstP,DstP,DstP>()(
+// pixel_multiplies_scalar_t<SrcP,Weight,DstP>()(src,weight),
+// dst),
+// dst);
+ }
+};
+} // namespace detail
+
+/// \brief A sampler that sets the destination pixel as the bilinear interpolation of the four closest pixels from the source.
+/// If outside the bounds, it doesn't change the destination
+/// \ingroup ImageAlgorithms
+struct bilinear_sampler {};
+
+template <typename DstP, typename SrcView, typename F>
+bool sample(bilinear_sampler, const SrcView& src, const point2<F>& p, DstP& result)
+{
+ typedef typename SrcView::value_type SrcP;
+
+ point2<ptrdiff_t> p0(ifloor(p.x), ifloor(p.y)); // the closest integer coordinate top left from p
+ point2<F> frac(p.x-p0.x, p.y-p0.y);
+
+ if (p0.x < -1 || p0.y < -1 || p0.x>=src.width() || p0.y>=src.height())
+ {
+ return false;
+ }
+
+ pixel<F,devicen_layout_t<num_channels<SrcView>::value> > mp(0); // suboptimal
+ typename SrcView::xy_locator loc=src.xy_at(p0.x,p0.y);
+
+ if (p0.x == -1)
+ {
+ if (p0.y == -1)
+ {
+ // the top-left corner pixel
+ ++loc.y();
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], 1 ,mp);
+ }
+ else if (p0.y+1<src.height())
+ {
+ // on the first column, but not the top-left nor bottom-left corner pixel
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], (1-frac.y),mp);
+ ++loc.y();
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.y ,mp);
+ }
+ else
+ {
+ // the bottom-left corner pixel
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], 1 ,mp);
+ }
+ }
+ else if (p0.x+1<src.width())
+ {
+ if (p0.y == -1)
+ {
+ // on the first row, but not the top-left nor top-right corner pixel
+ ++loc.y();
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x) ,mp);
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x ,mp);
+ }
+ else if (p0.y+1<src.height())
+ {
+ // most common case - inside the image, not on the frist nor last row/column
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x)*(1-frac.y),mp);
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x *(1-frac.y),mp);
+ ++loc.y();
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x)* frac.y ,mp);
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x * frac.y ,mp);
+ }
+ else
+ {
+ // on the last row, but not the bottom-left nor bottom-right corner pixel
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.x) ,mp);
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(loc.x()[1], frac.x ,mp);
+ }
+ }
+ else
+ {
+ if (p0.y == -1)
+ {
+ // the top-right corner pixel
+ ++loc.y();
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, 1 ,mp);
+ }
+ else if (p0.y+1<src.height())
+ {
+ // on the last column, but not the top-right nor bottom-right corner pixel
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, (1-frac.y),mp);
+ ++loc.y();
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, frac.y ,mp);
+ }
+ else
+ {
+ // the bottom-right corner pixel
+ detail::add_dst_mul_src<SrcP,F,pixel<F,devicen_layout_t<num_channels<SrcView>::value> > >()(*loc, 1 ,mp);
+ }
+ }
+
+ // Convert from floating point average value to the source type
+ SrcP src_result;
+ cast_pixel(mp,src_result);
+
+ color_convert(src_result, result);
+
+ return true;
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
diff --git a/boost/gil/extension/toolbox/color_converters.hpp b/boost/gil/extension/toolbox/color_converters.hpp
new file mode 100644
index 0000000000..5286ac14d6
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_converters.hpp
@@ -0,0 +1,25 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file color_converters.hpp
+/// \brief Color converters for toolbox extension.
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/toolbox/color_converters/gray_to_rgba.hpp>
+#include <boost/gil/extension/toolbox/color_converters/rgb_to_luminance.hpp>
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_HPP
diff --git a/boost/gil/extension/toolbox/color_converters/gray_to_rgba.hpp b/boost/gil/extension/toolbox/color_converters/gray_to_rgba.hpp
new file mode 100644
index 0000000000..1cfc873ac6
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_converters/gray_to_rgba.hpp
@@ -0,0 +1,49 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_GRAY_TO_RGBA_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_GRAY_TO_RGBA_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/color_convert.hpp>
+
+namespace boost{ namespace gil {
+
+/// This one is missing in gil ( color_convert.hpp ).
+template <>
+struct default_color_converter_impl<gray_t,rgba_t>
+{
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const
+ {
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type<P2, red_t >::type>(get_color(src,gray_color_t()));
+ get_color(dst,green_t())=
+ channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type<P2, blue_t >::type>(get_color(src,gray_color_t()));
+
+ typedef typename channel_type< P2 >::type channel_t;
+ get_color(dst,alpha_t()) = channel_traits< channel_t >::max_value();
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_GRAY_TO_RGBA_HPP
+
diff --git a/boost/gil/extension/toolbox/color_converters/rgb_to_luminance.hpp b/boost/gil/extension/toolbox/color_converters/rgb_to_luminance.hpp
new file mode 100644
index 0000000000..e4daa6570b
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_converters/rgb_to_luminance.hpp
@@ -0,0 +1,43 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_RGB_TO_LUMINANCE_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_RGB_TO_LUMINANCE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/color_convert.hpp>
+
+namespace boost{ namespace gil { namespace detail {
+
+/// - performance specialization double
+/// - to eliminate compiler warning 4244
+template <typename GrayChannelValue>
+struct rgb_to_luminance_fn< double, double, double, GrayChannelValue >
+{
+ GrayChannelValue operator()( const double& red
+ , const double& green
+ , const double& blue ) const
+ {
+ return channel_convert<GrayChannelValue>( red * 0.30 + green * 0.59 + blue * 0.11 );
+ }
+};
+
+} // namespace detail
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_CONVERTERS_RGB_TO_LUMINANCE_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces.hpp b/boost/gil/extension/toolbox/color_spaces.hpp
new file mode 100644
index 0000000000..acb3a9dea3
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces.hpp
@@ -0,0 +1,29 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file color_spaces.hpp
+/// \brief Color spaces for toolbox extension.
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/toolbox/color_spaces/cmyka.hpp>
+#include <boost/gil/extension/toolbox/color_spaces/gray_alpha.hpp>
+#include <boost/gil/extension/toolbox/color_spaces/hsl.hpp>
+#include <boost/gil/extension/toolbox/color_spaces/hsv.hpp>
+#include <boost/gil/extension/toolbox/color_spaces/lab.hpp>
+#include <boost/gil/extension/toolbox/color_spaces/xyz.hpp>
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces/cmyka.hpp b/boost/gil/extension/toolbox/color_spaces/cmyka.hpp
new file mode 100644
index 0000000000..e6c3572b92
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces/cmyka.hpp
@@ -0,0 +1,86 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_CMYKA_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_CMYKA_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file cmyka.hpp
+/// \brief Support for cmyka color space.
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/rgba.hpp>
+#include <boost/gil/cmyk.hpp>
+
+#include <boost/gil/color_convert.hpp>
+#include <boost/gil/typedefs.hpp>
+
+namespace boost{ namespace gil {
+
+/// \ingroup ColorSpaceModel
+using cmyka_t = mpl::vector5<cyan_t, magenta_t, yellow_t, black_t, alpha_t>;
+
+/// \ingroup LayoutModel
+using cmyka_layout_t = layout<cmyka_t>;
+
+GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, cmyka)
+GIL_DEFINE_ALL_TYPEDEFS(8s, int8_t, cmyka)
+GIL_DEFINE_ALL_TYPEDEFS(16, uint16_t, cmyka)
+GIL_DEFINE_ALL_TYPEDEFS(16s, int16_t, cmyka)
+GIL_DEFINE_ALL_TYPEDEFS(32, uint32_t, cmyka)
+GIL_DEFINE_ALL_TYPEDEFS(32s, int32_t, cmyka)
+GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, cmyka)
+
+///// \ingroup ColorConvert
+///// \brief Converting CMYKA to any pixel type. Note: Supports homogeneous pixels only.
+//template <typename C2>
+//struct default_color_converter_impl<cmyka_t,C2> {
+// template <typename P1, typename P2>
+// void operator()(const P1& src, P2& dst) const {
+// typedef typename channel_type<P1>::type T1;
+// default_color_converter_impl<cmyk_t,C2>()(
+// pixel<T1,cmyk_layout_t>(channel_multiply(get_color(src,cyan_t()), get_color(src,alpha_t())),
+// channel_multiply(get_color(src,magenta_t()),get_color(src,alpha_t())),
+// channel_multiply(get_color(src,yellow_t()), get_color(src,alpha_t())),
+// channel_multiply(get_color(src,black_t()), get_color(src,alpha_t())))
+// ,dst);
+// }
+//};
+template <>
+struct default_color_converter_impl<cmyka_t,rgba_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ typedef typename channel_type<P1>::type T1;
+ default_color_converter_impl<cmyk_t,rgba_t>()(
+ pixel<T1,cmyk_layout_t>(get_color(src,cyan_t()),
+ get_color(src,magenta_t()),
+ get_color(src,yellow_t()),
+ get_color(src,black_t()))
+ ,dst);
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief Unfortunately CMYKA to CMYKA must be explicitly provided - otherwise we get ambiguous specialization error.
+template <>
+struct default_color_converter_impl<cmyka_t,cmyka_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ static_for_each(src,dst,default_channel_converter());
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_CMYKA_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces/gray_alpha.hpp b/boost/gil/extension/toolbox/color_spaces/gray_alpha.hpp
new file mode 100644
index 0000000000..f32a95a541
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces/gray_alpha.hpp
@@ -0,0 +1,104 @@
+/*
+ Copyright 2012 Andreas Pokorny
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_GRAY_ALPHA_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_GRAY_ALPHA_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file gray_alpha.hpp
+/// \brief Support for gray_alpha color space.
+/// \author Andreas Pokorny \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/contains.hpp>
+
+#include <boost/gil/gil_config.hpp>
+#include <boost/gil/color_convert.hpp>
+#include <boost/gil/gray.hpp>
+#include <boost/gil/typedefs.hpp>
+
+namespace boost{ namespace gil {
+
+typedef mpl::vector2<gray_color_t,alpha_t> gray_alpha_t;
+
+typedef layout<gray_alpha_t> gray_alpha_layout_t;
+typedef layout<gray_alpha_layout_t, mpl::vector2_c<int,1,0> > alpha_gray_layout_t;
+
+GIL_DEFINE_BASE_TYPEDEFS(8, uint8_t, alpha_gray)
+GIL_DEFINE_BASE_TYPEDEFS(8s, int8_t, alpha_gray)
+GIL_DEFINE_BASE_TYPEDEFS(16, uint16_t, alpha_gray)
+GIL_DEFINE_BASE_TYPEDEFS(16s, int16_t, alpha_gray)
+GIL_DEFINE_BASE_TYPEDEFS(32, uint32_t, alpha_gray)
+GIL_DEFINE_BASE_TYPEDEFS(32s, int32_t, alpha_gray)
+GIL_DEFINE_BASE_TYPEDEFS(32f, float32_t, alpha_gray)
+
+GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, gray_alpha)
+GIL_DEFINE_ALL_TYPEDEFS(8s, int8_t, gray_alpha)
+GIL_DEFINE_ALL_TYPEDEFS(16, uint16_t, gray_alpha)
+GIL_DEFINE_ALL_TYPEDEFS(16s, int16_t, gray_alpha)
+GIL_DEFINE_ALL_TYPEDEFS(32, uint32_t, gray_alpha)
+GIL_DEFINE_ALL_TYPEDEFS(32s, int32_t, gray_alpha)
+GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, gray_alpha)
+
+/// \ingroup ColorConvert
+/// \brief Gray Alpha to RGBA
+template <>
+struct default_color_converter_impl<gray_alpha_t,rgba_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type<P2, red_t>::type>(get_color(src,gray_color_t()));
+ get_color(dst,green_t())=
+ channel_convert<typename color_element_type<P2, green_t>::type>(get_color(src,gray_color_t()));
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type<P2, blue_t>::type>(get_color(src,gray_color_t()));
+ get_color(dst,alpha_t()) =
+ channel_convert<typename color_element_type<P2, alpha_t>::type>(get_color(src,alpha_t()));
+ }
+};
+
+/// \brief Gray Alpha to RGB
+template <>
+struct default_color_converter_impl<gray_alpha_t,rgb_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type<P2, red_t>::type>(
+ channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
+ );
+ get_color(dst,green_t()) =
+ channel_convert<typename color_element_type<P2, green_t>::type>(
+ channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
+ );
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type<P2, blue_t>::type>(
+ channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
+ );
+ }
+};
+
+/// \brief Gray Alpha to Gray
+template <>
+struct default_color_converter_impl<gray_alpha_t,gray_t> {
+ template <typename P1, typename P2>
+ void operator()(const P1& src, P2& dst) const {
+ get_color(dst,gray_color_t()) =
+ channel_convert<typename color_element_type<P2, gray_color_t>::type>(
+ channel_multiply(get_color(src,gray_color_t()),get_color(src,alpha_t()) )
+ );
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_GRAY_ALPHA_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces/hsl.hpp b/boost/gil/extension/toolbox/color_spaces/hsl.hpp
new file mode 100644
index 0000000000..d5fb48e3f4
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces/hsl.hpp
@@ -0,0 +1,268 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSL_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSL_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file hsl.hpp
+/// \brief Support for HSL color space
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/typedefs.hpp>
+
+namespace boost{ namespace gil {
+
+/// \addtogroup ColorNameModel
+/// \{
+namespace hsl_color_space
+{
+/// \brief Hue
+struct hue_t {};
+/// \brief Saturation
+struct saturation_t {};
+/// \brief Lightness
+struct lightness_t {};
+}
+/// \}
+
+/// \ingroup ColorSpaceModel
+typedef mpl::vector3< hsl_color_space::hue_t
+ , hsl_color_space::saturation_t
+ , hsl_color_space::lightness_t
+ > hsl_t;
+
+/// \ingroup LayoutModel
+typedef layout<hsl_t> hsl_layout_t;
+
+
+GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsl)
+
+/// \ingroup ColorConvert
+/// \brief RGB to HSL
+template <>
+struct default_color_converter_impl< rgb_t, hsl_t >
+{
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst ) const
+ {
+ using namespace hsl_color_space;
+
+ // only float32_t for hsl is supported
+ float32_t temp_red = channel_convert<float32_t>( get_color( src, red_t() ));
+ float32_t temp_green = channel_convert<float32_t>( get_color( src, green_t() ));
+ float32_t temp_blue = channel_convert<float32_t>( get_color( src, blue_t() ));
+
+ float32_t hue, saturation, lightness;
+
+ float32_t min_color = (std::min)( temp_red, (std::min)( temp_green, temp_blue ));
+ float32_t max_color = (std::max)( temp_red, (std::max)( temp_green, temp_blue ));
+
+ if( std::abs( min_color - max_color ) < 0.001 )
+ {
+ // rgb color is gray
+
+ hue = 0.f;
+ saturation = 0.f;
+
+ // doesn't matter which rgb channel we use.
+ lightness = temp_red;
+ }
+ else
+ {
+
+ float32_t diff = max_color - min_color;
+
+ // lightness calculation
+
+ lightness = ( min_color + max_color ) / 2.f;
+
+ // saturation calculation
+
+ if( lightness < 0.5f )
+ {
+ saturation = diff
+ / ( min_color + max_color );
+ }
+ else
+ {
+ saturation = ( max_color - min_color )
+ / ( 2.f - diff );
+
+ }
+
+ // hue calculation
+ if( std::abs( max_color - temp_red ) < 0.0001f )
+ {
+ // max_color is red
+ hue = ( temp_green - temp_blue )
+ / diff;
+
+ }
+ else if( std::abs( max_color - temp_green) < 0.0001f )
+ {
+ // max_color is green
+ // 2.0 + (b - r) / (maxColor - minColor);
+ hue = 2.f
+ + ( temp_blue - temp_red )
+ / diff;
+
+ }
+ else
+ {
+ // max_color is blue
+ hue = 4.f
+ + ( temp_red - temp_blue )
+ / diff;
+ }
+
+ hue /= 6.f;
+
+ if( hue < 0.f )
+ {
+ hue += 1.f;
+ }
+ }
+
+ get_color( dst,hue_t() ) = hue;
+ get_color( dst,saturation_t() ) = saturation;
+ get_color( dst,lightness_t() ) = lightness;
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief HSL to RGB
+template <>
+struct default_color_converter_impl<hsl_t,rgb_t>
+{
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst) const
+ {
+ using namespace hsl_color_space;
+
+ float32_t red, green, blue;
+
+ if( std::abs( get_color( src, saturation_t() )) < 0.0001 )
+ {
+ // If saturation is 0, the color is a shade of gray
+ red = get_color( src, lightness_t() );
+ green = get_color( src, lightness_t() );
+ blue = get_color( src, lightness_t() );
+ }
+ else
+ {
+ float temp1, temp2;
+ float tempr, tempg, tempb;
+
+ //Set the temporary values
+ if( get_color( src, lightness_t() ) < 0.5 )
+ {
+ temp2 = get_color( src, lightness_t() )
+ * ( 1.f + get_color( src, saturation_t() ) );
+ }
+ else
+ {
+ temp2 = ( get_color( src, lightness_t() ) + get_color( src, saturation_t() ))
+ - ( get_color( src, lightness_t() ) * get_color( src, saturation_t() ));
+ }
+
+ temp1 = 2.f
+ * get_color( src, lightness_t() )
+ - temp2;
+
+ tempr = get_color( src, hue_t() ) + 1.f / 3.f;
+
+ if( tempr > 1.f )
+ {
+ tempr--;
+ }
+
+ tempg = get_color( src, hue_t() );
+ tempb = get_color( src, hue_t() ) - 1.f / 3.f;
+
+ if( tempb < 0.f )
+ {
+ tempb++;
+ }
+
+ //Red
+ if( tempr < 1.f / 6.f )
+ {
+ red = temp1 + ( temp2 - temp1 ) * 6.f * tempr;
+ }
+ else if( tempr < 0.5f )
+ {
+ red = temp2;
+ }
+ else if( tempr < 2.f / 3.f )
+ {
+ red = temp1 + (temp2 - temp1)
+ * (( 2.f / 3.f ) - tempr) * 6.f;
+ }
+ else
+ {
+ red = temp1;
+ }
+
+ //Green
+ if( tempg < 1.f / 6.f )
+ {
+ green = temp1 + ( temp2 - temp1 ) * 6.f * tempg;
+ }
+ else if( tempg < 0.5f )
+ {
+ green = temp2;
+ }
+ else if( tempg < 2.f / 3.f )
+ {
+ green = temp1 + ( temp2 - temp1 )
+ * (( 2.f / 3.f ) - tempg) * 6.f;
+ }
+ else
+ {
+ green = temp1;
+ }
+
+ //Blue
+ if( tempb < 1.f / 6.f )
+ {
+ blue = temp1 + (temp2 - temp1) * 6.f * tempb;
+ }
+ else if( tempb < 0.5f )
+ {
+ blue = temp2;
+ }
+ else if( tempb < 2.f / 3.f )
+ {
+ blue = temp1 + (temp2 - temp1)
+ * (( 2.f / 3.f ) - tempb) * 6.f;
+ }
+ else
+ {
+ blue = temp1;
+ }
+ }
+
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type< P2, red_t >::type>( red );
+ get_color(dst,green_t())=
+ channel_convert<typename color_element_type< P2, green_t >::type>( green );
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type< P2, blue_t >::type>( blue );
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSL_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces/hsv.hpp b/boost/gil/extension/toolbox/color_spaces/hsv.hpp
new file mode 100644
index 0000000000..6e0b332c3f
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces/hsv.hpp
@@ -0,0 +1,237 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSV_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSV_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file hsv.hpp
+/// \brief Support for HSV color space
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <boost/gil/typedefs.hpp>
+
+namespace boost{ namespace gil {
+
+/// \addtogroup ColorNameModel
+/// \{
+namespace hsv_color_space
+{
+/// \brief Hue
+struct hue_t {};
+/// \brief Saturation
+struct saturation_t{};
+/// \brief Value
+struct value_t {};
+}
+/// \}
+
+/// \ingroup ColorSpaceModel
+typedef mpl::vector3< hsv_color_space::hue_t
+ , hsv_color_space::saturation_t
+ , hsv_color_space::value_t
+ > hsv_t;
+
+/// \ingroup LayoutModel
+typedef layout<hsv_t> hsv_layout_t;
+
+GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsv)
+
+/// \ingroup ColorConvert
+/// \brief RGB to HSV
+template <>
+struct default_color_converter_impl< rgb_t, hsv_t >
+{
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst ) const
+ {
+ using namespace hsv_color_space;
+
+ // only float32_t for hsv is supported
+ float32_t temp_red = channel_convert<float32_t>( get_color( src, red_t() ));
+ float32_t temp_green = channel_convert<float32_t>( get_color( src, green_t() ));
+ float32_t temp_blue = channel_convert<float32_t>( get_color( src, blue_t() ));
+
+ float32_t hue, saturation, value;
+
+ float32_t min_color = (std::min)( temp_red, (std::min)( temp_green, temp_blue ));
+ float32_t max_color = (std::max)( temp_red, (std::max)( temp_green, temp_blue ));
+
+ value = max_color;
+
+ float32_t diff = max_color - min_color;
+
+ if( max_color < 0.0001f )
+ {
+ saturation = 0.f;
+ }
+ else
+ {
+ saturation = diff / max_color;
+ }
+
+
+ if( saturation < 0.0001f )
+ {
+ //it doesn't matter what value it has
+ hue = 0.f;
+ }
+ else
+ {
+ if( (std::abs)( boost::numeric_cast<float32_t>(temp_red - max_color) ) < 0.0001f )
+ {
+ hue = ( temp_green - temp_blue )
+ / diff;
+ }
+ else if( temp_green == max_color )
+ {
+ hue = 2.f + ( temp_blue - temp_red )
+ / diff;
+ }
+ else
+ {
+ hue = 4.f + ( temp_red - temp_green )
+ / diff;
+ }
+
+ //to bring it to a number between 0 and 1
+ hue /= 6.f;
+
+ if( hue < 0.f )
+ {
+ hue++;
+ }
+ }
+
+ get_color( dst, hue_t() ) = hue;
+ get_color( dst, saturation_t() ) = saturation;
+ get_color( dst, value_t() ) = value;
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief HSV to RGB
+template <>
+struct default_color_converter_impl<hsv_t,rgb_t>
+{
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst) const
+ {
+ using namespace hsv_color_space;
+
+ float32_t red, green, blue;
+
+ //If saturation is 0, the color is a shade of gray
+ if( abs( get_color( src, saturation_t() )) < 0.0001f )
+ {
+ // If saturation is 0, the color is a shade of gray
+ red = get_color( src, value_t() );
+ green = get_color( src, value_t() );
+ blue = get_color( src, value_t() );
+ }
+ else
+ {
+ float32_t frac, p, q, t, h;
+ uint32_t i;
+
+ //to bring hue to a number between 0 and 6, better for the calculations
+ h = get_color( src, hue_t() );
+ h *= 6.f;
+
+ i = static_cast<uint32_t>(floor(h));
+
+ frac = h - i;
+
+ p = get_color( src, value_t() )
+ * ( 1.f - get_color( src, saturation_t() ));
+
+ q = get_color( src, value_t() )
+ * ( 1.f - ( get_color( src, saturation_t() ) * frac ));
+
+ t = get_color( src, value_t() )
+ * ( 1.f - ( get_color( src, saturation_t() ) * ( 1.f - frac )));
+
+ switch( i )
+ {
+ case 0:
+ {
+ red = get_color( src, value_t() );
+ green = t;
+ blue = p;
+
+ break;
+ }
+
+ case 1:
+ {
+ red = q;
+ green = get_color( src, value_t() );
+ blue = p;
+
+ break;
+ }
+
+ case 2:
+ {
+ red = p;
+ green = get_color( src, value_t() );
+ blue = t;
+
+ break;
+ }
+
+ case 3:
+ {
+ red = p;
+ green = q;
+ blue = get_color( src, value_t() );
+
+ break;
+ }
+
+ case 4:
+ {
+ red = t;
+ green = p;
+ blue = get_color( src, value_t() );
+
+ break;
+ }
+
+ case 5:
+ {
+ red = get_color( src, value_t() );
+ green = p;
+ blue = q;
+
+ break;
+ }
+
+ }
+ }
+
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type< P2, red_t >::type>( red );
+ get_color(dst,green_t())=
+ channel_convert<typename color_element_type< P2, green_t >::type>( green );
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type< P2, blue_t >::type>( blue );
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSV_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces/lab.hpp b/boost/gil/extension/toolbox/color_spaces/lab.hpp
new file mode 100644
index 0000000000..140c79f763
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces/lab.hpp
@@ -0,0 +1,178 @@
+/*
+ Copyright 2012 Chung-Lin Wen
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_LAB_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_LAB_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file lab.hpp
+/// \brief Support for CIE Lab color space
+/// \author Chung-Lin Wen \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/gil_all.hpp> // FIXME: Include what you use, not everything, even in extensions!
+#include <boost/gil/extension/toolbox/color_spaces/xyz.hpp>
+
+namespace boost{ namespace gil {
+
+/// \addtogroup ColorNameModel
+/// \{
+namespace lab_color_space
+{
+/// \brief Luminance
+struct luminance_t {};
+/// \brief a Color Component
+struct a_color_opponent_t {};
+/// \brief b Color Component
+struct b_color_opponent_t {};
+}
+/// \}
+
+/// \ingroup ColorSpaceModel
+typedef mpl::vector3< lab_color_space::luminance_t
+ , lab_color_space::a_color_opponent_t
+ , lab_color_space::b_color_opponent_t
+ > lab_t;
+
+/// \ingroup LayoutModel
+typedef layout<lab_t> lab_layout_t;
+
+GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, lab)
+
+/// \ingroup ColorConvert
+/// \brief LAB to XYZ
+template <>
+struct default_color_converter_impl< lab_t, xyz_t >
+{
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst ) const
+ {
+ using namespace lab_color_space;
+ using namespace xyz_color_space;
+
+ float32_t p = ((get_color(src, luminance_t()) + 16.f)/116.f);
+
+ get_color(dst, y_t()) =
+ 1.f * powf(p, 3.f);
+
+ get_color(dst, x_t()) =
+ 0.95047f * powf((p +
+ (get_color(src, a_color_opponent_t())/500.f)
+ ), 3.f);
+ get_color(dst, z_t()) =
+ 1.08883f * powf((p -
+ (get_color(src, b_color_opponent_t())/200.f)
+ ), 3.f);
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief XYZ to LAB
+/// \note I assume \c xyz_t
+template <>
+struct default_color_converter_impl< xyz_t, lab_t >
+{
+private:
+ /// \ref http://www.brucelindbloom.com/index.html?Eqn_XYZ_to_Lab.html
+ BOOST_FORCEINLINE
+ float32_t forward_companding(float32_t value) const
+ {
+ if (value > 216.f/24389.f)
+ {
+ return powf(value, 1.f/3.f);
+ }
+ else
+ {
+ return ((24389.f/27.f * value + 16.f)/116.f);
+ }
+ }
+
+public:
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst ) const
+ {
+ using namespace lab_color_space;
+
+ float32_t f_y =
+ forward_companding(
+ channel_convert<float32_t>(
+ get_color(src, xyz_color_space::y_t())
+ )
+ // / 1.f
+ );
+
+ float32_t f_x =
+ forward_companding(
+ channel_convert<float32_t>(
+ get_color(src, xyz_color_space::x_t())
+ )
+ * (1.f / 0.95047f) // if the compiler is smart, it should
+ // precalculate this, no?
+ );
+
+ float32_t f_z =
+ forward_companding(
+ channel_convert<float32_t>(
+ get_color(src, xyz_color_space::z_t())
+ )
+ * (1.f / 1.08883f) // if the compiler is smart, it should
+ // precalculate this, no?
+ );
+
+ get_color(dst, luminance_t()) =
+ 116.f * f_y - 16.f;
+
+ get_color(dst, a_color_opponent_t()) =
+ 500.f * (f_x - f_y);
+
+ get_color(dst, b_color_opponent_t()) =
+ 200.f * (f_y - f_z);
+ }
+};
+
+
+/// \ingroup ColorConvert
+/// \brief RGB to LAB
+template <>
+struct default_color_converter_impl< rgb_t, lab_t >
+{
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst ) const
+ {
+ using namespace lab_color_space;
+
+ xyz32f_pixel_t xyz32f_temp_pixel;
+ default_color_converter_impl<rgb_t, xyz_t>()(src, xyz32f_temp_pixel);
+ default_color_converter_impl<xyz_t, lab_t>()(xyz32f_temp_pixel, dst);
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief LAB to RGB
+template <>
+struct default_color_converter_impl<lab_t,rgb_t>
+{
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst) const
+ {
+ using namespace lab_color_space;
+
+ xyz32f_pixel_t xyz32f_temp_pixel;
+ default_color_converter_impl<lab_t, xyz_t>()(src, xyz32f_temp_pixel);
+ default_color_converter_impl<xyz_t, rgb_t>()(xyz32f_temp_pixel, dst);
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_LAB_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces/xyz.hpp b/boost/gil/extension/toolbox/color_spaces/xyz.hpp
new file mode 100644
index 0000000000..a9973adf82
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces/xyz.hpp
@@ -0,0 +1,157 @@
+/*
+ Copyright 2012 Chung-Lin Wen, Davide Anastasia
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_XYZ_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_XYZ_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file xyz.hpp
+/// \brief Support for CIE XYZ color space
+/// \author Chung-Lin Wen, Davide Anastasia \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/typedefs.hpp>
+
+namespace boost{ namespace gil {
+
+/// \addtogroup ColorNameModel
+/// \{
+namespace xyz_color_space
+{
+/// \brief x Color Component
+struct x_t {};
+/// \brief y Color Component
+struct y_t {};
+/// \brief z Color Component
+struct z_t {};
+}
+/// \}
+
+/// \ingroup ColorSpaceModel
+typedef mpl::vector3< xyz_color_space::x_t
+ , xyz_color_space::y_t
+ , xyz_color_space::z_t
+ > xyz_t;
+
+/// \ingroup LayoutModel
+typedef layout<xyz_t> xyz_layout_t;
+
+GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, xyz)
+
+/// \ingroup ColorConvert
+/// \brief RGB to XYZ
+/// <a href="http://www.brucelindbloom.com/index.html?Eqn_RGB_XYZ_Matrix.html">Link</a>
+/// \note rgb_t is assumed to be sRGB D65
+template <>
+struct default_color_converter_impl< rgb_t, xyz_t >
+{
+private:
+ BOOST_FORCEINLINE
+ float32_t inverse_companding(float32_t sample) const
+ {
+ if ( sample > 0.04045f )
+ {
+ return powf((( sample + 0.055f ) / 1.055f ), 2.4f);
+ }
+ else
+ {
+ return ( sample / 12.92f );
+ }
+ }
+
+public:
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst ) const
+ {
+ using namespace xyz_color_space;
+
+ float32_t red(
+ inverse_companding(
+ channel_convert<float32_t>(get_color(src, red_t()))));
+ float32_t green(
+ inverse_companding(
+ channel_convert<float32_t>(get_color(src, green_t()))));
+ float32_t blue(
+ inverse_companding(
+ channel_convert<float32_t>(get_color(src, blue_t()))));
+
+ get_color( dst, x_t() ) =
+ red * 0.4124564f +
+ green * 0.3575761f +
+ blue * 0.1804375f;
+ get_color( dst, y_t() ) =
+ red * 0.2126729f +
+ green * 0.7151522f +
+ blue * 0.0721750f;
+ get_color( dst, z_t() ) =
+ red * 0.0193339f +
+ green * 0.1191920f +
+ blue * 0.9503041f;
+ }
+};
+
+/// \ingroup ColorConvert
+/// \brief XYZ to RGB
+template <>
+struct default_color_converter_impl<xyz_t,rgb_t>
+{
+private:
+ BOOST_FORCEINLINE
+ float32_t companding(float32_t sample) const
+ {
+ if ( sample > 0.0031308f )
+ {
+ return ( 1.055f * powf( sample, 1.f/2.4f ) - 0.055f );
+ }
+ else
+ {
+ return ( 12.92f * sample );
+ }
+ }
+
+public:
+ template <typename P1, typename P2>
+ void operator()( const P1& src, P2& dst) const
+ {
+ using namespace xyz_color_space;
+
+ // Note: ideally channel_convert should be compiled out, because xyz_t
+ // is float32_t natively only
+ float32_t x( channel_convert<float32_t>( get_color( src, x_t() ) ) );
+ float32_t y( channel_convert<float32_t>( get_color( src, y_t() ) ) );
+ float32_t z( channel_convert<float32_t>( get_color( src, z_t() ) ) );
+
+ get_color(dst,red_t()) =
+ channel_convert<typename color_element_type<P2, red_t>::type>(
+ companding( x * 3.2404542f +
+ y * -1.5371385f +
+ z * -0.4985314f )
+ );
+ get_color(dst,green_t()) =
+ channel_convert<typename color_element_type<P2, green_t>::type>(
+ companding( x * -0.9692660f +
+ y * 1.8760108f +
+ z * 0.0415560f )
+ );
+ get_color(dst,blue_t()) =
+ channel_convert<typename color_element_type<P2, blue_t>::type>(
+ companding( x * 0.0556434f +
+ y * -0.2040259f +
+ z * 1.0572252f )
+ );
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_XYZ_HPP
diff --git a/boost/gil/extension/toolbox/color_spaces/ycbcr.hpp b/boost/gil/extension/toolbox/color_spaces/ycbcr.hpp
new file mode 100644
index 0000000000..e8e282f6a5
--- /dev/null
+++ b/boost/gil/extension/toolbox/color_spaces/ycbcr.hpp
@@ -0,0 +1,253 @@
+/*
+ Copyright 2013 Juan V. Puertos G-Cluster, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_YCBCR_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_YCBCR_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file ycbcr.hpp
+/// \brief Support for ycbcr ITU.BT-601 color space
+/// \author Juan V. Puertos G-Cluster 2013 \n
+///
+/// \date 2013 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <cstdint>
+#include <boost/algorithm/clamp.hpp>
+#include <boost/mpl/range_c.hpp>
+#include <boost/mpl/vector_c.hpp>
+#include <boost/gil/gil_all.hpp>
+
+#include <boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp>
+
+namespace boost{ namespace gil {
+
+/// \addtogroup ColorNameModel
+/// \{
+namespace ycbcr_601_color_space
+{
+/// \brief Luminance
+struct y_t {};
+/// \brief Blue chrominance component
+struct cb_t {};
+/// \brief Red chrominance component
+struct cr_t {};
+}
+
+namespace ycbcr_709_color_space
+{
+/// \brief Luminance
+struct y_t {};
+/// \brief Blue chrominance component
+struct cb_t {};
+/// \brief Red chrominance component
+struct cr_t {};
+}
+/// \}
+
+/// \ingroup ColorSpaceModel
+typedef boost::mpl::vector3< ycbcr_601_color_space::y_t, ycbcr_601_color_space::cb_t, ycbcr_601_color_space::cr_t > ycbcr_601__t;
+typedef boost::mpl::vector3< ycbcr_709_color_space::y_t, ycbcr_709_color_space::cb_t, ycbcr_709_color_space::cr_t > ycbcr_709__t;
+
+/// \ingroup LayoutModel
+typedef boost::gil::layout<ycbcr_601__t> ycbcr_601__layout_t;
+typedef boost::gil::layout<ycbcr_709__t> ycbcr_709__layout_t;
+
+//The channel depth is ALWAYS 8bits ofr YCbCr!
+GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, ycbcr_601_)
+GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, ycbcr_709_)
+
+/*
+ * 601 Source: http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
+ * 709 Source: http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.709_conversion
+ * (using values coming directly from ITU-R BT.601 recommendation)
+ * (using values coming directly from ITU-R BT.709 recommendation)
+ */
+
+/**
+* @brief Convert YCbCr ITU.BT-601 to RGB.
+*/
+template<>
+struct default_color_converter_impl<ycbcr_601__t, rgb_t>
+{
+ // Note: the RGB_t channels range can be set later on by the users. We dont want to cast to uint8_t or anything here.
+ template < typename SRCP, typename DSTP >
+ void operator()( const SRCP& src, DSTP& dst ) const
+ {
+ typedef typename channel_type< DSTP >::type dst_channel_t;
+ convert( src, dst
+ , typename boost::is_same< typename mpl::int_< sizeof( dst_channel_t ) >::type
+ , typename mpl::int_<1>::type
+ >::type()
+ );
+ }
+
+private:
+
+ // optimization for bit8 channels
+ template< typename Src_Pixel
+ , typename Dst_Pixel
+ >
+ void convert( const Src_Pixel& src
+ , Dst_Pixel& dst
+ , mpl::true_ // is 8 bit channel
+ ) const
+ {
+ using namespace boost::algorithm;
+ using namespace ycbcr_601_color_space;
+
+ typedef typename channel_type< Src_Pixel >::type src_channel_t;
+ typedef typename channel_type< Dst_Pixel >::type dst_channel_t;
+
+ src_channel_t y = channel_convert<src_channel_t>( get_color(src, y_t()));
+ src_channel_t cb = channel_convert<src_channel_t>( get_color(src, cb_t()));
+ src_channel_t cr = channel_convert<src_channel_t>( get_color(src, cr_t()));
+
+ // The intermediate results of the formulas require at least 16bits of precission.
+ std::int_fast16_t c = y - 16;
+ std::int_fast16_t d = cb - 128;
+ std::int_fast16_t e = cr - 128;
+ std::int_fast16_t red = clamp((( 298 * c + 409 * e + 128) >> 8), 0, 255);
+ std::int_fast16_t green = clamp((( 298 * c - 100 * d - 208 * e + 128) >> 8), 0, 255);
+ std::int_fast16_t blue = clamp((( 298 * c + 516 * d + 128) >> 8), 0, 255);
+
+ get_color( dst, red_t() ) = (dst_channel_t) red;
+ get_color( dst, green_t() ) = (dst_channel_t) green;
+ get_color( dst, blue_t() ) = (dst_channel_t) blue;
+ }
+
+
+ template< typename Src_Pixel
+ , typename Dst_Pixel
+ >
+ void convert( const Src_Pixel& src
+ , Dst_Pixel& dst
+ , mpl::false_ // is 8 bit channel
+ ) const
+ {
+ using namespace boost::algorithm;
+ using namespace ycbcr_601_color_space;
+
+ typedef typename channel_type< Dst_Pixel >::type dst_channel_t;
+
+ double y = get_color( src, y_t() );
+ double cb = get_color( src, cb_t() );
+ double cr = get_color( src, cr_t() );
+
+ get_color(dst, red_t()) = (dst_channel_t) clamp( 1.6438 * ( y - 16.0 ) + 1.5960 * ( cr -128.0 )
+ , 0.0
+ , 255.0
+ );
+
+ get_color(dst, green_t()) = (dst_channel_t) clamp( 1.6438 * ( y - 16.0 ) - 0.3917 * ( cb - 128.0 ) + 0.8129 * ( cr -128.0 )
+ , 0.0
+ , 255.0
+ );
+
+ get_color(dst, blue_t()) = (dst_channel_t) clamp( 1.6438 * ( y - 16.0 ) - 2.0172 * ( cb -128.0 )
+ , 0.0
+ , 255.0
+ );
+ }
+};
+
+/*
+ * Source: http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
+ * digital Y′CbCr derived from digital R'dG'dB'd 8 bits per sample, each using the full range.
+ * with NO footroom wither headroom.
+ */
+/**
+* @brief Convert RGB to YCbCr ITU.BT-601.
+*/
+template<>
+struct default_color_converter_impl<rgb_t, ycbcr_601__t>
+{
+ template < typename SRCP, typename DSTP >
+ void operator()( const SRCP& src, DSTP& dst ) const
+ {
+ using namespace ycbcr_601_color_space;
+
+ typedef typename channel_type< SRCP >::type src_channel_t;
+ typedef typename channel_type< DSTP >::type dst_channel_t;
+
+ src_channel_t red = channel_convert<src_channel_t>( get_color(src, red_t()));
+ src_channel_t green = channel_convert<src_channel_t>( get_color(src, green_t()));
+ src_channel_t blue = channel_convert<src_channel_t>( get_color(src, blue_t()));
+
+ double y = 16.0 + 0.2567 * red + 0.5041 * green + 0.0979 * blue;
+ double cb = 128.0 - 0.1482 * red - 0.2909 * green + 0.4392 * blue;
+ double cr = 128.0 + 0.4392 * red - 0.3677 * green - 0.0714 * blue;
+
+ get_color( dst, y_t() ) = (dst_channel_t) y;
+ get_color( dst, cb_t() ) = (dst_channel_t) cb;
+ get_color( dst, cr_t() ) = (dst_channel_t) cr;
+ }
+};
+
+/**
+* @brief Convert RGB to YCbCr ITU.BT-709.
+*/
+template<>
+struct default_color_converter_impl<rgb_t, ycbcr_709__t>
+{
+ template < typename SRCP, typename DSTP >
+ void operator()( const SRCP& src, DSTP& dst ) const
+ {
+ using namespace ycbcr_709_color_space;
+
+ typedef typename channel_type< SRCP >::type src_channel_t;
+ typedef typename channel_type< DSTP >::type dst_channel_t;
+
+ src_channel_t red = channel_convert<src_channel_t>( get_color(src, red_t()));
+ src_channel_t green = channel_convert<src_channel_t>( get_color(src, green_t()));
+ src_channel_t blue = channel_convert<src_channel_t>( get_color(src, blue_t()));
+
+ double y = 0.299 * red + 0.587 * green + 0.114 * blue;
+ double cb = 128.0 - 0.168736 * red - 0.331264 * green + 0.5 * blue;
+ double cr = 128.0 + 0.5 * red - 0.418688 * green - 0.081312 * blue;
+
+ get_color( dst, y_t() ) = (dst_channel_t) y;
+ get_color( dst, cb_t() ) = (dst_channel_t) cb;
+ get_color( dst, cr_t() ) = (dst_channel_t) cr;
+ }
+};
+
+/**
+* @brief Convert RGB to YCbCr ITU.BT-709.
+*/
+template<>
+struct default_color_converter_impl<ycbcr_709__t, rgb_t>
+{
+ template < typename SRCP, typename DSTP >
+ void operator()( const SRCP& src, DSTP& dst ) const
+ {
+ using namespace ycbcr_709_color_space;
+
+ typedef typename channel_type< SRCP >::type src_channel_t;
+ typedef typename channel_type< DSTP >::type dst_channel_t;
+
+ src_channel_t y = channel_convert<src_channel_t>( get_color(src, y_t()) );
+ src_channel_t cb_clipped = channel_convert<src_channel_t>( get_color(src, cb_t()) - 128 );
+ src_channel_t cr_clipped = channel_convert<src_channel_t>( get_color(src, cr_t()) - 128 );
+
+ double red = y + 1.042 * cr_clipped;
+ double green = y - 0.34414 * cb_clipped - 0.71414 * cr_clipped;
+ double blue = y + 1.772 * cb_clipped;
+
+ get_color( dst, red_t() ) = (dst_channel_t) red;
+ get_color( dst, green_t() ) = (dst_channel_t) green;
+ get_color( dst, blue_t() ) = (dst_channel_t) blue;
+ }
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif
diff --git a/boost/gil/extension/io/dynamic_io.hpp b/boost/gil/extension/toolbox/dynamic_images.hpp
index 9f88e50d44..f0993599eb 100644
--- a/boost/gil/extension/io/dynamic_io.hpp
+++ b/boost/gil/extension/toolbox/dynamic_images.hpp
@@ -1,6 +1,6 @@
/*
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).
@@ -9,24 +9,30 @@
*/
/*************************************************************************************************/
-#ifndef GIL_DYNAMIC_IO_H
-#define GIL_DYNAMIC_IO_H
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP
-/// \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
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file dynamic_images.hpp
+/// \brief Generic io functions for dealing with dynamic images.
+/// \author Hailin Jin, Lubomir Bourdev, and Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
#include <boost/mpl/at.hpp>
#include <boost/mpl/size.hpp>
-#include "../../gil_config.hpp"
-#include "io_error.hpp"
-#include "../dynamic_image/any_image.hpp"
+#include <boost/gil/gil_config.hpp>
+#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
namespace boost { namespace gil {
+// need this for various meta functions.
+struct any_image_pixel_t {};
+struct any_image_channel_t {};
+struct any_image_color_space_t {};
+
namespace detail {
template <long N>
@@ -55,8 +61,31 @@ class dynamic_io_fnobj {
template <typename View>
void apply(const View& view,mpl::true_ ) {_op->apply(view);}
+
+ template <typename View, typename Info >
+ void apply( const View& view
+ , const Info& info
+ , const mpl::true_
+ )
+ {
+ _op->apply( view, info );
+ }
+
template <typename View>
- void apply(const View& view,mpl::false_) {io_error("dynamic_io: unsupported view type for the given file format");}
+ void apply(const View& /* view */ ,mpl::false_)
+ {
+ throw std::ios_base::failure( "dynamic_io: unsupported view type for the given file format" );
+ }
+
+ template <typename View, typename Info >
+ void apply( const View& /* view */
+ , const Info& /* info */
+ , const mpl::false_
+ )
+ {
+ throw std::ios_base::failure( "dynamic_io: unsupported view type for the given file format" );
+ }
+
public:
dynamic_io_fnobj(OpClass* op) : _op(op) {}
@@ -64,6 +93,16 @@ public:
template <typename View>
void operator()(const View& view) {apply(view,typename IsSupported::template apply<View>::type());}
+
+ template< typename View, typename Info >
+ void operator()(const View& view, const Info& info )
+ {
+ apply( view
+ , info
+ , typename IsSupported::template apply< View >::type()
+ );
+ }
+
};
} // namespace detail
@@ -75,6 +114,13 @@ inline bool construct_matched(any_image<Images>& im,Pred pred) {
return detail::construct_matched_t<mpl::size<Images>::value>::apply(im,pred);
}
+template<>
+struct color_space_type< any_image_pixel_t >
+{
+ typedef any_image_color_space_t type;
+};
+
+
} } // namespace boost::gil
-#endif
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_DYNAMIC_IMAGES_HPP
diff --git a/boost/gil/extension/toolbox/image_types.hpp b/boost/gil/extension/toolbox/image_types.hpp
new file mode 100644
index 0000000000..94d52fad63
--- /dev/null
+++ b/boost/gil/extension/toolbox/image_types.hpp
@@ -0,0 +1,24 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IMAGE_TYPES_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IMAGE_TYPES_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file image_types.hpp
+/// \brief Image Types for toolbox extension.
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/toolbox/image_types/indexed_image.hpp>
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IMAGE_TYPES_HPP
diff --git a/boost/gil/extension/toolbox/image_types/indexed_image.hpp b/boost/gil/extension/toolbox/image_types/indexed_image.hpp
new file mode 100644
index 0000000000..c413f67533
--- /dev/null
+++ b/boost/gil/extension/toolbox/image_types/indexed_image.hpp
@@ -0,0 +1,392 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file indexed_image.hpp
+/// \brief Indexed Image extension
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/gil/image.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
+
+
+namespace boost{ namespace gil {
+
+typedef boost::gil::point2< std::ptrdiff_t > point_t;
+
+template< typename Locator >
+struct get_pixel_type_locator : mpl::if_< typename is_bit_aligned< typename Locator::value_type >::type
+ , typename Locator::reference
+ , typename Locator::value_type
+ > {};
+
+// used for virtual locator
+template< typename IndicesLoc
+ , typename PaletteLoc
+ >
+struct indexed_image_deref_fn_base
+{
+ typedef IndicesLoc indices_locator_t;
+ typedef PaletteLoc palette_locator_t;
+ //typedef typename get_pixel_type_locator< indices_locator_t >::type index_t;
+
+ typedef indexed_image_deref_fn_base const_t;
+ typedef typename PaletteLoc::value_type value_type;
+ typedef value_type reference;
+ typedef value_type const_reference;
+ typedef point_t argument_type;
+ typedef reference result_type;
+
+ static const bool is_mutable = false;
+
+ indexed_image_deref_fn_base() {}
+
+ indexed_image_deref_fn_base( const indices_locator_t& indices_loc
+ , const palette_locator_t& palette_loc
+ )
+ : _indices_loc( indices_loc )
+ , _palette_loc( palette_loc )
+ {}
+
+ void set_indices( const indices_locator_t& indices_loc ) { _indices_loc = indices_loc; }
+ void set_palette( const palette_locator_t& palette_loc ) { _palette_loc = palette_loc; }
+
+ const indices_locator_t& indices() const { return _indices_loc; }
+ const palette_locator_t& palette() const { return _palette_loc; }
+
+protected:
+
+ indices_locator_t _indices_loc;
+ palette_locator_t _palette_loc;
+};
+
+
+// used for virtual locator
+template< typename IndicesLoc
+ , typename PaletteLoc
+ , typename Enable = void // there is specialization for integral indices
+ >
+struct indexed_image_deref_fn : indexed_image_deref_fn_base< IndicesLoc
+ , PaletteLoc
+ >
+{
+ typedef indexed_image_deref_fn_base< IndicesLoc
+ , PaletteLoc
+ > base_t;
+
+
+ indexed_image_deref_fn()
+ : base_t()
+ {}
+
+ indexed_image_deref_fn( const typename base_t::indices_locator_t& indices_loc
+ , const typename base_t::palette_locator_t& palette_loc
+ )
+ : base_t( indices_loc
+ , palette_loc
+ )
+ {}
+
+ typename base_t::result_type operator()( const point_t& p ) const
+ {
+ return * this->_palette_loc.xy_at( at_c<0>( *this->_indices_loc.xy_at( p )), 0 );
+ }
+};
+
+
+template< typename IndicesLoc
+ , typename PaletteLoc
+ >
+struct indexed_image_deref_fn< IndicesLoc
+ , PaletteLoc
+ , typename boost::enable_if< boost::is_integral< typename IndicesLoc::value_type > >::type
+ > : indexed_image_deref_fn_base< IndicesLoc
+ , PaletteLoc
+ >
+{
+ typedef indexed_image_deref_fn_base< IndicesLoc
+ , PaletteLoc
+ > base_t;
+
+ indexed_image_deref_fn()
+ : base_t()
+ {}
+
+ indexed_image_deref_fn( const typename base_t::indices_locator_t& indices_loc
+ , const typename base_t::palette_locator_t& palette_loc
+ )
+ : base_t( indices_loc
+ , palette_loc
+ )
+ {}
+
+ typename base_t::result_type operator()( const point_t& p ) const
+ {
+ return *this->_palette_loc.xy_at( *this->_indices_loc.xy_at( p ), 0 );
+ }
+};
+
+template< typename IndicesLoc
+ , typename PaletteLoc
+ >
+struct indexed_image_locator_type
+{
+ typedef virtual_2d_locator< indexed_image_deref_fn< IndicesLoc
+ , PaletteLoc
+ >
+ , false
+ > type;
+};
+
+template< typename Locator > // indexed_image_locator_type< ... >::type
+class indexed_image_view : public image_view< Locator >
+{
+public:
+
+ typedef typename Locator::deref_fn_t deref_fn_t;
+ typedef typename deref_fn_t::indices_locator_t indices_locator_t;
+ typedef typename deref_fn_t::palette_locator_t palette_locator_t;
+
+ typedef indexed_image_view< Locator > const_t;
+
+ typedef image_view< indices_locator_t > indices_view_t;
+ typedef image_view< palette_locator_t > palette_view_t;
+
+ indexed_image_view()
+ : image_view< Locator >()
+ , _num_colors( 0 )
+ {}
+
+ indexed_image_view( const point_t& dimensions
+ , std::size_t num_colors
+ , const Locator& locator
+ )
+ : image_view< Locator >( dimensions, locator )
+ , _num_colors( num_colors )
+ {}
+
+ template< typename IndexedView >
+ indexed_image_view( const IndexedView& iv )
+ : image_view< Locator >( iv )
+ , _num_colors( iv._num_colors )
+ {}
+
+ std::size_t num_colors() const { return _num_colors; }
+
+
+ const indices_locator_t& indices() const { return get_deref_fn().indices(); }
+ const palette_locator_t& palette() const { return get_deref_fn().palette(); }
+
+ indices_view_t get_indices_view() const { return indices_view_t(this->dimensions(), indices() );}
+ palette_view_t get_palette_view() const { return palette_view_t(point_t(num_colors(), 1), palette());}
+
+private:
+
+ const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
+
+private:
+
+ template< typename Locator2 > friend class indexed_image_view;
+
+ std::size_t _num_colors;
+};
+
+// build an indexed_image_view from two views
+template<typename Index_View, typename Palette_View>
+indexed_image_view
+<
+ typename indexed_image_locator_type
+ <
+ typename Index_View::locator
+ , typename Palette_View::locator
+ >::type
+>
+ view(Index_View iv, Palette_View pv)
+{
+ typedef indexed_image_view<
+ typename indexed_image_locator_type<
+ typename Index_View::locator
+ , typename Palette_View::locator
+ >::type
+ > view_t;
+
+ typedef indexed_image_deref_fn<
+ typename Index_View::locator
+ , typename Palette_View::locator
+ > defer_fn_t;
+
+ return view_t(
+ iv.dimensions()
+ , pv.dimensions().x
+ , typename view_t::locator(point_t(0, 0), point_t(1, 1), defer_fn_t(iv.xy_at(0, 0), pv.xy_at(0, 0)))
+ );
+}
+
+template< typename Index
+ , typename Pixel
+ , typename IndicesAllocator = std::allocator< unsigned char >
+ , typename PalleteAllocator = std::allocator< unsigned char >
+ >
+class indexed_image
+{
+public:
+
+ typedef image< Index, false, IndicesAllocator > indices_t;
+ typedef image< Pixel, false, PalleteAllocator > palette_t;
+
+ typedef typename indices_t::view_t indices_view_t;
+ typedef typename palette_t::view_t palette_view_t;
+
+ typedef typename indices_t::const_view_t indices_const_view_t;
+ typedef typename palette_t::const_view_t palette_const_view_t;
+
+ typedef typename indices_view_t::locator indices_locator_t;
+ typedef typename palette_view_t::locator palette_locator_t;
+
+ typedef typename indexed_image_locator_type< indices_locator_t
+ , palette_locator_t
+ >::type locator_t;
+
+ typedef typename indices_t::coord_t x_coord_t;
+ typedef typename indices_t::coord_t y_coord_t;
+
+
+ typedef indexed_image_view< locator_t > view_t;
+ typedef typename view_t::const_t const_view_t;
+
+ indexed_image( const x_coord_t width = 0
+ , const y_coord_t height = 0
+ , const std::size_t num_colors = 1
+ , const std::size_t indices_alignment = 0
+ , const std::size_t palette_alignment = 0
+ )
+ : _indices( width , height, indices_alignment, IndicesAllocator() )
+ , _palette( num_colors, 1, palette_alignment, PalleteAllocator() )
+ {
+ init( point_t( width, height ), num_colors );
+ }
+
+ indexed_image( const point_t& dimensions
+ , const std::size_t num_colors = 1
+ , const std::size_t indices_alignment = 0
+ , const std::size_t palette_alignment = 0
+ )
+ : _indices( dimensions, indices_alignment, IndicesAllocator() )
+ , _palette( num_colors, 1, palette_alignment, PalleteAllocator() )
+ {
+ init( dimensions, num_colors );
+ }
+
+ indexed_image( const indexed_image& img )
+ : _indices( img._indices )
+ , _palette( img._palette )
+ {}
+
+ template <typename Pixel2, typename Index2>
+ indexed_image( const indexed_image< Pixel2, Index2 >& img )
+ {
+ _indices = img._indices;
+ _palette = img._palette;
+ }
+
+ indexed_image& operator= ( const indexed_image& img )
+ {
+ _indices = img._indices;
+ _palette = img._palette;
+
+ return *this;
+ }
+
+ indices_const_view_t get_indices_const_view() const { return static_cast< indices_const_view_t >( _view.get_indices_view()); }
+ palette_const_view_t get_palette_const_view() const { return static_cast< palette_const_view_t >( _view.get_palette_view()); }
+
+ indices_view_t get_indices_view() { return _view.get_indices_view(); }
+ palette_view_t get_palette_view() { return _view.get_palette_view(); }
+
+public:
+
+ view_t _view;
+
+private:
+
+ void init( const point_t& dimensions
+ , const std::size_t num_colors
+ )
+ {
+ typedef indexed_image_deref_fn< indices_locator_t
+ , palette_locator_t
+ > defer_fn_t;
+
+ defer_fn_t deref_fn( view( _indices ).xy_at( 0, 0 )
+ , view( _palette ).xy_at( 0, 0 )
+ );
+
+ locator_t locator( point_t( 0, 0 ) // p
+ , point_t( 1, 1 ) // step
+ , deref_fn
+ );
+
+ _view = view_t( dimensions
+ , num_colors
+ , locator
+ );
+ }
+
+private:
+
+ indices_t _indices;
+ palette_t _palette;
+};
+
+template< typename Index
+ , typename Pixel
+ >
+inline
+const typename indexed_image< Index, Pixel >::view_t& view( indexed_image< Index, Pixel >& img )
+{
+ return img._view;
+}
+
+template< typename Index
+ , typename Pixel
+ >
+inline
+const typename indexed_image< Index, Pixel >::const_view_t const_view( indexed_image< Index, Pixel >& img )
+{
+ return static_cast< const typename indexed_image< Index, Pixel >::const_view_t>( img._view );
+}
+
+// Whole image has one color and all indices are set to 0.
+template< typename Locator
+ , typename Value
+ >
+void fill_pixels( const indexed_image_view< Locator >& view
+ , const Value& value
+ )
+{
+ typedef indexed_image_view< Locator > view_t;
+
+ fill_pixels( view.get_indices_view(), typename view_t::indices_view_t::value_type( 0 ));
+ *view.get_palette_view().begin() = value;
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_INDEXED_IMAGE_HPP
diff --git a/boost/gil/extension/toolbox/image_types/subchroma_image.hpp b/boost/gil/extension/toolbox/image_types/subchroma_image.hpp
new file mode 100644
index 0000000000..e98abe0f1c
--- /dev/null
+++ b/boost/gil/extension/toolbox/image_types/subchroma_image.hpp
@@ -0,0 +1,577 @@
+/*
+ Copyright 2013 Christian Henning and Juan V. Puertos
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file subchroma_image.hpp
+/// \brief Subchroma Image extension
+/// \author Christian Henning and Juan V. Puertos\n
+///
+/// \date 2013 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/divides.hpp>
+#include <boost/mpl/equal_to.hpp>
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/or.hpp>
+#include <boost/mpl/vector_c.hpp>
+
+#include <boost/gil/image.hpp>
+
+namespace boost{ namespace gil {
+
+typedef boost::gil::point2< std::ptrdiff_t > point_t;
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \class subchroma_image_deref_fn
+/// \ingroup PixelLocatorModel PixelBasedModel
+/// \brief Used for virtual_2D_locator
+///
+////////////////////////////////////////////////////////////////////////////////////////
+template< typename Locator
+ , typename Factors
+ >
+struct subchroma_image_deref_fn
+{
+ typedef gray8_view_t::locator plane_locator_t;
+
+ typedef subchroma_image_deref_fn const_t;
+ typedef typename Locator::value_type value_type;
+ typedef value_type reference;
+ typedef value_type const_reference;
+ typedef point_t argument_type;
+ typedef reference result_type;
+
+ static const bool is_mutable = false;
+
+ /// default constructor
+ subchroma_image_deref_fn() {}
+
+ /// constructor
+ subchroma_image_deref_fn( const plane_locator_t& y_locator
+ , const plane_locator_t& v_locator
+ , const plane_locator_t& u_locator
+ )
+ : _y_locator( y_locator )
+ , _v_locator( v_locator )
+ , _u_locator( u_locator )
+ {}
+
+ /// operator()
+ typename result_type operator()( const point_t& p ) const
+ {
+ typedef Scaling_Factors< mpl::at_c< Factors, 0 >::type::value
+ , mpl::at_c< Factors, 1 >::type::value
+ , mpl::at_c< Factors, 2 >::type::value
+ > scaling_factors_t;
+
+ plane_locator_t y = _y_locator.xy_at( p );
+ plane_locator_t v = _v_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
+ plane_locator_t u = _u_locator.xy_at( p.x / scaling_factors_t::ss_X, p.y / scaling_factors_t::ss_X );
+
+ return value_type( at_c< 0 >( *y )
+ , at_c< 0 >( *v )
+ , at_c< 0 >( *u )
+ );
+ }
+
+ ///
+ const plane_locator_t& y_locator() const { return _y_locator; }
+ const plane_locator_t& v_locator() const { return _v_locator; }
+ const plane_locator_t& u_locator() const { return _u_locator; }
+
+private:
+
+ plane_locator_t _y_locator;
+ plane_locator_t _v_locator;
+ plane_locator_t _u_locator;
+};
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \class subchroma_image_locator_type
+/// \ingroup PixelLocatorModel PixelBasedModel
+/// \brief
+///
+////////////////////////////////////////////////////////////////////////////////////////
+template< typename Locator
+ , typename Factors
+ >
+struct subchroma_image_locator
+{
+ typedef virtual_2d_locator< subchroma_image_deref_fn< Locator
+ , Factors
+ > // Deref
+ , false // IsTransposed
+ > type;
+};
+
+
+/////////////////////////////
+// PixelBasedConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct channel_type< subchroma_image_locator< Locator, Factors > >
+ : public channel_type< typename subchroma_image_locator< Locator, Factors >::type > {};
+
+template < typename Locator, typename Factors >
+struct color_space_type< subchroma_image_locator< Locator, Factors > >
+ : public color_space_type< typename subchroma_image_locator< Locator, Factors >::type > {};
+
+template < typename Locator, typename Factors >
+struct channel_mapping_type< subchroma_image_locator< Locator, Factors > >
+ : public channel_mapping_type< typename subchroma_image_locator< Locator, Factors >::type > {};
+
+template < typename Locator, typename Factors >
+struct is_planar< subchroma_image_locator< Locator, Factors > >
+ : public is_planar< typename subchroma_image_locator< Locator, Factors >::type > {};
+
+/////////////////////////////
+// HasDynamicXStepTypeConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct dynamic_x_step_type< subchroma_image_locator< Locator, Factors > >
+{
+ typedef typename subchroma_image_locator< Locator, Factors >::type type;
+};
+
+/////////////////////////////
+// HasDynamicYStepTypeConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct dynamic_y_step_type< subchroma_image_locator< Locator, Factors > >
+{
+ typedef typename subchroma_image_locator< Locator, Factors >::type type;
+};
+
+/////////////////////////////
+// HasTransposedTypeConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct transposed_type< subchroma_image_locator< Locator, Factors > >
+{
+ typedef typename subchroma_image_locator< Locator, Factors >::type type;
+};
+
+//////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \class subchroma_image_view
+/// \ingroup ImageViewModel PixelBasedModel
+/// \brief A lightweight object that interprets a subchroma image.
+///
+////////////////////////////////////////////////////////////////////////////////////////
+template< typename Locator
+ , typename Factors = mpl::vector_c< int, 4, 4, 4 >
+ >
+class subchroma_image_view : public image_view< Locator >
+{
+public:
+
+ typedef typename Locator locator;
+ typedef typename locator::deref_fn_t deref_fn_t;
+ typedef typename deref_fn_t::plane_locator_t plane_locator_t;
+
+
+ typedef subchroma_image_view const_t;
+
+ typedef image_view< plane_locator_t > plane_view_t;
+
+ /// default constructor
+ subchroma_image_view()
+ : image_view< Locator >()
+ {}
+
+ /// constructor
+ subchroma_image_view( const point_t& y_dimensions
+ , const point_t& v_dimensions
+ , const point_t& u_dimensions
+ , const Locator& locator
+ )
+ : image_view< Locator >( y_dimensions, locator )
+ , _y_dimensions( y_dimensions )
+ , _v_dimensions( v_dimensions )
+ , _u_dimensions( u_dimensions )
+ {}
+
+ /// copy constructor
+ template< typename Subchroma_View >
+ subchroma_image_view( const Subchroma_View& v )
+ : image_view< locator >( v )
+ {}
+
+ const point_t& v_ssfactors() const { return point_t( get_deref_fn().vx_ssfactor(), get_deref_fn().vx_ssfactor() ); }
+ const point_t& u_ssfactors() const { return point_t( get_deref_fn().ux_ssfactor(), get_deref_fn().ux_ssfactor() ); }
+
+ const point_t& y_dimension() const { return _y_dimensions; }
+ const point_t& v_dimension() const { return _v_dimensions; }
+ const point_t& u_dimension() const { return _u_dimensions; }
+
+ const plane_locator_t& y_plane() const { return get_deref_fn().y_locator(); }
+ const plane_locator_t& v_plane() const { return get_deref_fn().v_locator(); }
+ const plane_locator_t& u_plane() const { return get_deref_fn().u_locator(); }
+
+ const plane_view_t y_plane_view() const { return plane_view_t( _y_dimensions, y_plane() ); }
+ const plane_view_t v_plane_view() const { return plane_view_t( _v_dimensions, v_plane() ); }
+ const plane_view_t u_plane_view() const { return plane_view_t( _u_dimensions, u_plane() ); }
+
+
+private:
+
+ const deref_fn_t& get_deref_fn() const { return this->pixels().deref_fn(); }
+
+private:
+
+ template< typename Locator, typename Factors > friend class subchroma_image_view;
+
+ point_t _y_dimensions;
+ point_t _v_dimensions;
+ point_t _u_dimensions;
+};
+
+
+/////////////////////////////
+// PixelBasedConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct channel_type< subchroma_image_view< Locator, Factors > >
+ : public channel_type< Locator > {};
+
+template < typename Locator, typename Factors >
+struct color_space_type< subchroma_image_view< Locator, Factors > >
+ : public color_space_type< Locator > {};
+
+template < typename Locator, typename Factors >
+struct channel_mapping_type< subchroma_image_view< Locator, Factors > >
+ : public channel_mapping_type< Locator > {};
+
+template < typename Locator, typename Factors >
+struct is_planar< subchroma_image_view< Locator, Factors > >
+ : public is_planar< Locator > {};
+
+/////////////////////////////
+// HasDynamicXStepTypeConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct dynamic_x_step_type< subchroma_image_view< Locator, Factors > >
+{
+ typedef image_view< typename dynamic_x_step_type< Locator >::type > type;
+};
+
+/////////////////////////////
+// HasDynamicYStepTypeConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct dynamic_y_step_type< subchroma_image_view< Locator, Factors > >
+{
+ typedef image_view< typename dynamic_y_step_type< Locator >::type > type;
+};
+
+/////////////////////////////
+// HasTransposedTypeConcept
+/////////////////////////////
+
+template < typename Locator, typename Factors >
+struct transposed_type< subchroma_image_view< Locator, Factors > >
+{
+ typedef image_view< typename transposed_type< Locator >::type > type;
+};
+
+
+/////////////////////////////////////////////////////////////
+template< int J
+ , int a
+ , int b
+ >
+struct Scaling_Factors
+{
+ BOOST_STATIC_ASSERT(( mpl::equal_to< mpl::int_< J >, mpl::int_< 4 > >::type::value ));
+
+ BOOST_STATIC_ASSERT(( mpl::or_< mpl::equal_to< mpl::int_< a >, mpl::int_< 4 > >
+ , mpl::or_< mpl::equal_to< mpl::int_< a >, mpl::int_< 2 > >
+ , mpl::equal_to< mpl::int_< a >, mpl::int_< 1 > >
+ >
+ >::type::value
+ ));
+
+ BOOST_STATIC_ASSERT(( mpl::or_< mpl::equal_to< mpl::int_< b >, mpl::int_< 4 > >
+ , mpl::or_< mpl::equal_to< mpl::int_< b >, mpl::int_< 2 > >
+ , mpl::or_< mpl::equal_to< mpl::int_< b >, mpl::int_< 1 > >
+ , mpl::equal_to< mpl::int_< b >, mpl::int_< 0 > >
+ >
+ >
+ >::type::value
+ ));
+
+ BOOST_STATIC_CONSTANT( int, ss_X = ( mpl::divides< mpl::int_< J >
+ , mpl::int_< a >
+ >::type::value )
+ );
+
+ BOOST_STATIC_CONSTANT( int, ss_Y = ( mpl::if_< mpl::equal_to< mpl::int_< b >, mpl::int_< 0 > >
+ , mpl::int_< 2 >
+ , mpl::if_< mpl::equal_to< mpl::int_< a >, mpl::int_< b > >
+ , mpl::int_< 1 >
+ , mpl::int_< 4 >
+ >::type
+ >::type::value )
+ );
+};
+
+
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \ingroup ImageModel PixelBasedModel
+/// \brief container interface over image view. Models ImageConcept, PixelBasedConcept
+///
+/// A subchroma image holds a bunch of planes which don't need to have the same resolution.
+///
+////////////////////////////////////////////////////////////////////////////////////////
+template< typename Pixel
+ , typename Factors = mpl::vector_c< int, 4, 4, 4 >
+ , typename Allocator = std::allocator< unsigned char >
+ >
+class subchroma_image : public Scaling_Factors< mpl::at_c< Factors, 0 >::type::value
+ , mpl::at_c< Factors, 1 >::type::value
+ , mpl::at_c< Factors, 2 >::type::value
+ >
+{
+
+public:
+
+ typedef typename channel_type< Pixel >::type channel_t;
+ typedef pixel< channel_t, gray_layout_t> pixel_t;
+
+ typedef image< pixel_t, false, Allocator > plane_image_t;
+
+ typedef typename plane_image_t::view_t plane_view_t;
+ typedef typename plane_image_t::const_view_t plane_const_view_t;
+ typedef typename plane_view_t::locator plane_locator_t;
+
+ typedef typename view_type_from_pixel< Pixel >::type pixel_view_t;
+ typedef typename pixel_view_t::locator pixel_locator_t;
+
+ typedef typename subchroma_image_locator< pixel_locator_t
+ , Factors
+ >::type locator_t;
+
+ typedef typename plane_image_t::coord_t x_coord_t;
+ typedef typename plane_image_t::coord_t y_coord_t;
+
+ typedef subchroma_image_view< locator_t, Factors > view_t;
+ typedef typename view_t::const_t const_view_t;
+
+
+ /// constructor
+ subchroma_image( const x_coord_t y_width
+ , const y_coord_t y_height
+ )
+ : _y_plane( y_width, y_height, 0, Allocator() )
+ , _v_plane( y_width / ss_X, y_height / ss_Y, 0, Allocator() )
+ , _u_plane( y_width / ss_X, y_height / ss_Y, 0, Allocator() )
+ {
+ init();
+ }
+
+public:
+
+ view_t _view;
+
+private:
+
+ void init()
+ {
+ typedef subchroma_image_deref_fn< pixel_locator_t
+ , Factors
+ > defer_fn_t;
+
+ defer_fn_t deref_fn( view( _y_plane ).xy_at( 0, 0 )
+ , view( _v_plane ).xy_at( 0, 0 )
+ , view( _u_plane ).xy_at( 0, 0 )
+ );
+
+ // init a virtual_2d_locator
+ locator_t locator( point_t( 0, 0 ) // p
+ , point_t( 1, 1 ) // step
+ , deref_fn
+ );
+
+ _view = view_t( _y_plane.dimensions()
+ , _v_plane.dimensions()
+ , _u_plane.dimensions()
+ , locator
+ );
+ }
+
+
+private:
+
+ plane_image_t _y_plane;
+ plane_image_t _v_plane;
+ plane_image_t _u_plane;
+};
+
+
+/////////////////////////////
+// PixelBasedConcept
+/////////////////////////////
+
+template < typename Pixel, typename Factors, typename Alloc >
+struct channel_type< subchroma_image< Pixel, Factors, Alloc > >
+ : public channel_type< Pixel > {};
+
+template < typename Pixel, typename Factors, typename Alloc >
+struct color_space_type< subchroma_image< Pixel, Factors, Alloc > >
+ : public color_space_type< Pixel > {};
+
+template < typename Pixel, typename Factors, typename Alloc >
+struct channel_mapping_type< subchroma_image< Pixel, Factors, Alloc > >
+ : public channel_mapping_type< Pixel > {};
+
+template < typename Pixel, typename Factors, typename Alloc >
+struct is_planar< subchroma_image< Pixel, Factors, Alloc > >
+ : public mpl::bool_< false > {};
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/// \name view, const_view
+/// \brief Get an image view from an subchroma_image
+/// \ingroup ImageModel
+/// \brief Returns the non-constant-pixel view of an image
+/////////////////////////////////////////////////////////////////////////////////////////
+template< typename Pixel
+ , typename Factors
+ >
+inline
+const typename subchroma_image< Pixel, Factors >::view_t& view( subchroma_image< Pixel, Factors >& img )
+{
+ return img._view;
+}
+
+template< typename Pixel
+ , typename Factors
+ >
+inline
+const typename subchroma_image< Pixel, Factors >::const_view_t const_view( subchroma_image< Pixel, Factors >& img )
+{
+ return static_cast< const typename subchroma_image< Pixel, Factors >::const_view_t>( img._view );
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/// \ingroup ImageViewSTLAlgorithmsFillPixels
+/// \brief std::fill for subchroma_image views
+/////////////////////////////////////////////////////////////////////////////////////////
+template< typename Locator
+ , typename Factors
+ , typename Pixel
+ >
+void fill_pixels( const subchroma_image_view< Locator, Factors >& view
+ , const Pixel& value
+ )
+{
+ typedef typename subchroma_image< Pixel, Factors >::plane_view_t::value_type channel_t;
+
+ fill_pixels( view.y_plane_view(), channel_t( at_c< 0 >( value )));
+ fill_pixels( view.v_plane_view(), channel_t( at_c< 1 >( value )));
+ fill_pixels( view.u_plane_view(), channel_t( at_c< 2 >( value )));
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+/// \ingroup ImageViewConstructors
+/// \brief Creates a subchroma view from a raw memory
+/////////////////////////////////////////////////////////////////////////////////////////
+template< typename Pixel
+ , typename Factors
+ >
+typename subchroma_image< Pixel
+ , Factors
+ >::view_t subchroma_view( std::size_t y_width
+ , std::size_t y_height
+ , unsigned char* y_base
+ )
+{
+ typedef Scaling_Factors< mpl::at_c< Factors, 0 >::type::value
+ , mpl::at_c< Factors, 1 >::type::value
+ , mpl::at_c< Factors, 2 >::type::value
+ > scaling_factors_t;
+
+ std::size_t y_channel_size = 1;
+ std::size_t u_channel_size = 1;
+
+ unsigned char* u_base = y_base + ( y_width * y_height * y_channel_size );
+ unsigned char* v_base = u_base + ( y_width / scaling_factors_t::ss_X )
+ * u_channel_size;
+
+ typedef subchroma_image< Pixel, Factors >::plane_view_t plane_view_t;
+
+ plane_view_t y_plane = interleaved_view( y_width
+ , y_height
+ , (plane_view_t::value_type*) y_base // pixels
+ , y_width // rowsize_in_bytes
+ );
+
+ plane_view_t v_plane = interleaved_view( y_width / scaling_factors_t::ss_X
+ , y_height / scaling_factors_t::ss_Y
+ , (plane_view_t::value_type*) v_base // pixels
+ , y_width // rowsize_in_bytes
+ );
+
+ plane_view_t u_plane = interleaved_view( y_width / scaling_factors_t::ss_X
+ , y_height / scaling_factors_t::ss_Y
+ , (plane_view_t::value_type*) u_base // pixels
+ , y_width // rowsize_in_bytes
+ );
+
+ typedef subchroma_image_deref_fn< typename subchroma_image< Pixel
+ , Factors
+ >::pixel_locator_t
+ , Factors
+ > defer_fn_t;
+
+ defer_fn_t deref_fn( y_plane.xy_at( 0, 0 )
+ , v_plane.xy_at( 0, 0 )
+ , u_plane.xy_at( 0, 0 )
+ );
+
+
+ typedef subchroma_image< Pixel
+ , Factors
+ >::locator_t locator_t;
+
+ locator_t locator( point_t( 0, 0 ) // p
+ , point_t( 1, 1 ) // step
+ , deref_fn
+ );
+
+ typedef subchroma_image< Pixel
+ , Factors
+ >::view_t view_t;
+
+ return view_t( point_t( y_width, y_height )
+ , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
+ , point_t( y_width / scaling_factors_t::ss_X, y_height / scaling_factors_t::ss_Y )
+ , locator
+ );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_IMAGE_TYPES_SUBCHROMA_IMAGE_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions.hpp b/boost/gil/extension/toolbox/metafunctions.hpp
new file mode 100644
index 0000000000..1912ed0023
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions.hpp
@@ -0,0 +1,31 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file metafunctions.hpp
+/// \brief Header for toolbox's metafunctions.
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/toolbox/metafunctions/channel_type.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/channel_view.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/get_pixel_type.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/is_similar.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/pixel_bit_size.hpp>
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions/channel_type.hpp b/boost/gil/extension/toolbox/metafunctions/channel_type.hpp
new file mode 100644
index 0000000000..13550b43e3
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/channel_type.hpp
@@ -0,0 +1,111 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_CHANNEL_TYPE_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_CHANNEL_TYPE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file channel_type.hpp
+/// \brief channel_type metafunction.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/utility/enable_if.hpp>
+
+#include <boost/mpl/at.hpp>
+
+#include <boost/gil/bit_aligned_pixel_reference.hpp>
+#include <boost/gil/channel.hpp>
+
+#include <boost/gil/extension/toolbox/dynamic_images.hpp>
+
+#include <boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp>
+
+namespace boost{ namespace gil {
+
+/// channel_type metafunction
+/// \brief Generates the channel type for
+
+template <typename B, typename C, typename L, bool M>
+struct gen_chan_ref
+{
+ typedef packed_dynamic_channel_reference< B
+ , mpl::at_c< C, 0 >::type::value
+ , M
+ > type;
+};
+
+//! This implementation works for bit_algined_pixel_reference
+//! with a homogeneous channel layout.
+//! The result type will be a packed_dynamic_channel_reference, since the
+//! offset info will be missing.
+
+// bit_aligned_pixel_reference
+template <typename B, typename C, typename L, bool M>
+struct channel_type< bit_aligned_pixel_reference<B,C,L,M> >
+ : lazy_enable_if< is_homogeneous< bit_aligned_pixel_reference< B, C, L, M > >
+ , gen_chan_ref< B, C, L, M >
+ > {};
+
+template <typename B, typename C, typename L, bool M>
+struct channel_type<const bit_aligned_pixel_reference<B,C,L,M> >
+ : lazy_enable_if< is_homogeneous< bit_aligned_pixel_reference< B, C, L, M > >
+ , gen_chan_ref< B, C, L, M >
+ > {};
+
+template <typename B, typename C, typename L>
+struct gen_chan_ref_p
+{
+ typedef packed_dynamic_channel_reference< B
+ , get_num_bits< typename mpl::at_c<C,0>::type>::value
+ , true
+ > type;
+};
+
+// packed_pixel
+template < typename BitField
+ , typename ChannelRefVec
+ , typename Layout
+ >
+struct channel_type< packed_pixel< BitField
+ , ChannelRefVec
+ , Layout
+ >
+ > : lazy_enable_if< is_homogeneous< packed_pixel< BitField
+ , ChannelRefVec
+ , Layout
+ >
+ >
+ , gen_chan_ref_p< BitField
+ , ChannelRefVec
+ , Layout
+ >
+ > {};
+
+template <typename B, typename C, typename L>
+struct channel_type< const packed_pixel< B, C, L > >
+ : lazy_enable_if< is_homogeneous<packed_pixel< B, C, L > >
+ , gen_chan_ref_p< B, C, L >
+ >
+{};
+
+template<>
+struct channel_type< any_image_pixel_t >
+{
+ typedef any_image_channel_t type;
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_CHANNEL_TYPE_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions/channel_view.hpp b/boost/gil/extension/toolbox/metafunctions/channel_view.hpp
new file mode 100644
index 0000000000..4d42ff3ac1
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/channel_view.hpp
@@ -0,0 +1,79 @@
+/*
+ Copyright 2010 Fabien Castan, Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_CHANNEL_VIEW_HPP_INCLUDED
+#define BOOST_GIL_EXTENSION_TOOLBOX_CHANNEL_VIEW_HPP_INCLUDED
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file channel_view.hpp
+/// \brief Helper to generate channel_view type.
+/// \author Fabien Castan, Christian Henning \n
+///
+/// \date 2010 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/image_view_factory.hpp>
+
+namespace boost {
+namespace gil {
+
+template < typename Channel
+ , typename View
+ >
+struct channel_type_to_index
+{
+ static const int value = detail::type_to_index< typename color_space_type< View >::type // color (mpl::vector)
+ , Channel // channel type
+ >::type::value; //< index of the channel in the color (mpl::vector)
+};
+
+template< typename Channel
+ , typename View
+ >
+struct channel_view_type : public kth_channel_view_type< channel_type_to_index< Channel
+ , View
+ >::value
+ , View
+ >
+{
+ static const int index = channel_type_to_index< Channel
+ , View
+ >::value;
+
+ typedef kth_channel_view_type< index
+ , View
+ > parent_t;
+
+ typedef typename parent_t::type type;
+
+
+ static type make( const View& src )
+ {
+ return parent_t::make( src );
+ }
+};
+
+/// \ingroup ImageViewTransformationsKthChannel
+template< typename Channel
+ , typename View
+ >
+typename channel_view_type< Channel
+ , View
+ >::type channel_view( const View& src )
+{
+ return channel_view_type< Channel
+ , View
+ >::make( src );
+}
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_CHANNEL_VIEW_HPP_INCLUDED
diff --git a/boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp b/boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp
new file mode 100644
index 0000000000..9cec37eac4
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/get_num_bits.hpp
@@ -0,0 +1,73 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_GET_NUM_BITS_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_GET_NUM_BITS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file get_num_bits.hpp
+/// \brief get_num_bits metafunction.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/channel.hpp>
+
+#include <boost/mpl/int.hpp>
+#include <boost/type_traits/is_integral.hpp>
+#include <boost/type_traits/is_class.hpp>
+#include <boost/utility/enable_if.hpp>
+
+namespace boost{ namespace gil {
+
+/// get_num_bits metafunctions
+/// \brief Determines the numbers of bits for the given channel type.
+
+template <typename T, class = void >
+struct get_num_bits;
+
+template< typename B, int I, int S, bool M >
+struct get_num_bits< packed_channel_reference< B, I, S, M > > : mpl::int_< S >
+{};
+
+template< typename B, int I, int S, bool M >
+struct get_num_bits< const packed_channel_reference< B, I, S, M > > : mpl::int_< S >
+{};
+
+template<typename B, int I, bool M>
+struct get_num_bits< packed_dynamic_channel_reference< B, I, M > > : mpl::int_< I >
+{};
+
+template<typename B, int I, bool M>
+struct get_num_bits< const packed_dynamic_channel_reference< B, I, M > > : mpl::int_< I >
+{};
+
+template< int N >
+struct get_num_bits< packed_channel_value< N > > : mpl::int_< N >
+{};
+
+template< int N >
+struct get_num_bits< const packed_channel_value< N > > : mpl::int_< N >
+{};
+
+template< typename T >
+struct get_num_bits< T
+ , typename enable_if< mpl::and_< is_integral< T >
+ , mpl::not_< is_class< T > >
+ >
+ >::type
+ > : mpl::int_< sizeof(T) * 8 >
+{};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_GET_NUM_BITS_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions/get_pixel_type.hpp b/boost/gil/extension/toolbox/metafunctions/get_pixel_type.hpp
new file mode 100644
index 0000000000..dc0876c1ae
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/get_pixel_type.hpp
@@ -0,0 +1,46 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_GET_PIXEL_TYPE_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_GET_PIXEL_TYPE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file get_pixel_type.hpp
+/// \brief get_pixel_type metafunction.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/toolbox/dynamic_images.hpp>
+#include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
+
+namespace boost{ namespace gil {
+
+/// get_pixel_type metafunction
+/// \brief Depending on Image this function generates either
+/// the pixel type or the reference type in case
+/// the image is bit_aligned.
+template< typename View >
+struct get_pixel_type : mpl::if_< typename is_bit_aligned< typename View::value_type >::type
+ , typename View::reference
+ , typename View::value_type
+ > {};
+
+template< typename ImageViewTypes >
+struct get_pixel_type< any_image_view< ImageViewTypes > >
+{
+ typedef any_image_pixel_t type;
+};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_GET_PIXEL_TYPE_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions/gil_extensions.hpp b/boost/gil/extension/toolbox/metafunctions/gil_extensions.hpp
new file mode 100644
index 0000000000..927a2194c7
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/gil_extensions.hpp
@@ -0,0 +1,42 @@
+/*
+ Copyright 2010 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_GIL_EXTENSIONS_HPP_INCLUDED
+#define BOOST_GIL_EXTENSION_TOOLBOX_GIL_EXTENSIONS_HPP_INCLUDED
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file
+/// \brief Definitions of is_bit_aligned, is_homogeneous, and is_similar metafunctions and
+/// some other goodies.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2008 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/gil_all.hpp>
+
+
+#include <boost/mpl/if.hpp>
+
+#include <boost/gil/extension/toolbox/dynamic_images.hpp>
+
+namespace boost { namespace gil {
+
+
+/// other goodies
+
+
+
+
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_GIL_EXTENSIONS_HPP_INCLUDED
diff --git a/boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp b/boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp
new file mode 100644
index 0000000000..369f8cbab5
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp
@@ -0,0 +1,47 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_BIT_ALIGNED_TYPE_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_BIT_ALIGNED_TYPE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file is_bit_aligned.hpp
+/// \brief is_bit_aligned metafunction.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/bit_aligned_pixel_reference.hpp>
+
+namespace boost{ namespace gil {
+
+/// is_bit_aligned metafunctions
+/// \brief Determines whether the given type is bit_aligned.
+
+template< typename PixelRef >
+struct is_bit_aligned : mpl::false_{};
+
+template <typename B, typename C, typename L, bool M>
+struct is_bit_aligned<bit_aligned_pixel_reference<B,C,L,M> > : mpl::true_{};
+
+template <typename B, typename C, typename L, bool M>
+struct is_bit_aligned<const bit_aligned_pixel_reference<B,C,L,M> > : mpl::true_{};
+
+template <typename B, typename C, typename L>
+struct is_bit_aligned<packed_pixel<B,C,L> > : mpl::true_{};
+
+template <typename B, typename C, typename L>
+struct is_bit_aligned<const packed_pixel<B,C,L> > : mpl::true_{};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_BIT_ALIGNED_TYPE_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp b/boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp
new file mode 100644
index 0000000000..9770d2bb2b
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/is_homogeneous.hpp
@@ -0,0 +1,93 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_HOMOGENEOUS_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_HOMOGENEOUS_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file is_homogeneous.hpp
+/// \brief is_homogeneous metafunction
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/at.hpp>
+
+#include <boost/gil/pixel.hpp>
+
+
+namespace boost{ namespace gil {
+
+/// is_homogeneous metafunctions
+/// \brief Determines if a pixel types are homogeneous.
+
+template<typename C,typename CMP, int Next, int Last> struct is_homogeneous_impl;
+
+template<typename C,typename CMP, int Last>
+struct is_homogeneous_impl<C,CMP,Last,Last> : mpl::true_{};
+
+template<typename C,typename CMP, int Next, int Last>
+struct is_homogeneous_impl : mpl::and_< is_homogeneous_impl< C, CMP,Next + 1, Last >
+ , is_same< CMP, typename mpl::at_c<C,Next>::type
+ > > {};
+
+template < typename P > struct is_homogeneous : mpl::false_ {};
+
+// pixel
+template < typename C, typename L > struct is_homogeneous< pixel<C,L> > : mpl::true_ {};
+template < typename C, typename L > struct is_homogeneous<const pixel<C,L> > : mpl::true_ {};
+template < typename C, typename L > struct is_homogeneous< pixel<C,L>& > : mpl::true_ {};
+template < typename C, typename L > struct is_homogeneous<const pixel<C,L>& > : mpl::true_ {};
+
+// planar pixel reference
+template <typename Channel, typename ColorSpace>
+struct is_homogeneous< planar_pixel_reference< Channel, ColorSpace > > : mpl::true_ {};
+template <typename Channel, typename ColorSpace>
+struct is_homogeneous< const planar_pixel_reference< Channel, ColorSpace > > : mpl::true_ {};
+
+template<typename C,typename CMP, int I,int Last>
+struct is_homogeneous_impl_p {};
+
+// for packed_pixel
+template <typename B, typename C, typename L >
+struct is_homogeneous<packed_pixel< B, C, L > >
+ : is_homogeneous_impl_p< C
+ , typename mpl::at_c< C, 0 >::type
+ , 1
+ , mpl::size< C >::type::value
+ > {};
+
+template< typename B
+ , typename C
+ , typename L
+ >
+struct is_homogeneous< const packed_pixel< B, C, L > >
+ : is_homogeneous_impl_p< C
+ , typename mpl::at_c<C,0>::type
+ , 1
+ , mpl::size< C >::type::value
+ > {};
+
+// for bit_aligned_pixel_reference
+template <typename B, typename C, typename L, bool M>
+struct is_homogeneous<bit_aligned_pixel_reference<B,C,L,M> >
+ : is_homogeneous_impl<C,typename mpl::at_c<C,0>::type,1,mpl::size<C>::type::value>
+{};
+
+template <typename B, typename C, typename L, bool M>
+struct is_homogeneous<const bit_aligned_pixel_reference<B,C,L,M> >
+ : is_homogeneous_impl<C,typename mpl::at_c<C,0>::type,1,mpl::size<C>::type::value>
+{};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_HOMOGENEOUS_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions/is_similar.hpp b/boost/gil/extension/toolbox/metafunctions/is_similar.hpp
new file mode 100644
index 0000000000..74af5c915d
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/is_similar.hpp
@@ -0,0 +1,43 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_SIMILAR_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_SIMILAR_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file is_similar.hpp
+/// \brief is_similar metafunction.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/channel.hpp>
+
+namespace boost{ namespace gil {
+
+/// is_similar metafunctions
+/// \brief Determines if two pixel types are similar.
+
+template< typename A, typename B >
+struct is_similar : mpl::false_ {};
+
+template<typename A>
+struct is_similar< A, A > : mpl::true_ {};
+
+template<typename B,int I, int S, bool M, int I2>
+struct is_similar< packed_channel_reference< B, I, S, M >
+ , packed_channel_reference< B, I2, S, M >
+ > : mpl::true_ {};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_SIMILAR_HPP
diff --git a/boost/gil/extension/toolbox/metafunctions/pixel_bit_size.hpp b/boost/gil/extension/toolbox/metafunctions/pixel_bit_size.hpp
new file mode 100644
index 0000000000..cff9a49bb7
--- /dev/null
+++ b/boost/gil/extension/toolbox/metafunctions/pixel_bit_size.hpp
@@ -0,0 +1,55 @@
+/*
+ Copyright 2012 Christian Henning, Andreas Pokorny, Lubomir Bourdev
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_PIXEL_BIT_SIZE_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_PIXEL_BIT_SIZE_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file pixel_bit_size.hpp
+/// \brief pixel_bit_size metafunction.
+/// \author Christian Henning, Andreas Pokorny, Lubomir Bourdev \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/mpl/int.hpp>
+#include <boost/mpl/accumulate.hpp>
+
+#include <boost/gil/bit_aligned_pixel_reference.hpp>
+#include <boost/gil/packed_pixel.hpp>
+
+namespace boost{ namespace gil {
+
+/// pixel_bit_size metafunctions
+/// \brief Accumulates the all channel size.
+///
+/// \code
+/// typedef bit_aligned_image5_type< 16, 16, 16, 8, 8, devicen_layout_t< 5 > >::type image_t;
+/// const int size = pixel_bit_size<image_t::view_t::reference>::value;
+/// \endcode
+template< typename PixelRef >
+struct pixel_bit_size : mpl::int_<0> {};
+
+template <typename B, typename C, typename L, bool M>
+struct pixel_bit_size<bit_aligned_pixel_reference<B,C,L,M> > : mpl::int_< mpl::accumulate< C, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type::value >{};
+
+template <typename B, typename C, typename L, bool M>
+struct pixel_bit_size<const bit_aligned_pixel_reference<B,C,L,M> > : mpl::int_< mpl::accumulate< C, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type::value >{};
+
+template <typename B, typename C, typename L>
+struct pixel_bit_size<packed_pixel<B,C,L> > : mpl::int_< mpl::accumulate< C, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type::value >{};
+
+template <typename B, typename C, typename L>
+struct pixel_bit_size<const packed_pixel<B,C,L> > : mpl::int_< mpl::accumulate< C, mpl::int_<0>, mpl::plus<mpl::_1, mpl::_2> >::type::value >{};
+
+} // namespace gil
+} // namespace boost
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_PIXEL_BIT_SIZE_HPP
diff --git a/boost/gil/extension/toolbox/toolbox.hpp b/boost/gil/extension/toolbox/toolbox.hpp
new file mode 100644
index 0000000000..07f10736db
--- /dev/null
+++ b/boost/gil/extension/toolbox/toolbox.hpp
@@ -0,0 +1,29 @@
+/*
+ Copyright 2012 Christian Henning
+ Use, modification and distribution are subject to the Boost Software License,
+ Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
+ http://www.boost.org/LICENSE_1_0.txt).
+*/
+
+/*************************************************************************************************/
+
+#ifndef BOOST_GIL_EXTENSION_TOOLBOX_TOOLBOX_HPP
+#define BOOST_GIL_EXTENSION_TOOLBOX_TOOLBOX_HPP
+
+////////////////////////////////////////////////////////////////////////////////////////
+/// \file toolbox.hpp
+/// \brief Main header for toolbox extension.
+/// \author Christian Henning \n
+///
+/// \date 2012 \n
+///
+////////////////////////////////////////////////////////////////////////////////////////
+
+#include <boost/gil/extension/toolbox/color_converters.hpp>
+#include <boost/gil/extension/toolbox/color_spaces.hpp>
+#include <boost/gil/extension/toolbox/image_types.hpp>
+#include <boost/gil/extension/toolbox/metafunctions.hpp>
+
+#include <boost/gil/extension/toolbox/dynamic_images.hpp>
+
+#endif // BOOST_GIL_EXTENSION_TOOLBOX_TOOLBOX_HPP