update boost
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2022 Marco Langer <langer.m86 at gmail dot com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -12,7 +13,10 @@
|
||||
|
||||
#include <boost/gil/algorithm.hpp>
|
||||
|
||||
#include <boost/variant2/variant.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <utility>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \file
|
||||
@@ -40,34 +44,34 @@ struct equal_pixels_fn : binary_operation_obj<equal_pixels_fn, bool>
|
||||
} // namespace detail
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
|
||||
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam View Model MutableImageViewConcept
|
||||
template <typename Types, typename View>
|
||||
bool equal_pixels(any_image_view<Types> const& src, View const& dst)
|
||||
template <typename ...Types, typename View>
|
||||
auto equal_pixels(any_image_view<Types...> const& src, View const& dst) -> bool
|
||||
{
|
||||
return apply_operation(
|
||||
src,
|
||||
std::bind(detail::equal_pixels_fn(), std::placeholders::_1, dst));
|
||||
return variant2::visit(
|
||||
std::bind(detail::equal_pixels_fn(), std::placeholders::_1, dst),
|
||||
src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
|
||||
/// \tparam View Model ImageViewConcept
|
||||
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
template <typename View, typename Types>
|
||||
bool equal_pixels(View const& src, any_image_view<Types> const& dst)
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
template <typename View, typename ...Types>
|
||||
auto equal_pixels(View const& src, any_image_view<Types...> const& dst) -> bool
|
||||
{
|
||||
return apply_operation(
|
||||
dst,
|
||||
std::bind(detail::equal_pixels_fn(), src, std::placeholders::_1));
|
||||
return variant2::visit(
|
||||
std::bind(detail::equal_pixels_fn(), src, std::placeholders::_1),
|
||||
dst);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsEqualPixels
|
||||
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
template <typename Types1, typename Types2>
|
||||
bool equal_pixels(any_image_view<Types1> const& src, any_image_view<Types2> const& dst)
|
||||
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
template <typename ...Types1, typename ...Types2>
|
||||
auto equal_pixels(any_image_view<Types1...> const& src, any_image_view<Types2...> const& dst) -> bool
|
||||
{
|
||||
return apply_operation(src, dst, detail::equal_pixels_fn());
|
||||
return variant2::visit(detail::equal_pixels_fn(), src, dst);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -85,99 +89,99 @@ struct copy_pixels_fn : public binary_operation_obj<copy_pixels_fn>
|
||||
} // namespace detail
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
|
||||
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam View Model MutableImageViewConcept
|
||||
template <typename Types, typename View>
|
||||
void copy_pixels(any_image_view<Types> const& src, View const& dst)
|
||||
template <typename ...Types, typename View>
|
||||
void copy_pixels(any_image_view<Types...> const& src, View const& dst)
|
||||
{
|
||||
apply_operation(src, std::bind(detail::copy_pixels_fn(), std::placeholders::_1, dst));
|
||||
variant2::visit(std::bind(detail::copy_pixels_fn(), std::placeholders::_1, dst), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
|
||||
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
/// \tparam View Model ImageViewConcept
|
||||
template <typename Types, typename View>
|
||||
void copy_pixels(View const& src, any_image_view<Types> const& dst)
|
||||
template <typename ...Types, typename View>
|
||||
void copy_pixels(View const& src, any_image_view<Types...> const& dst)
|
||||
{
|
||||
apply_operation(dst, std::bind(detail::copy_pixels_fn(), src, std::placeholders::_1));
|
||||
variant2::visit(std::bind(detail::copy_pixels_fn(), src, std::placeholders::_1), dst);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyPixels
|
||||
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
template <typename Types1, typename Types2>
|
||||
void copy_pixels(any_image_view<Types1> const& src, any_image_view<Types2> const& dst)
|
||||
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
template <typename ...Types1, typename ...Types2>
|
||||
void copy_pixels(any_image_view<Types1...> const& src, any_image_view<Types2...> const& dst)
|
||||
{
|
||||
apply_operation(src, dst, detail::copy_pixels_fn());
|
||||
variant2::visit(detail::copy_pixels_fn(), src, dst);
|
||||
}
|
||||
|
||||
//forward declaration for default_color_converter (see full definition in color_convert.hpp)
|
||||
struct default_color_converter;
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
|
||||
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam View Model MutableImageViewConcept
|
||||
/// \tparam CC Model ColorConverterConcept
|
||||
template <typename Types, typename View, typename CC>
|
||||
void copy_and_convert_pixels(any_image_view<Types> const& src, View const& dst, CC cc)
|
||||
template <typename ...Types, typename View, typename CC>
|
||||
void copy_and_convert_pixels(any_image_view<Types...> const& src, View const& dst, CC cc)
|
||||
{
|
||||
using cc_fn = detail::copy_and_convert_pixels_fn<CC>;
|
||||
apply_operation(src, std::bind(cc_fn{cc}, std::placeholders::_1, dst));
|
||||
variant2::visit(std::bind(cc_fn{cc}, std::placeholders::_1, dst), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
|
||||
/// \tparam Types Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam View Model MutableImageViewConcept
|
||||
template <typename Types, typename View>
|
||||
void copy_and_convert_pixels(any_image_view<Types> const& src, View const& dst)
|
||||
template <typename ...Types, typename View>
|
||||
void copy_and_convert_pixels(any_image_view<Types...> const& src, View const& dst)
|
||||
{
|
||||
using cc_fn = detail::copy_and_convert_pixels_fn<default_color_converter>;
|
||||
apply_operation(src, std::bind(cc_fn{}, std::placeholders::_1, dst));
|
||||
variant2::visit(std::bind(cc_fn{}, std::placeholders::_1, dst), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
|
||||
/// \tparam View Model ImageViewConcept
|
||||
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
/// \tparam CC Model ColorConverterConcept
|
||||
template <typename View, typename Types, typename CC>
|
||||
void copy_and_convert_pixels(View const& src, any_image_view<Types> const& dst, CC cc)
|
||||
template <typename View, typename ...Types, typename CC>
|
||||
void copy_and_convert_pixels(View const& src, any_image_view<Types...> const& dst, CC cc)
|
||||
{
|
||||
using cc_fn = detail::copy_and_convert_pixels_fn<CC>;
|
||||
apply_operation(dst, std::bind(cc_fn{cc}, src, std::placeholders::_1));
|
||||
variant2::visit(std::bind(cc_fn{cc}, src, std::placeholders::_1), dst);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
|
||||
/// \tparam View Model ImageViewConcept
|
||||
/// \tparam Type Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
template <typename View, typename Types>
|
||||
void copy_and_convert_pixels(View const& src, any_image_view<Types> const& dst)
|
||||
/// \tparam Type Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
template <typename View, typename ...Types>
|
||||
void copy_and_convert_pixels(View const& src, any_image_view<Types...> const& dst)
|
||||
{
|
||||
using cc_fn = detail::copy_and_convert_pixels_fn<default_color_converter>;
|
||||
apply_operation(dst, std::bind(cc_fn{}, src, std::placeholders::_1));
|
||||
variant2::visit(std::bind(cc_fn{}, src, std::placeholders::_1), dst);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
|
||||
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
/// \tparam CC Model ColorConverterConcept
|
||||
template <typename Types1, typename Types2, typename CC>
|
||||
template <typename ...Types1, typename ...Types2, typename CC>
|
||||
void copy_and_convert_pixels(
|
||||
any_image_view<Types1> const& src,
|
||||
any_image_view<Types2> const& dst, CC cc)
|
||||
any_image_view<Types1...> const& src,
|
||||
any_image_view<Types2...> const& dst, CC cc)
|
||||
{
|
||||
apply_operation(src, dst, detail::copy_and_convert_pixels_fn<CC>(cc));
|
||||
variant2::visit(detail::copy_and_convert_pixels_fn<CC>(cc), src, dst);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsCopyAndConvertPixels
|
||||
/// \tparam Types1 Model MPL Random Access Container of models of ImageViewConcept
|
||||
/// \tparam Types2 Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
template <typename Types1, typename Types2>
|
||||
/// \tparam Types1 Model Boost.MP11-compatible list of models of ImageViewConcept
|
||||
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
template <typename ...Types1, typename ...Types2>
|
||||
void copy_and_convert_pixels(
|
||||
any_image_view<Types1> const& src,
|
||||
any_image_view<Types2> const& dst)
|
||||
any_image_view<Types1...> const& src,
|
||||
any_image_view<Types2...> const& dst)
|
||||
{
|
||||
apply_operation(src, dst,
|
||||
detail::copy_and_convert_pixels_fn<default_color_converter>());
|
||||
variant2::visit(
|
||||
detail::copy_and_convert_pixels_fn<default_color_converter>(), src, dst);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
@@ -186,7 +190,7 @@ template <bool IsCompatible>
|
||||
struct fill_pixels_fn1
|
||||
{
|
||||
template <typename V, typename Value>
|
||||
static void apply(V const &src, Value const &val) { fill_pixels(src, val); }
|
||||
static void apply(V const& src, Value const& val) { fill_pixels(src, val); }
|
||||
};
|
||||
|
||||
// copy_pixels invoked on incompatible images
|
||||
@@ -194,7 +198,7 @@ template <>
|
||||
struct fill_pixels_fn1<false>
|
||||
{
|
||||
template <typename V, typename Value>
|
||||
static void apply(V const &, Value const &) { throw std::bad_cast();}
|
||||
static void apply(V const&, Value const&) { throw std::bad_cast();}
|
||||
};
|
||||
|
||||
template <typename Value>
|
||||
@@ -223,11 +227,40 @@ struct fill_pixels_fn
|
||||
|
||||
/// \ingroup ImageViewSTLAlgorithmsFillPixels
|
||||
/// \brief fill_pixels for any image view. The pixel to fill with must be compatible with the current view
|
||||
/// \tparam Types Model MPL Random Access Container of models of MutableImageViewConcept
|
||||
template <typename Types, typename Value>
|
||||
void fill_pixels(any_image_view<Types> const& view, Value const& val)
|
||||
/// \tparam Types Model Boost.MP11-compatible list of models of MutableImageViewConcept
|
||||
template <typename ...Types, typename Value>
|
||||
void fill_pixels(any_image_view<Types...> const& view, Value const& val)
|
||||
{
|
||||
apply_operation(view, detail::fill_pixels_fn<Value>(val));
|
||||
variant2::visit(detail::fill_pixels_fn<Value>(val), view);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename F>
|
||||
struct for_each_pixel_fn
|
||||
{
|
||||
for_each_pixel_fn(F&& fun) : fun_(std::move(fun)) {}
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& view) -> F
|
||||
{
|
||||
return for_each_pixel(view, fun_);
|
||||
}
|
||||
|
||||
F fun_;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \defgroup ImageViewSTLAlgorithmsForEachPixel for_each_pixel
|
||||
/// \ingroup ImageViewSTLAlgorithms
|
||||
/// \brief std::for_each for any image views
|
||||
///
|
||||
/// \ingroup ImageViewSTLAlgorithmsForEachPixel
|
||||
template <typename ...Types, typename F>
|
||||
auto for_each_pixel(any_image_view<Types...> const& view, F fun) -> F
|
||||
{
|
||||
return variant2::visit(detail::for_each_pixel_fn<F>(std::move(fun)), view);
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2020 Samuel Debionne
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -9,11 +10,12 @@
|
||||
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_ANY_IMAGE_HPP
|
||||
|
||||
#include <boost/gil/extension/dynamic_image/any_image_view.hpp>
|
||||
#include <boost/gil/extension/dynamic_image/apply_operation.hpp>
|
||||
|
||||
#include <boost/gil/image.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/variant2/variant.hpp>
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
#pragma warning(push)
|
||||
@@ -23,35 +25,53 @@
|
||||
namespace boost { namespace gil {
|
||||
|
||||
namespace detail {
|
||||
template <typename T> struct get_view_t { using type = typename T::view_t; };
|
||||
template <typename Images> struct images_get_views_t : public mpl::transform<Images, get_view_t<mpl::_1> > {};
|
||||
|
||||
template <typename T> struct get_const_view_t { using type = typename T::const_view_t; };
|
||||
template <typename Images> struct images_get_const_views_t : public mpl::transform<Images, get_const_view_t<mpl::_1> > {};
|
||||
template <typename T>
|
||||
using get_view_t = typename T::view_t;
|
||||
|
||||
struct recreate_image_fnobj
|
||||
template <typename Images>
|
||||
using images_get_views_t = mp11::mp_transform<get_view_t, Images>;
|
||||
|
||||
template <typename T>
|
||||
using get_const_view_t = typename T::const_view_t;
|
||||
|
||||
template <typename Images>
|
||||
using images_get_const_views_t = mp11::mp_transform<get_const_view_t, Images>;
|
||||
|
||||
struct recreate_image_fnobj
|
||||
{
|
||||
using result_type = void;
|
||||
point<std::ptrdiff_t> const& _dimensions;
|
||||
unsigned _alignment;
|
||||
|
||||
recreate_image_fnobj(point<std::ptrdiff_t> const& dims, unsigned alignment)
|
||||
: _dimensions(dims), _alignment(alignment)
|
||||
{}
|
||||
|
||||
template <typename Image>
|
||||
result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); }
|
||||
};
|
||||
|
||||
template <typename AnyView> // Models AnyViewConcept
|
||||
struct any_image_get_view
|
||||
{
|
||||
using result_type = AnyView;
|
||||
template <typename Image>
|
||||
result_type operator()(Image& img) const
|
||||
{
|
||||
using result_type = void;
|
||||
point<std::ptrdiff_t> const& _dimensions;
|
||||
unsigned _alignment;
|
||||
return result_type(view(img));
|
||||
}
|
||||
};
|
||||
|
||||
recreate_image_fnobj(point<std::ptrdiff_t> const& dims, unsigned alignment) : _dimensions(dims), _alignment(alignment) {}
|
||||
template <typename Image>
|
||||
result_type operator()(Image& img) const { img.recreate(_dimensions,_alignment); }
|
||||
};
|
||||
template <typename AnyConstView> // Models AnyConstViewConcept
|
||||
struct any_image_get_const_view
|
||||
{
|
||||
using result_type = AnyConstView;
|
||||
template <typename Image>
|
||||
result_type operator()(Image const& img) const { return result_type{const_view(img)}; }
|
||||
};
|
||||
|
||||
template <typename AnyView> // Models AnyViewConcept
|
||||
struct any_image_get_view {
|
||||
using result_type = AnyView;
|
||||
template <typename Image> result_type operator()( Image& img) const { return result_type(view(img)); }
|
||||
};
|
||||
|
||||
template <typename AnyConstView> // Models AnyConstViewConcept
|
||||
struct any_image_get_const_view {
|
||||
using result_type = AnyConstView;
|
||||
template <typename Image> result_type operator()(const Image& img) const { return result_type(const_view(img)); }
|
||||
};
|
||||
}
|
||||
} // namespce detail
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// \ingroup ImageModel
|
||||
@@ -63,40 +83,63 @@ namespace detail {
|
||||
/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image does not fully model ImageConcept.
|
||||
/// In particular, its \p view and \p const_view methods return \p any_image_view, which does not fully model ImageViewConcept. See \p any_image_view for more.
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename ImageTypes>
|
||||
class any_image : public make_variant_over<ImageTypes>::type {
|
||||
using parent_t = typename make_variant_over<ImageTypes>::type;
|
||||
|
||||
template <typename ...Images>
|
||||
class any_image : public variant2::variant<Images...>
|
||||
{
|
||||
using parent_t = variant2::variant<Images...>;
|
||||
|
||||
public:
|
||||
using const_view_t = any_image_view<typename detail::images_get_const_views_t<ImageTypes>::type>;
|
||||
using view_t = any_image_view<typename detail::images_get_views_t<ImageTypes>::type>;
|
||||
using view_t = mp11::mp_rename<detail::images_get_views_t<any_image>, any_image_view>;
|
||||
using const_view_t = mp11::mp_rename<detail::images_get_const_views_t<any_image>, any_image_view>;
|
||||
using x_coord_t = std::ptrdiff_t;
|
||||
using y_coord_t = std::ptrdiff_t;
|
||||
using point_t = point<std::ptrdiff_t>;
|
||||
|
||||
any_image() : parent_t() {}
|
||||
template <typename T> explicit any_image(const T& obj) : parent_t(obj) {}
|
||||
template <typename T> explicit any_image(T& obj, bool do_swap) : parent_t(obj,do_swap) {}
|
||||
any_image(const any_image& v) : parent_t((const parent_t&)v) {}
|
||||
template <typename Types> any_image(const any_image<Types>& v) : parent_t((const typename make_variant_over<Types>::type&)v) {}
|
||||
using parent_t::parent_t;
|
||||
|
||||
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 typename make_variant_over<Types>::type&)v); return *this;}
|
||||
|
||||
void recreate(const point_t& dims, unsigned alignment=1)
|
||||
any_image& operator=(any_image const& img)
|
||||
{
|
||||
apply_operation(*this,detail::recreate_image_fnobj(dims,alignment));
|
||||
parent_t::operator=((parent_t const&)img);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename Image>
|
||||
any_image& operator=(Image const& img)
|
||||
{
|
||||
parent_t::operator=(img);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename ...OtherImages>
|
||||
any_image& operator=(any_image<OtherImages...> const& img)
|
||||
{
|
||||
parent_t::operator=((typename variant2::variant<OtherImages...> const&)img);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void recreate(point_t const& dims, unsigned alignment=1)
|
||||
{
|
||||
variant2::visit(detail::recreate_image_fnobj(dims, alignment), *this);
|
||||
}
|
||||
|
||||
void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1)
|
||||
{
|
||||
recreate({width, height}, alignment);
|
||||
recreate({ width, height }, alignment);
|
||||
}
|
||||
|
||||
std::size_t num_channels() const { return apply_operation(*this, detail::any_type_get_num_channels()); }
|
||||
point_t dimensions() const { return apply_operation(*this, detail::any_type_get_dimensions()); }
|
||||
x_coord_t width() const { return dimensions().x; }
|
||||
y_coord_t height() const { return dimensions().y; }
|
||||
std::size_t num_channels() const
|
||||
{
|
||||
return variant2::visit(detail::any_type_get_num_channels(), *this);
|
||||
}
|
||||
|
||||
point_t dimensions() const
|
||||
{
|
||||
return variant2::visit(detail::any_type_get_dimensions(), *this);
|
||||
}
|
||||
|
||||
x_coord_t width() const { return dimensions().x; }
|
||||
y_coord_t height() const { return dimensions().y; }
|
||||
};
|
||||
|
||||
///@{
|
||||
@@ -106,15 +149,23 @@ public:
|
||||
/// \ingroup ImageModel
|
||||
|
||||
/// \brief Returns the non-constant-pixel view of any image. The returned view is any view.
|
||||
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>());
|
||||
/// \tparam Images Models ImageVectorConcept
|
||||
template <typename ...Images>
|
||||
BOOST_FORCEINLINE
|
||||
auto view(any_image<Images...>& img) -> typename any_image<Images...>::view_t
|
||||
{
|
||||
using view_t = typename any_image<Images...>::view_t;
|
||||
return variant2::visit(detail::any_image_get_view<view_t>(), img);
|
||||
}
|
||||
|
||||
/// \brief Returns the constant-pixel view of any image. The returned view is any view.
|
||||
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>());
|
||||
/// \tparam Types Models ImageVectorConcept
|
||||
template <typename ...Images>
|
||||
BOOST_FORCEINLINE
|
||||
auto const_view(any_image<Images...> const& img) -> typename any_image<Images...>::const_view_t
|
||||
{
|
||||
using view_t = typename any_image<Images...>::const_view_t;
|
||||
return variant2::visit(detail::any_image_get_const_view<view_t>(), img);
|
||||
}
|
||||
///@}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2020 Samuel Debionne
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -12,36 +13,48 @@
|
||||
#include <boost/gil/image.hpp>
|
||||
#include <boost/gil/image_view.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/variant2/variant.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
namespace detail {
|
||||
template <typename View> struct get_const_t { using type = typename View::const_t; };
|
||||
template <typename Views> struct views_get_const_t : public mpl::transform<Views, get_const_t<mpl::_1> > {};
|
||||
}
|
||||
|
||||
template <typename View> struct dynamic_xy_step_transposed_type;
|
||||
template <typename View>
|
||||
struct dynamic_xy_step_transposed_type;
|
||||
|
||||
namespace detail {
|
||||
|
||||
// works for both image_view and image
|
||||
struct any_type_get_num_channels
|
||||
{
|
||||
using result_type = int;
|
||||
template <typename T>
|
||||
result_type operator()(const T&) const { return num_channels<T>::value; }
|
||||
};
|
||||
template <typename View>
|
||||
using get_const_t = typename View::const_t;
|
||||
|
||||
// works for both image_view and image
|
||||
struct any_type_get_dimensions
|
||||
{
|
||||
using result_type = point<std::ptrdiff_t>;
|
||||
template <typename T>
|
||||
result_type operator()(const T& v) const { return v.dimensions(); }
|
||||
};
|
||||
}
|
||||
template <typename Views>
|
||||
using views_get_const_t = mp11::mp_transform<get_const_t, Views>;
|
||||
|
||||
// works for both image_view and image
|
||||
struct any_type_get_num_channels
|
||||
{
|
||||
using result_type = int;
|
||||
template <typename T>
|
||||
result_type operator()(const T&) const { return num_channels<T>::value; }
|
||||
};
|
||||
|
||||
// works for both image_view and image
|
||||
struct any_type_get_dimensions
|
||||
{
|
||||
using result_type = point<std::ptrdiff_t>;
|
||||
template <typename T>
|
||||
result_type operator()(const T& v) const { return v.dimensions(); }
|
||||
};
|
||||
|
||||
// works for image_view
|
||||
struct any_type_get_size
|
||||
{
|
||||
using result_type = std::size_t;
|
||||
template <typename T>
|
||||
result_type operator()(const T& v) const { return v.size(); }
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
/// CLASS any_image_view
|
||||
@@ -55,28 +68,46 @@ namespace detail {
|
||||
/// Other requirements, such as access to the pixels, would be inefficient to provide. Thus \p any_image_view does not fully model ImageViewConcept.
|
||||
/// However, many algorithms provide overloads taking runtime specified views and thus in many cases \p any_image_view can be used in places taking a view.
|
||||
///
|
||||
/// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p apply_operation(runtime_view, algorithm_fn);
|
||||
/// To perform an algorithm on any_image_view, put the algorithm in a function object and invoke it by calling \p variant2::visit(algorithm_fn, runtime_view);
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
template <typename ImageViewTypes>
|
||||
class any_image_view : public make_variant_over<ImageViewTypes>::type {
|
||||
using parent_t = typename make_variant_over<ImageViewTypes>::type;
|
||||
|
||||
template <typename ...Views>
|
||||
class any_image_view : public variant2::variant<Views...>
|
||||
{
|
||||
using parent_t = variant2::variant<Views...>;
|
||||
|
||||
public:
|
||||
using const_t = any_image_view<typename detail::views_get_const_t<ImageViewTypes>::type>;
|
||||
using const_t = detail::views_get_const_t<any_image_view>;
|
||||
using x_coord_t = std::ptrdiff_t;
|
||||
using y_coord_t = std::ptrdiff_t;
|
||||
using point_t = point<std::ptrdiff_t>;
|
||||
using size_type = std::size_t;
|
||||
|
||||
any_image_view() : parent_t() {}
|
||||
template <typename T> explicit any_image_view(const T& obj) : parent_t(obj) {}
|
||||
any_image_view(const any_image_view& v) : parent_t((const parent_t&)v) {}
|
||||
template <typename Types> any_image_view(const any_image_view<Types>& v) : parent_t((const typename make_variant_over<Types>::type&)v) {}
|
||||
using parent_t::parent_t;
|
||||
|
||||
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 typename make_variant_over<Types>::type&)v); return *this;}
|
||||
any_image_view& operator=(any_image_view const& view)
|
||||
{
|
||||
parent_t::operator=((parent_t const&)view);
|
||||
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()); }
|
||||
template <typename View>
|
||||
any_image_view& operator=(View const& view)
|
||||
{
|
||||
parent_t::operator=(view);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename ...OtherViews>
|
||||
any_image_view& operator=(any_image_view<OtherViews...> const& view)
|
||||
{
|
||||
parent_t::operator=((variant2::variant<OtherViews...> const&)view);
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::size_t num_channels() const { return variant2::visit(detail::any_type_get_num_channels(), *this); }
|
||||
point_t dimensions() const { return variant2::visit(detail::any_type_get_dimensions(), *this); }
|
||||
size_type size() const { return variant2::visit(detail::any_type_get_size(), *this); }
|
||||
x_coord_t width() const { return dimensions().x; }
|
||||
y_coord_t height() const { return dimensions().y; }
|
||||
};
|
||||
@@ -85,32 +116,68 @@ public:
|
||||
// HasDynamicXStepTypeConcept
|
||||
/////////////////////////////
|
||||
|
||||
template <typename IVTypes>
|
||||
struct dynamic_x_step_type<any_image_view<IVTypes>>
|
||||
template <typename ...Views>
|
||||
struct dynamic_x_step_type<any_image_view<Views...>>
|
||||
{
|
||||
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_x_step_type<mpl::_1>>::type>;
|
||||
private:
|
||||
// FIXME: Remove class name injection with gil:: qualification
|
||||
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
|
||||
// in the class definition of the same name as the specialization (Peter Dimov):
|
||||
// invalid template argument for template parameter 'F', expected a class template
|
||||
template <typename T>
|
||||
using dynamic_step_view = typename gil::dynamic_x_step_type<T>::type;
|
||||
|
||||
public:
|
||||
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
|
||||
};
|
||||
|
||||
/////////////////////////////
|
||||
// HasDynamicYStepTypeConcept
|
||||
/////////////////////////////
|
||||
|
||||
template <typename IVTypes>
|
||||
struct dynamic_y_step_type<any_image_view<IVTypes>>
|
||||
template <typename ...Views>
|
||||
struct dynamic_y_step_type<any_image_view<Views...>>
|
||||
{
|
||||
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_y_step_type<mpl::_1>>::type>;
|
||||
private:
|
||||
// FIXME: Remove class name injection with gil:: qualification
|
||||
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
|
||||
// in the class definition of the same name as the specialization (Peter Dimov):
|
||||
// invalid template argument for template parameter 'F', expected a class template
|
||||
template <typename T>
|
||||
using dynamic_step_view = typename gil::dynamic_y_step_type<T>::type;
|
||||
|
||||
public:
|
||||
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
|
||||
};
|
||||
|
||||
template <typename IVTypes>
|
||||
struct dynamic_xy_step_type<any_image_view<IVTypes>>
|
||||
template <typename ...Views>
|
||||
struct dynamic_xy_step_type<any_image_view<Views...>>
|
||||
{
|
||||
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_xy_step_type<mpl::_1>>::type>;
|
||||
private:
|
||||
// FIXME: Remove class name injection with gil:: qualification
|
||||
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
|
||||
// in the class definition of the same name as the specialization (Peter Dimov):
|
||||
// invalid template argument for template parameter 'F', expected a class template
|
||||
template <typename T>
|
||||
using dynamic_step_view = typename gil::dynamic_xy_step_type<T>::type;
|
||||
|
||||
public:
|
||||
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
|
||||
};
|
||||
|
||||
template <typename IVTypes>
|
||||
struct dynamic_xy_step_transposed_type<any_image_view<IVTypes>>
|
||||
template <typename ...Views>
|
||||
struct dynamic_xy_step_transposed_type<any_image_view<Views...>>
|
||||
{
|
||||
using type = any_image_view<typename mpl::transform<IVTypes, dynamic_xy_step_transposed_type<mpl::_1>>::type>;
|
||||
private:
|
||||
// FIXME: Remove class name injection with gil:: qualification
|
||||
// Required as workaround for Boost.MP11 issue that treats unqualified metafunction
|
||||
// in the class definition of the same name as the specialization (Peter Dimov):
|
||||
// invalid template argument for template parameter 'F', expected a class template
|
||||
template <typename T>
|
||||
using dynamic_step_view = typename gil::dynamic_xy_step_type<T>::type;
|
||||
|
||||
public:
|
||||
using type = mp11::mp_transform<dynamic_step_view, any_image_view<Views...>>;
|
||||
};
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
@@ -8,64 +8,36 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_HPP
|
||||
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_APPLY_OPERATION_HPP
|
||||
|
||||
#include <boost/variant/apply_visitor.hpp>
|
||||
|
||||
#ifdef BOOST_GIL_DOXYGEN_ONLY
|
||||
#undef BOOST_GIL_REDUCE_CODE_BLOAT
|
||||
#endif
|
||||
|
||||
// Implements apply_operation for variants.
|
||||
// Optionally performs type reduction.
|
||||
#ifdef BOOST_GIL_REDUCE_CODE_BLOAT
|
||||
|
||||
#include <boost/gil/extension/dynamic_image/reduce.hpp>
|
||||
|
||||
#else
|
||||
#include <boost/variant2/variant.hpp>
|
||||
|
||||
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>
|
||||
/// \brief Applies the visitor op to the variants
|
||||
template <typename Variant1, typename Visitor>
|
||||
[[deprecated("Use variant2::visit instead.")]]
|
||||
BOOST_FORCEINLINE
|
||||
auto apply_operation(variant<Types>& arg, UnaryOp op)
|
||||
auto apply_operation(Variant1&& arg1, Visitor&& op)
|
||||
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
-> typename UnaryOp::result_type
|
||||
-> decltype(variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1)))
|
||||
#endif
|
||||
{
|
||||
return apply_visitor(op, arg);
|
||||
return variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1));
|
||||
}
|
||||
|
||||
/// \ingroup Variant
|
||||
/// \brief Invokes a generic constant operation (represented as a unary function object) on a variant
|
||||
template <typename Types, typename UnaryOp>
|
||||
/// \brief Applies the visitor op to the variants
|
||||
template <typename Variant1, typename Variant2, typename Visitor>
|
||||
[[deprecated("Use variant2::visit instead.")]]
|
||||
BOOST_FORCEINLINE
|
||||
auto apply_operation(variant<Types> const& arg, UnaryOp op)
|
||||
auto apply_operation(Variant1&& arg1, Variant2&& arg2, Visitor&& op)
|
||||
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
-> typename UnaryOp::result_type
|
||||
-> decltype(variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1), std::forward<Variant2>(arg2)))
|
||||
#endif
|
||||
{
|
||||
return apply_visitor(op, arg);
|
||||
}
|
||||
|
||||
/// \ingroup Variant
|
||||
/// \brief Invokes a generic constant operation (represented as a binary function object) on two variants
|
||||
template <typename Types1, typename Types2, typename BinaryOp>
|
||||
BOOST_FORCEINLINE
|
||||
auto apply_operation(
|
||||
variant<Types1> const& arg1,
|
||||
variant<Types2> const& arg2,
|
||||
BinaryOp op)
|
||||
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
|
||||
-> typename BinaryOp::result_type
|
||||
#endif
|
||||
{
|
||||
return apply_visitor(
|
||||
op, arg1, arg2);
|
||||
return variant2::visit(std::forward<Visitor>(op), std::forward<Variant1>(arg1), std::forward<Variant2>(arg2));
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif // defined(BOOST_GIL_REDUCE_CODE_BLOAT)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -8,8 +8,10 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_DYNAMIC_AT_C_HPP
|
||||
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_DYNAMIC_AT_C_HPP
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <boost/preprocessor/facilities/empty.hpp>
|
||||
#include <boost/preprocessor/repetition/repeat.hpp>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
@@ -17,16 +19,16 @@ namespace boost { namespace gil {
|
||||
|
||||
// Constructs for static-to-dynamic integer convesion
|
||||
|
||||
#define GIL_AT_C_VALUE(z, N, text) mpl::at_c<IntTypes,S+N>::type::value,
|
||||
#define GIL_DYNAMIC_AT_C_LIMIT 226 // size of the maximum vector to handle
|
||||
#define BOOST_GIL_AT_C_VALUE(z, N, text) mp11::mp_at_c<IntTypes, S+N>::value,
|
||||
#define BOOST_GIL_DYNAMIC_AT_C_LIMIT 226 // size of the maximum vector to handle
|
||||
|
||||
#define GIL_AT_C_LOOKUP(z, NUM, text) \
|
||||
#define BOOST_GIL_AT_C_LOOKUP(z, NUM, text) \
|
||||
template<std::size_t S> \
|
||||
struct at_c_fn<S,NUM> { \
|
||||
template <typename IntTypes, typename ValueType> inline \
|
||||
static ValueType apply(std::size_t index) { \
|
||||
static ValueType table[] = { \
|
||||
BOOST_PP_REPEAT(NUM, GIL_AT_C_VALUE, BOOST_PP_EMPTY) \
|
||||
BOOST_PP_REPEAT(NUM, BOOST_GIL_AT_C_VALUE, BOOST_PP_EMPTY) \
|
||||
}; \
|
||||
return table[index]; \
|
||||
} \
|
||||
@@ -35,7 +37,7 @@ namespace boost { namespace gil {
|
||||
namespace detail {
|
||||
namespace at_c {
|
||||
template <std::size_t START, std::size_t NUM> struct at_c_fn;
|
||||
BOOST_PP_REPEAT(GIL_DYNAMIC_AT_C_LIMIT, GIL_AT_C_LOOKUP, BOOST_PP_EMPTY)
|
||||
BOOST_PP_REPEAT(BOOST_GIL_DYNAMIC_AT_C_LIMIT, BOOST_GIL_AT_C_LOOKUP, BOOST_PP_EMPTY)
|
||||
|
||||
template <std::size_t QUOT> struct at_c_impl;
|
||||
|
||||
@@ -43,7 +45,7 @@ namespace detail {
|
||||
struct at_c_impl<0> {
|
||||
template <typename IntTypes, typename ValueType> inline
|
||||
static ValueType apply(std::size_t index) {
|
||||
return at_c_fn<0,mpl::size<IntTypes>::value>::template apply<IntTypes,ValueType>(index);
|
||||
return at_c_fn<0, mp11::mp_size<IntTypes>::value>::template apply<IntTypes,ValueType>(index);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -51,11 +53,11 @@ namespace detail {
|
||||
struct at_c_impl<1> {
|
||||
template <typename IntTypes, typename ValueType> inline
|
||||
static ValueType apply(std::size_t index) {
|
||||
const std::size_t SIZE=mpl::size<IntTypes>::value;
|
||||
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
|
||||
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
|
||||
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
|
||||
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
|
||||
const std::size_t SIZE = mp11::mp_size<IntTypes>::value;
|
||||
const std::size_t REM = SIZE % BOOST_GIL_DYNAMIC_AT_C_LIMIT;
|
||||
switch (index / BOOST_GIL_DYNAMIC_AT_C_LIMIT) {
|
||||
case 0: return at_c_fn<0 ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
|
||||
case 1: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT ,REM >::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT);
|
||||
};
|
||||
throw;
|
||||
}
|
||||
@@ -65,12 +67,12 @@ namespace detail {
|
||||
struct at_c_impl<2> {
|
||||
template <typename IntTypes, typename ValueType> inline
|
||||
static ValueType apply(std::size_t index) {
|
||||
const std::size_t SIZE=mpl::size<IntTypes>::value;
|
||||
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
|
||||
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
|
||||
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
|
||||
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
|
||||
case 2: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*2,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*2);
|
||||
const std::size_t SIZE = mp11::mp_size<IntTypes>::value;
|
||||
const std::size_t REM = SIZE % BOOST_GIL_DYNAMIC_AT_C_LIMIT;
|
||||
switch (index / BOOST_GIL_DYNAMIC_AT_C_LIMIT) {
|
||||
case 0: return at_c_fn<0 ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
|
||||
case 1: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT);
|
||||
case 2: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT*2,REM >::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT*2);
|
||||
};
|
||||
throw;
|
||||
}
|
||||
@@ -80,13 +82,13 @@ namespace detail {
|
||||
struct at_c_impl<3> {
|
||||
template <typename IntTypes, typename ValueType> inline
|
||||
static ValueType apply(std::size_t index) {
|
||||
const std::size_t SIZE=mpl::size<IntTypes>::value;
|
||||
const std::size_t REM = SIZE % GIL_DYNAMIC_AT_C_LIMIT;
|
||||
switch (index / GIL_DYNAMIC_AT_C_LIMIT) {
|
||||
case 0: return at_c_fn<0 ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
|
||||
case 1: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT ,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT);
|
||||
case 2: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*2,GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*2);
|
||||
case 3: return at_c_fn<GIL_DYNAMIC_AT_C_LIMIT*3,REM >::template apply<IntTypes,ValueType>(index - GIL_DYNAMIC_AT_C_LIMIT*3);
|
||||
const std::size_t SIZE = mp11::mp_size<IntTypes>::value;
|
||||
const std::size_t REM = SIZE % BOOST_GIL_DYNAMIC_AT_C_LIMIT;
|
||||
switch (index / BOOST_GIL_DYNAMIC_AT_C_LIMIT) {
|
||||
case 0: return at_c_fn<0 ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index);
|
||||
case 1: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT ,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT);
|
||||
case 2: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT*2,BOOST_GIL_DYNAMIC_AT_C_LIMIT-1>::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT*2);
|
||||
case 3: return at_c_fn<BOOST_GIL_DYNAMIC_AT_C_LIMIT*3,REM >::template apply<IntTypes,ValueType>(index - BOOST_GIL_DYNAMIC_AT_C_LIMIT*3);
|
||||
};
|
||||
throw;
|
||||
}
|
||||
@@ -96,20 +98,21 @@ namespace detail {
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
///
|
||||
/// \brief Given an MPL Random Access Sequence and a dynamic index n, returns the value of the n-th element
|
||||
/// It constructs a lookup table at compile time
|
||||
/// \brief Given an Boost.MP11-compatible list and a dynamic index n,
|
||||
/// returns the value of the n-th element.
|
||||
/// It constructs a lookup table at compile time.
|
||||
///
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <typename IntTypes, typename ValueType> inline
|
||||
ValueType at_c(std::size_t index) {
|
||||
const std::size_t Size=mpl::size<IntTypes>::value;
|
||||
return detail::at_c::at_c_impl<Size/GIL_DYNAMIC_AT_C_LIMIT>::template apply<IntTypes,ValueType>(index);
|
||||
const std::size_t Size=mp11::mp_size<IntTypes>::value;
|
||||
return detail::at_c::at_c_impl<Size/BOOST_GIL_DYNAMIC_AT_C_LIMIT>::template apply<IntTypes,ValueType>(index);
|
||||
}
|
||||
|
||||
#undef GIL_AT_C_VALUE
|
||||
#undef GIL_DYNAMIC_AT_C_LIMIT
|
||||
#undef GIL_AT_C_LOOKUP
|
||||
#undef BOOST_GIL_AT_C_VALUE
|
||||
#undef BOOST_GIL_DYNAMIC_AT_C_LIMIT
|
||||
#undef BOOST_GIL_AT_C_LOOKUP
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
|
||||
@@ -12,6 +12,5 @@
|
||||
#include <boost/gil/extension/dynamic_image/any_image.hpp>
|
||||
#include <boost/gil/extension/dynamic_image/apply_operation.hpp>
|
||||
#include <boost/gil/extension/dynamic_image/image_view_factory.hpp>
|
||||
#include <boost/gil.hpp> // FIXME: Include what you use!
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
#include <boost/gil/dynamic_step.hpp>
|
||||
#include <boost/gil/image_view_factory.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
@@ -20,238 +23,386 @@ namespace boost { namespace gil {
|
||||
// Extends image view factory to runtime type-specified views (any_image_view)
|
||||
|
||||
namespace detail {
|
||||
template <typename Result> struct flipped_up_down_view_fn {
|
||||
using result_type = Result;
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(flipped_up_down_view(src)); }
|
||||
};
|
||||
template <typename Result> struct flipped_left_right_view_fn {
|
||||
using result_type = Result;
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(flipped_left_right_view(src)); }
|
||||
};
|
||||
template <typename Result> struct rotated90cw_view_fn {
|
||||
using result_type = Result;
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(rotated90cw_view(src)); }
|
||||
};
|
||||
template <typename Result> struct rotated90ccw_view_fn {
|
||||
using result_type = Result;
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(rotated90ccw_view(src)); }
|
||||
};
|
||||
template <typename Result> struct tranposed_view_fn {
|
||||
using result_type = Result;
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(tranposed_view(src)); }
|
||||
};
|
||||
template <typename Result> struct rotated180_view_fn {
|
||||
using result_type = Result;
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(rotated180_view(src)); }
|
||||
|
||||
template <typename ResultView>
|
||||
struct flipped_up_down_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type{flipped_up_down_view(src)};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
template <typename ResultView>
|
||||
struct flipped_left_right_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type{flipped_left_right_view(src)};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultView>
|
||||
struct rotated90cw_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type{rotated90cw_view(src)};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultView>
|
||||
struct rotated90ccw_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type{rotated90ccw_view(src)};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultView>
|
||||
struct tranposed_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type{tranposed_view(src)};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultView>
|
||||
struct rotated180_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type{rotated180_view(src)};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename ResultView>
|
||||
struct subimage_view_fn
|
||||
{
|
||||
using result_type = Result;
|
||||
using result_type = ResultView;
|
||||
|
||||
subimage_view_fn(point_t const& topleft, point_t const& dimensions)
|
||||
: _topleft(topleft), _size2(dimensions)
|
||||
{}
|
||||
|
||||
template <typename View>
|
||||
result_type operator()(const View& src) const
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type(subimage_view(src,_topleft,_size2));
|
||||
return result_type{subimage_view(src,_topleft,_size2)};
|
||||
}
|
||||
|
||||
point_t _topleft;
|
||||
point_t _size2;
|
||||
};
|
||||
|
||||
template <typename Result>
|
||||
template <typename ResultView>
|
||||
struct subsampled_view_fn
|
||||
{
|
||||
using result_type = Result;
|
||||
using result_type = ResultView;
|
||||
|
||||
subsampled_view_fn(point_t const& step) : _step(step) {}
|
||||
|
||||
template <typename View>
|
||||
result_type operator()(const View& src) const
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type(subsampled_view(src,_step));
|
||||
return result_type{subsampled_view(src,_step)};
|
||||
}
|
||||
|
||||
point_t _step;
|
||||
};
|
||||
|
||||
template <typename Result> struct nth_channel_view_fn {
|
||||
using result_type = Result;
|
||||
template <typename ResultView>
|
||||
struct nth_channel_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
nth_channel_view_fn(int n) : _n(n) {}
|
||||
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type(nth_channel_view(src,_n));
|
||||
}
|
||||
|
||||
int _n;
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(nth_channel_view(src,_n)); }
|
||||
};
|
||||
template <typename DstP, typename Result, typename CC = default_color_converter> struct color_converted_view_fn {
|
||||
using result_type = Result;
|
||||
|
||||
template <typename DstP, typename ResultView, typename CC = default_color_converter>
|
||||
struct color_converted_view_fn
|
||||
{
|
||||
using result_type = ResultView;
|
||||
|
||||
color_converted_view_fn(CC cc = CC()): _cc(cc) {}
|
||||
|
||||
template <typename View> result_type operator()(const View& src) const { return result_type(color_converted_view<DstP>(src, _cc)); }
|
||||
template <typename View>
|
||||
auto operator()(View const& src) const -> result_type
|
||||
{
|
||||
return result_type{color_converted_view<DstP>(src, _cc)};
|
||||
}
|
||||
|
||||
private:
|
||||
CC _cc;
|
||||
private:
|
||||
CC _cc;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
||||
/// \ingroup ImageViewTransformationsFlipUD
|
||||
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename dynamic_y_step_type<any_image_view<ViewTypes> >::type flipped_up_down_view(const any_image_view<ViewTypes>& src) {
|
||||
return apply_operation(src,detail::flipped_up_down_view_fn<typename dynamic_y_step_type<any_image_view<ViewTypes> >::type>());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto flipped_up_down_view(any_image_view<Views...> const& src)
|
||||
-> typename dynamic_y_step_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using result_view_t = typename dynamic_y_step_type<any_image_view<Views...>>::type;
|
||||
return variant2::visit(detail::flipped_up_down_view_fn<result_view_t>(), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsFlipLR
|
||||
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename dynamic_x_step_type<any_image_view<ViewTypes> >::type flipped_left_right_view(const any_image_view<ViewTypes>& src) {
|
||||
return apply_operation(src,detail::flipped_left_right_view_fn<typename dynamic_x_step_type<any_image_view<ViewTypes> >::type>());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto flipped_left_right_view(any_image_view<Views...> const& src)
|
||||
-> typename dynamic_x_step_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using result_view_t = typename dynamic_x_step_type<any_image_view<Views...>>::type;
|
||||
return variant2::visit(detail::flipped_left_right_view_fn<result_view_t>(), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsTransposed
|
||||
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type transposed_view(const any_image_view<ViewTypes>& src) {
|
||||
return apply_operation(src,detail::tranposed_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto transposed_view(any_image_view<Views...> const& src)
|
||||
-> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
|
||||
return variant2::visit(detail::tranposed_view_fn<result_view_t>(), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformations90CW
|
||||
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type rotated90cw_view(const any_image_view<ViewTypes>& src) {
|
||||
return apply_operation(src,detail::rotated90cw_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto rotated90cw_view(any_image_view<Views...> const& src)
|
||||
-> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
|
||||
return variant2::visit(detail::rotated90cw_view_fn<result_view_t>(), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformations90CCW
|
||||
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type rotated90ccw_view(const any_image_view<ViewTypes>& src) {
|
||||
return apply_operation(src,detail::rotated90ccw_view_fn<typename dynamic_xy_step_transposed_type<any_image_view<ViewTypes> >::type>());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto rotated90ccw_view(any_image_view<Views...> const& src)
|
||||
-> typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using result_view_t = typename dynamic_xy_step_transposed_type<any_image_view<Views...>>::type;
|
||||
return variant2::visit(detail::rotated90ccw_view_fn<result_view_t>(), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformations180
|
||||
/// Models MPL Random Access Container of models of ImageViewConcept
|
||||
template <typename ViewTypes>
|
||||
inline auto rotated180_view(const any_image_view<ViewTypes>& src)
|
||||
-> typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto rotated180_view(any_image_view<Views...> const& src)
|
||||
-> typename dynamic_xy_step_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using step_type = typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type;
|
||||
return apply_operation(src, detail::rotated180_view_fn<step_type>());
|
||||
using result_view_t = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
|
||||
return variant2::visit(detail::rotated180_view_fn<result_view_t>(), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsSubimage
|
||||
/// // Models MPL Random Access Container of models of ImageViewConcept
|
||||
template <typename ViewTypes>
|
||||
inline auto subimage_view(any_image_view<ViewTypes> const& src,
|
||||
point_t const& topleft, point_t const& dimensions)
|
||||
-> any_image_view<ViewTypes>
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto subimage_view(
|
||||
any_image_view<Views...> const& src,
|
||||
point_t const& topleft,
|
||||
point_t const& dimensions)
|
||||
-> any_image_view<Views...>
|
||||
{
|
||||
using subimage_view_fn = detail::subimage_view_fn<any_image_view<ViewTypes>>;
|
||||
return apply_operation(src, subimage_view_fn(topleft, dimensions));
|
||||
using subimage_view_fn = detail::subimage_view_fn<any_image_view<Views...>>;
|
||||
return variant2::visit(subimage_view_fn(topleft, dimensions), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsSubimage
|
||||
/// Models MPL Random Access Container of models of ImageViewConcept
|
||||
template <typename ViewTypes>
|
||||
inline auto subimage_view(any_image_view<ViewTypes> const& src,
|
||||
int xMin, int yMin, int width, int height)
|
||||
-> any_image_view<ViewTypes>
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto subimage_view(
|
||||
any_image_view<Views...> const& src,
|
||||
std::ptrdiff_t x_min, std::ptrdiff_t y_min, std::ptrdiff_t width, std::ptrdiff_t height)
|
||||
-> any_image_view<Views...>
|
||||
{
|
||||
using subimage_view_fn = detail::subimage_view_fn<any_image_view<ViewTypes>>;
|
||||
return apply_operation(src, subimage_view_fn(point_t(xMin, yMin),point_t(width, height)));
|
||||
using subimage_view_fn = detail::subimage_view_fn<any_image_view<Views...>>;
|
||||
return variant2::visit(subimage_view_fn(point_t(x_min, y_min),point_t(width, height)), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsSubsampled
|
||||
/// Models MPL Random Access Container of models of ImageViewConcept
|
||||
template <typename ViewTypes>
|
||||
inline auto subsampled_view(any_image_view<ViewTypes> const& src, point_t const& step)
|
||||
-> typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto subsampled_view(any_image_view<Views...> const& src, point_t const& step)
|
||||
-> typename dynamic_xy_step_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using step_type = typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type;
|
||||
using step_type = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
|
||||
using subsampled_view = detail::subsampled_view_fn<step_type>;
|
||||
return apply_operation(src, subsampled_view(step));
|
||||
return variant2::visit(subsampled_view(step), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsSubsampled
|
||||
/// Models MPL Random Access Container of models of ImageViewConcept
|
||||
template <typename ViewTypes>
|
||||
inline auto subsampled_view(any_image_view<ViewTypes> const& src, int xStep, int yStep)
|
||||
-> typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto subsampled_view(any_image_view<Views...> const& src, std::ptrdiff_t x_step, std::ptrdiff_t y_step)
|
||||
-> typename dynamic_xy_step_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using step_type = typename dynamic_xy_step_type<any_image_view<ViewTypes>>::type;
|
||||
using step_type = typename dynamic_xy_step_type<any_image_view<Views...>>::type;
|
||||
using subsampled_view_fn = detail::subsampled_view_fn<step_type>;
|
||||
return apply_operation(src, subsampled_view_fn(point_t(xStep, yStep)));
|
||||
return variant2::visit(subsampled_view_fn(point_t(x_step, y_step)), src);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename View> struct get_nthchannel_type { using type = typename nth_channel_view_type<View>::type; };
|
||||
template <typename Views> struct views_get_nthchannel_type : public mpl::transform<Views, get_nthchannel_type<mpl::_1> > {};
|
||||
}
|
||||
|
||||
template <typename View>
|
||||
struct get_nthchannel_type { using type = typename nth_channel_view_type<View>::type; };
|
||||
|
||||
template <typename Views>
|
||||
struct views_get_nthchannel_type : mp11::mp_transform<get_nthchannel_type, Views> {};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \ingroup ImageViewTransformationsNthChannel
|
||||
/// \brief Given a runtime source image view, returns the type of a runtime image view over a single channel of the source view
|
||||
template <typename ViewTypes>
|
||||
struct nth_channel_view_type<any_image_view<ViewTypes> > {
|
||||
using type = any_image_view<typename detail::views_get_nthchannel_type<ViewTypes>::type>;
|
||||
template <typename ...Views>
|
||||
struct nth_channel_view_type<any_image_view<Views...>>
|
||||
{
|
||||
using type = typename detail::views_get_nthchannel_type<any_image_view<Views...>>;
|
||||
};
|
||||
|
||||
/// \ingroup ImageViewTransformationsNthChannel
|
||||
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename nth_channel_view_type<any_image_view<ViewTypes> >::type nth_channel_view(const any_image_view<ViewTypes>& src, int n) {
|
||||
return apply_operation(src,detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes> >::type>(n));
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename ...Views>
|
||||
inline
|
||||
auto nth_channel_view(any_image_view<Views...> const& src, int n)
|
||||
-> typename nth_channel_view_type<any_image_view<Views...>>::type
|
||||
{
|
||||
using result_view_t = typename nth_channel_view_type<any_image_view<Views...>>::type;
|
||||
return variant2::visit(detail::nth_channel_view_fn<result_view_t>(n), src);
|
||||
}
|
||||
|
||||
namespace detail {
|
||||
template <typename View, typename DstP, typename CC> struct get_ccv_type : public color_converted_view_type<View, DstP, CC> {};
|
||||
template <typename Views, typename DstP, typename CC> struct views_get_ccv_type : public mpl::transform<Views, get_ccv_type<mpl::_1,DstP,CC> > {};
|
||||
}
|
||||
|
||||
template <typename View, typename DstP, typename CC>
|
||||
struct get_ccv_type : color_converted_view_type<View, DstP, CC> {};
|
||||
|
||||
template <typename Views, typename DstP, typename CC>
|
||||
struct views_get_ccv_type
|
||||
{
|
||||
private:
|
||||
// FIXME: Remove class name injection with detail:: qualification
|
||||
// Required as workaround for MP11 issue that treats unqualified metafunction
|
||||
// in the class definition of the same name as the specialization (Peter Dimov):
|
||||
// invalid template argument for template parameter 'F', expected a class template
|
||||
template <typename T>
|
||||
using ccvt = detail::get_ccv_type<T, DstP, CC>;
|
||||
|
||||
public:
|
||||
using type = mp11::mp_transform<ccvt, Views>;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/// \ingroup ImageViewTransformationsColorConvert
|
||||
/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with user specified color converter
|
||||
template <typename ViewTypes, typename DstP, typename CC>
|
||||
struct color_converted_view_type<any_image_view<ViewTypes>,DstP,CC>
|
||||
template <typename ...Views, typename DstP, typename CC>
|
||||
struct color_converted_view_type<any_image_view<Views...>,DstP,CC>
|
||||
{
|
||||
using type = any_image_view<typename detail::views_get_ccv_type<ViewTypes, DstP, CC>::type>;
|
||||
//using type = any_image_view<typename detail::views_get_ccv_type<Views, DstP, CC>::type>;
|
||||
using type = detail::views_get_ccv_type<any_image_view<Views...>, 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) {
|
||||
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename DstP, typename ...Views, typename CC>
|
||||
inline
|
||||
auto color_converted_view(any_image_view<Views...> const& src, CC)
|
||||
-> typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type
|
||||
{
|
||||
using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type;
|
||||
return variant2::visit(detail::color_converted_view_fn<DstP, cc_view_t>(), src);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsColorConvert
|
||||
/// \brief Returns the type of a runtime-specified view, color-converted to a given pixel type with the default coor converter
|
||||
template <typename ViewTypes, typename DstP>
|
||||
struct color_converted_view_type<any_image_view<ViewTypes>,DstP>
|
||||
template <typename ...Views, typename DstP>
|
||||
struct color_converted_view_type<any_image_view<Views...>,DstP>
|
||||
{
|
||||
using type = any_image_view<typename detail::views_get_ccv_type<ViewTypes, DstP, default_color_converter>::type>;
|
||||
using type = detail::views_get_ccv_type<any_image_view<Views...>, DstP, default_color_converter>;
|
||||
};
|
||||
|
||||
/// \ingroup ImageViewTransformationsColorConvert
|
||||
/// \brief overload of generic color_converted_view with the default color-converter
|
||||
template <typename DstP, typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type color_converted_view(const any_image_view<ViewTypes>& src) {
|
||||
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type >());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename DstP, typename ...Views>
|
||||
inline
|
||||
auto color_converted_view(any_image_view<Views...> const& src)
|
||||
-> typename color_converted_view_type<any_image_view<Views...>, DstP>::type
|
||||
{
|
||||
using cc_view_t = typename color_converted_view_type<any_image_view<Views...>, DstP>::type;
|
||||
return variant2::visit(detail::color_converted_view_fn<DstP, cc_view_t>(), src);
|
||||
}
|
||||
|
||||
|
||||
/// \ingroup ImageViewTransformationsColorConvert
|
||||
/// \brief overload of generic color_converted_view with user defined color-converter
|
||||
/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
|
||||
template <typename DstP, typename ViewTypes, typename CC> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type any_color_converted_view(const any_image_view<ViewTypes>& src, CC) {
|
||||
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP, CC>::type >());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename DstP, typename ...Views, typename CC>
|
||||
[[deprecated("Use color_converted_view(const any_image_view<Views...>& src, CC) instead.")]]
|
||||
inline
|
||||
auto any_color_converted_view(const any_image_view<Views...>& src, CC cc)
|
||||
-> typename color_converted_view_type<any_image_view<Views...>, DstP, CC>::type
|
||||
{
|
||||
return color_converted_view(src, cc);
|
||||
}
|
||||
|
||||
/// \ingroup ImageViewTransformationsColorConvert
|
||||
/// \brief overload of generic color_converted_view with the default color-converter
|
||||
/// These are workarounds for GCC 3.4, which thinks color_converted_view is ambiguous with the same method for templated views (in gil/image_view_factory.hpp)
|
||||
template <typename DstP, typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
|
||||
typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type any_color_converted_view(const any_image_view<ViewTypes>& src) {
|
||||
return apply_operation(src,detail::color_converted_view_fn<DstP,typename color_converted_view_type<any_image_view<ViewTypes>, DstP>::type >());
|
||||
/// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept
|
||||
template <typename DstP, typename ...Views>
|
||||
[[deprecated("Use color_converted_view(any_image_view<Views...> const& src) instead.")]]
|
||||
inline
|
||||
auto any_color_converted_view(const any_image_view<Views...>& src)
|
||||
-> typename color_converted_view_type<any_image_view<Views...>, DstP>::type
|
||||
{
|
||||
return color_converted_view(src);
|
||||
}
|
||||
|
||||
/// \}
|
||||
|
||||
} } // namespace boost::gil
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,832 +0,0 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
#ifndef BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_GIL_REDUCE_HPP
|
||||
#define BOOST_GIL_EXTENSION_DYNAMIC_IMAGE_GIL_REDUCE_HPP
|
||||
|
||||
#ifdef BOOST_GIL_DOXYGEN_ONLY
|
||||
#undef BOOST_GIL_REDUCE_CODE_BLOAT
|
||||
#endif
|
||||
|
||||
#ifdef BOOST_GIL_REDUCE_CODE_BLOAT
|
||||
|
||||
#include <boost/gil/extension/dynamic_image/dynamic_at_c.hpp>
|
||||
|
||||
#include <boost/gil/metafunctions.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
|
||||
#include <boost/mpl/back.hpp>
|
||||
#include <boost/mpl/insert.hpp>
|
||||
#include <boost/mpl/insert_range.hpp>
|
||||
#include <boost/mpl/long.hpp>
|
||||
#include <boost/mpl/logical.hpp>
|
||||
#include <boost/mpl/range_c.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/mpl/vector_c.hpp>
|
||||
#include <boost/mpl/transform.hpp>
|
||||
|
||||
// Max number of cases in the cross-expension of binary operation for it to be reduced as unary
|
||||
#define GIL_BINARY_REDUCE_LIMIT 226
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
|
||||
// Constructs for static-to-dynamic integer convesion
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
/// Mapping vector - represents the mapping of one type vector to another
|
||||
/// It is not a full-blown MPL Random Access Type sequence; just has at_c and size implemented
|
||||
///
|
||||
/// SrcTypes, DstTypes: MPL Random Access Type Sequences
|
||||
///
|
||||
/// Implements size and at_c to behave as if this is an MPL vector of integers
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
template <typename SrcTypes, typename DstTypes>
|
||||
struct mapping_vector {};
|
||||
|
||||
template <typename SrcTypes, typename DstTypes, long K>
|
||||
struct at_c<mapping_vector<SrcTypes,DstTypes>, K>
|
||||
{
|
||||
static const std::size_t value=size<DstTypes>::value - order<DstTypes, typename gil::at_c<SrcTypes,K>::type>::type::value +1;
|
||||
using type = size_t<value>;
|
||||
};
|
||||
|
||||
template <typename SrcTypes, typename DstTypes>
|
||||
struct size<mapping_vector<SrcTypes,DstTypes>>
|
||||
{
|
||||
using type = typename size<SrcTypes>::type;
|
||||
static const std::size_t value=type::value;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
/// copy_to_vector - copies a sequence (mpl::set) to vector.
|
||||
///
|
||||
/// Temporary solution because I couldn't get mpl::copy to do this.
|
||||
/// This is what I tried:
|
||||
/// mpl::copy<SET, mpl::back_inserter<mpl::vector<>>>::type;
|
||||
/// It works when SET is mpl::vector, but not when SET is mpl::set...
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
template <typename SFirst, std::size_t NLeft>
|
||||
struct copy_to_vector_impl {
|
||||
private:
|
||||
using T = typename deref<SFirst>::type;
|
||||
using next = typename next<SFirst>::type;
|
||||
using rest = typename copy_to_vector_impl<next, NLeft-1>::type;
|
||||
public:
|
||||
using type = typename push_front<rest, T>::type;
|
||||
};
|
||||
|
||||
template <typename SFirst>
|
||||
struct copy_to_vector_impl<SFirst,1>
|
||||
{
|
||||
using type = vector<typename deref<SFirst>::type>;
|
||||
};
|
||||
}
|
||||
|
||||
template <typename Src>
|
||||
struct copy_to_vector
|
||||
{
|
||||
using type = typename detail::copy_to_vector_impl<typename begin<Src>::type, size<Src>::value>::type;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct copy_to_vector<set<>>
|
||||
{
|
||||
using type = vector0<>;
|
||||
};
|
||||
|
||||
} } // boost::mpl
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
///
|
||||
/// unary_reduce, binary_reduce - given an MPL Random Access Sequence,
|
||||
/// dynamically specified index to that container, the bits of an instance of the corresponding type and
|
||||
/// a generic operation, invokes the operation on the given type
|
||||
///
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
///
|
||||
/// \brief Unary reduce.
|
||||
///
|
||||
/// Given a set of types and an operation, reduces each type in the set (to reduced_t), then removes duplicates (to unique_t)
|
||||
/// To apply the operation, first constructs a lookup table that maps each element from Types to its place in unique_t and uses it to map
|
||||
/// the index to anther index (in map_index). Then invokes apply_operation_base on the unique types with the new index.
|
||||
///
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
template <typename Types, typename Op>
|
||||
struct unary_reduce_impl {
|
||||
using reduced_t = typename mpl::transform<Types, detail::reduce<Op, mpl::_1> >::type;
|
||||
using unique_t = typename mpl::copy<reduced_t, mpl::inserter<mpl::set<>, mpl::insert<mpl::_1,mpl::_2>>>::type;
|
||||
static const bool is_single=mpl::size<unique_t>::value==1;
|
||||
};
|
||||
|
||||
template <typename Types, typename Op, bool IsSingle=unary_reduce_impl<Types,Op>::is_single>
|
||||
struct unary_reduce : public unary_reduce_impl<Types,Op>
|
||||
{
|
||||
using reduced_t = typename unary_reduce_impl<Types,Op>::reduced_t;
|
||||
using unique_t = typename unary_reduce_impl<Types,Op>::unique_t;
|
||||
|
||||
static unsigned short inline map_index(std::size_t index)
|
||||
{
|
||||
using indices_t = typename mpl::mapping_vector<reduced_t, unique_t>;
|
||||
return gil::at_c<indices_t, unsigned short>(index);
|
||||
}
|
||||
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> 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);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Types, typename Op>
|
||||
struct unary_reduce<Types,Op,true> : public unary_reduce_impl<Types,Op> {
|
||||
using unique_t = typename unary_reduce_impl<Types,Op>::unique_t;
|
||||
static unsigned short inline map_index(std::size_t index) { return 0; }
|
||||
|
||||
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> 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));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
///
|
||||
/// \brief Binary reduce.
|
||||
///
|
||||
/// Given two sets of types, Types1 and Types2, first performs unary reduction on each. Then checks if the product of their sizes is above
|
||||
/// the GIL_BINARY_REDUCE_LIMIT limit. If so, the operation is too complex to be binary-reduced and uses a specialization of binary_reduce_impl
|
||||
/// to simply call the binary apply_operation_base (which performs two nested 1D apply operations)
|
||||
/// If the operation is not too complex, uses the other specialization of binary_reduce_impl to create a cross-product of the input types
|
||||
/// and performs unary reduction on the result (bin_reduced_t). To apply the binary operation, it simply invokes a unary apply_operation_base
|
||||
/// on the reduced cross-product types
|
||||
///
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
namespace detail {
|
||||
struct pair_generator {
|
||||
template <typename Vec2> struct apply
|
||||
{
|
||||
using type = std::pair<const typename mpl::at_c<Vec2,0>::type*, const typename mpl::at_c<Vec2,1>::type*>;
|
||||
};
|
||||
};
|
||||
|
||||
// When the types are not too large, applies reduce on their cross product
|
||||
template <typename Unary1, typename Unary2, typename Op, bool IsComplex>
|
||||
struct binary_reduce_impl
|
||||
{
|
||||
//private:
|
||||
using vec1_types = typename mpl::copy_to_vector<typename Unary1::unique_t>::type;
|
||||
using vec2_types = typename mpl::copy_to_vector<typename Unary2::unique_t>::type;
|
||||
|
||||
using BIN_TYPES = mpl::cross_vector<mpl::vector2<vec1_types, vec2_types>, pair_generator>;
|
||||
using bin_reduced_t = unary_reduce<BIN_TYPES,Op>;
|
||||
|
||||
static unsigned short inline map_index(std::size_t index1, std::size_t index2) {
|
||||
unsigned short r1=Unary1::map_index(index1);
|
||||
unsigned short r2=Unary2::map_index(index2);
|
||||
return bin_reduced_t::map_index(r2*mpl::size<vec1_types>::value + r1);
|
||||
}
|
||||
public:
|
||||
using unique_t = typename bin_reduced_t::unique_t
|
||||
|
||||
template <typename Bits1, typename Bits2>
|
||||
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
|
||||
std::pair<const void*,const void*> pr(&bits1, &bits2);
|
||||
return apply_operation_basec<unique_t>(pr, map_index(index1,index2),op);
|
||||
}
|
||||
};
|
||||
|
||||
// When the types are large performs a double-dispatch. Binary reduction is not done.
|
||||
template <typename Unary1, typename Unary2, typename Op>
|
||||
struct binary_reduce_impl<Unary1,Unary2,Op,true> {
|
||||
template <typename Bits1, typename Bits2>
|
||||
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
|
||||
return apply_operation_base<Unary1::unique_t,Unary2::unique_t>(bits1, index1, bits2, index2, op);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
template <typename Types1, typename Types2, typename Op>
|
||||
struct binary_reduce
|
||||
{
|
||||
//private:
|
||||
using unary1_t = unary_reduce<Types1,Op>;
|
||||
using unary2_t = unary_reduce<Types2,Op>;
|
||||
|
||||
static const std::size_t CROSS_SIZE = mpl::size<typename unary1_t::unique_t>::value *
|
||||
mpl::size<typename unary2_t::unique_t>::value;
|
||||
|
||||
using impl = detail::binary_reduce_impl<unary1_t,unary2_t,Op, (CROSS_SIZE>GIL_BINARY_REDUCE_LIMIT)>;
|
||||
public:
|
||||
template <typename Bits1, typename Bits2>
|
||||
static typename Op::result_type inline apply(const Bits1& bits1, std::size_t index1, const Bits2& bits2, std::size_t index2, Op op) {
|
||||
return impl::apply(bits1,index1,bits2,index2,op);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Types, typename UnaryOp>
|
||||
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>
|
||||
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>
|
||||
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);
|
||||
}
|
||||
|
||||
#undef GIL_BINARY_REDUCE_LIMIT
|
||||
|
||||
} } // namespace gil
|
||||
|
||||
|
||||
namespace boost { namespace mpl {
|
||||
///////////////////////////////////////////////////////
|
||||
/// \brief Represents the virtual cross-product of the types generated from VecOfVecs.
|
||||
/// \ingroup CrossVector
|
||||
/// INPUT:
|
||||
/// VecOfVecs - a vector of vector types. For example [ [A1,A2,A3], [B1,B2], [C1,C2,C3,C4] ]
|
||||
/// Each element must be a non-empty mpl vector
|
||||
/// TypeGen - a metafunction that generates a type from a vector of types, each of which can be
|
||||
/// selected from the corresponding vector in VecOfVecs. For example, [A1, B2, C4]
|
||||
///
|
||||
/// Represents the virtual cross-product of the types generated from VecOfVecs.
|
||||
/// For example, [ TypeGen[A1,B1,C1], TypeGen[A2,B1,C1], TypeGen[A3,B1,C1],
|
||||
/// TypeGen[A1,B2,C1], TypeGen[A2,B2,C1], TypeGen[A3,B2,C1],
|
||||
/// TypeGen[A1,B1,C2], TypeGen[A2,B1,C2], TypeGen[A3,B1,C2], ... ]
|
||||
///
|
||||
/// Models an immutable MPL Random Access Sequence
|
||||
/// Traversal, random-access, etc, is defined, but mutable operations,
|
||||
/// such as push_back and pop_front are not supported
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
template <typename VecOfVecs, typename TypeGen>
|
||||
struct cross_vector {};
|
||||
|
||||
/// \brief Iterator of cross_vector
|
||||
/// \ingroup CrossVectorIterator
|
||||
template <typename VecOfVecs, typename TypeGen, std::size_t K>
|
||||
struct cross_iterator
|
||||
{
|
||||
using category = mpl::random_access_iterator_tag;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
/// Implementation of the iterator functions of cross vector
|
||||
///////////////////////////////////////////////////////
|
||||
|
||||
/// \brief Dereferences a cross-vector iterator
|
||||
/// \ingroup CrossVectorIterator
|
||||
/// Creates a vector of the sizes of each type vector in VecOfVecs, then uses it as a basis
|
||||
/// to represent the iterator's position K as a vector of indices. Extracts the corresponding type of
|
||||
/// each input vector and passes the element types to the type generation function, which returns the dereferenced type
|
||||
template <typename VecOfVecs, typename TypeGen, std::size_t K>
|
||||
struct deref<cross_iterator<VecOfVecs,TypeGen,K>>
|
||||
{
|
||||
private:
|
||||
using DerefTypes = typename detail::select_subvector_c<VecOfVecs, K>::type;
|
||||
public:
|
||||
using type = typename TypeGen::template apply<DerefTypes>::type;
|
||||
};
|
||||
|
||||
/// \brief Increments a cross-vector iterator.
|
||||
/// \ingroup CrossVectorIterator
|
||||
template <typename VecOfVecs, typename TypeGen, std::size_t K>
|
||||
struct next<cross_iterator<VecOfVecs,TypeGen,K>>
|
||||
{
|
||||
using type = cross_iterator<VecOfVecs,TypeGen,K+1>;
|
||||
};
|
||||
|
||||
/// \brief Decrements a cross-vector iterator.
|
||||
/// \ingroup CrossVectorIterator
|
||||
template <typename VecOfVecs, typename TypeGen, std::size_t K>
|
||||
struct prior<cross_iterator<VecOfVecs,TypeGen,K>>
|
||||
{
|
||||
using type = cross_iterator<VecOfVecs,TypeGen,K-1>;
|
||||
};
|
||||
|
||||
/// \brief Advances a cross-vector iterator.
|
||||
/// \ingroup CrossVectorIterator
|
||||
template <typename VecOfVecs, typename TypeGen, std::size_t K, typename Distance>
|
||||
struct advance<cross_iterator<VecOfVecs,TypeGen,K>, Distance>
|
||||
{
|
||||
using type = cross_iterator<VecOfVecs,TypeGen,K+Distance::value>;
|
||||
};
|
||||
|
||||
/// \brief Computes the distance between two cross-vector iterator-s.
|
||||
/// \ingroup CrossVectorIterator
|
||||
// (shortened the names of the template arguments - otherwise doxygen cannot parse this...)
|
||||
template <typename VecOfVecs, typename TypeGen, std::size_t K1, std::size_t K2>
|
||||
struct distance<cross_iterator<VecOfVecs,TypeGen,K1>, cross_iterator<VecOfVecs,TypeGen,K2>>
|
||||
{
|
||||
using type = size_t<K2-K1>;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
/// Implementation of cross vector
|
||||
///////////////////////////////////////////////////////
|
||||
/// \brief Computes the size of a cross vector as the product of the sizes of all vectors in VecOfVecs
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen>
|
||||
struct size<cross_vector<VecOfVecs,TypeGen>>
|
||||
{
|
||||
using type = typename fold<VecOfVecs, size_t<1>, times<_1, size<_2>>>::type;
|
||||
static const std::size_t value=type::value;
|
||||
};
|
||||
|
||||
/// \brief Determines whether a cross vector is empty
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen>
|
||||
struct empty<cross_vector<VecOfVecs,TypeGen>> {
|
||||
using type = typename empty<VecOfVecs>::type;
|
||||
};
|
||||
|
||||
/// \brief Returns the K-th element of a cross vector
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen, typename K>
|
||||
struct at<cross_vector<VecOfVecs,TypeGen>, K>
|
||||
{
|
||||
private:
|
||||
using KthIterator = cross_iterator<VecOfVecs,TypeGen,K::value>;
|
||||
public:
|
||||
using type = typename deref<KthIterator>::type;
|
||||
};
|
||||
|
||||
/// \brief Returns an iterator to the first element of a cross vector
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen>
|
||||
struct begin<cross_vector<VecOfVecs,TypeGen>>
|
||||
{
|
||||
using type = cross_iterator<VecOfVecs,TypeGen,0>;
|
||||
};
|
||||
|
||||
/// \brief Returns an iterator to the last element of a cross vector
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen>
|
||||
struct end<cross_vector<VecOfVecs,TypeGen>>
|
||||
{
|
||||
private:
|
||||
using this_t = cross_vector<VecOfVecs,TypeGen>;
|
||||
public:
|
||||
using type = cross_iterator<VecOfVecs,TypeGen,size<this_t>::value>;
|
||||
};
|
||||
|
||||
/// \brief Returns the first element of a cross vector
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen>
|
||||
struct front<cross_vector<VecOfVecs,TypeGen>> {
|
||||
private:
|
||||
using this_t = cross_vector<VecOfVecs,TypeGen>;
|
||||
public:
|
||||
using type = typename deref<typename begin<this_t>::type>::type;
|
||||
};
|
||||
|
||||
/// \brief Returns the last element of a cross vector
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen>
|
||||
struct back<cross_vector<VecOfVecs,TypeGen>>
|
||||
{
|
||||
private:
|
||||
using this_t = cross_vector<VecOfVecs,TypeGen>;
|
||||
using size = typename size<this_t>::type;
|
||||
using last_index = typename minus<size, size_t<1>>::type;
|
||||
public:
|
||||
using type = typename at<this_t, last_index>::type;
|
||||
};
|
||||
|
||||
/// \brief Transforms the elements of a cross vector
|
||||
/// \ingroup CrossVector
|
||||
template <typename VecOfVecs, typename TypeGen, typename OPP>
|
||||
struct transform<cross_vector<VecOfVecs,TypeGen>, OPP>
|
||||
{
|
||||
using Op = typename lambda<OPP>::type;
|
||||
struct adapter
|
||||
{
|
||||
template <typename Elements>
|
||||
struct apply
|
||||
{
|
||||
using orig_t = typename TypeGen::template apply<Elements>::type;
|
||||
using type = typename Op::template apply<orig_t>::type;
|
||||
};
|
||||
};
|
||||
using type = cross_vector<VecOfVecs, adapter>;
|
||||
};
|
||||
|
||||
} } // boost::mpl
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
template <typename Types, typename T> struct type_to_index;
|
||||
template <typename V> struct view_is_basic;
|
||||
struct rgb_t;
|
||||
struct lab_t;
|
||||
struct hsb_t;
|
||||
struct cmyk_t;
|
||||
struct rgba_t;
|
||||
struct error_t;
|
||||
|
||||
|
||||
namespace detail {
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Generic reduce operation
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
template <typename Op, typename T>
|
||||
struct reduce
|
||||
{
|
||||
using type = T;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Unary reduce_view operation. Splits into basic and non-basic views.
|
||||
//// Algorithm-specific reduce should specialize for basic views
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Op, typename View, bool IsBasic>
|
||||
struct reduce_view_basic
|
||||
{
|
||||
using type = View;
|
||||
};
|
||||
|
||||
template <typename Op, typename Loc>
|
||||
struct reduce<Op, image_view<Loc>>
|
||||
: public reduce_view_basic<Op,image_view<Loc>,view_is_basic<image_view<Loc>>::value> {};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Unary reduce_image operation. Splits into basic and non-basic images.
|
||||
//// Algorithm-specific reduce should specialize for basic images
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Op, typename Img, bool IsBasic>
|
||||
struct reduce_image_basic
|
||||
{
|
||||
using type = Img;
|
||||
};
|
||||
|
||||
template <typename Op, typename V, typename Alloc>
|
||||
struct reduce<Op, image<V,Alloc>> : public reduce_image_basic<Op,image<V,Alloc>,image_is_basic<image<V,Alloc>>::value > {};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Binary reduce_view operation. Splits into basic and non-basic views.
|
||||
//// Algorithm-specific reduce should specialize for basic views
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Op, typename V1, typename V2, bool AreBasic>
|
||||
struct reduce_views_basic
|
||||
{
|
||||
using type = std::pair<const V1*, const V2*>;
|
||||
};
|
||||
|
||||
template <typename Op, typename L1, typename L2>
|
||||
struct reduce<Op, std::pair<const image_view<L1>*, const image_view<L2>*>>
|
||||
: public reduce_views_basic<Op,image_view<L1>,image_view<L2>,
|
||||
mpl::and_<view_is_basic<image_view<L1>>, view_is_basic<image_view<L2>>>::value >
|
||||
{};
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Color space unary reduce operation. Reduce a color space to a base with the same number of channels
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
template <typename CS>
|
||||
struct reduce_color_space
|
||||
{
|
||||
using type = CS;
|
||||
};
|
||||
|
||||
template <> struct reduce_color_space<lab_t> { using type = rgb_t; };
|
||||
template <> struct reduce_color_space<hsb_t> { using type = rgb_t; };
|
||||
template <> struct reduce_color_space<cmyk_t> { using type = rgba_t; };
|
||||
|
||||
/*
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Color space binary reduce operation. Given a source and destination color spaces,
|
||||
//// returns a reduced source and destination color spaces that have the same mapping of channels
|
||||
////
|
||||
//// Precondition: The two color spaces must be compatible (i.e. must have the same set of channels)
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Vec, int Basis, int VecSize>
|
||||
struct type_vec_to_integer_impl {
|
||||
using last = typename mpl::back<Vec>::type;
|
||||
using rest = typename mpl::pop_back<Vec>::type;
|
||||
static const int value = type_vec_to_integer_impl<rest, Basis, VecSize-1>::value * Basis + last::value;
|
||||
};
|
||||
|
||||
template <typename Vec, int Basis>
|
||||
struct type_vec_to_integer_impl<Vec,Basis,0> {
|
||||
static const int value=0;
|
||||
};
|
||||
|
||||
template <typename Vec, int Basis=10>
|
||||
struct type_vec_to_integer {
|
||||
static const int value = type_vec_to_integer_impl<Vec,Basis, mpl::size<Vec>::value>::value;
|
||||
};
|
||||
|
||||
// Given two color spaces and the mapping of the channels between them, returns the reduced pair of color spaces
|
||||
// The default version performs no reduction
|
||||
template <typename SrcColorSpace, typename DstColorSpace, int Mapping>
|
||||
struct reduce_color_spaces_impl {
|
||||
using first_t = SrcColorSpace;
|
||||
using second_t = DstColorSpace;
|
||||
};
|
||||
|
||||
// 012: RGB-RGB, bgr-bgr, lab-lab, hsb-hsb
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,12> {
|
||||
using first_t = rgb_t;
|
||||
using second_t = rgb_t;
|
||||
};
|
||||
|
||||
// 210: RGB-bgr, bgr-RGB
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,210> {
|
||||
using first_t = rgb_t;
|
||||
using second_t = bgr_t;
|
||||
};
|
||||
|
||||
// 0123: RGBA-RGBA, bgra-bgra, argb-argb, abgr-abgr cmyk-cmyk
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,123> {
|
||||
using first_t = rgba_t;
|
||||
using second_t = rgba_t;
|
||||
};
|
||||
|
||||
// 3210: RGBA-abgr, bgra-argb, argb-bgra, abgr-RGBA
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3210> {
|
||||
using first_t = rgba_t;
|
||||
using second_t = abgr_t;
|
||||
};
|
||||
|
||||
// 1230: RGBA-argb, bgra-abgr
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,1230> {
|
||||
using first_t = rgba_t;
|
||||
using second_t = argb_t;
|
||||
};
|
||||
|
||||
// 2103: RGBA-bgra, bgra-RGBA (uses subclass to ensure that base color space is not reduced to derived)
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,2103> {
|
||||
using first_t = rgba_t;
|
||||
using second_t = bgra_t;
|
||||
};
|
||||
|
||||
// 3012: argb-RGBA, abgr-bgra
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,3012> {
|
||||
using first_t = argb_t;
|
||||
using second_t = rgba_t;
|
||||
};
|
||||
|
||||
// 0321: argb-abgr, abgr-argb
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,321> {
|
||||
using first_t = argb_t;
|
||||
using second_t = abgr_t;
|
||||
};
|
||||
|
||||
template <typename SrcColorSpace, typename DstColorSpace>
|
||||
struct reduce_color_spaces {
|
||||
using src_order_t = typename channel_order<SrcColorSpace>::type;
|
||||
using dst_order_t = typename channel_order<DstColorSpace>::type;
|
||||
using mapping = typename mpl::transform<src_order_t, type_to_index<dst_order_t,mpl::_1>>::type;
|
||||
static const int mapping_val = type_vec_to_integer<mapping>::value;
|
||||
|
||||
using _first_t = typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::first_t;
|
||||
using _second_t = typename reduce_color_spaces_impl<SrcColorSpace,DstColorSpace,mapping_val>::second_t;
|
||||
using swap_t = typename mpl::and_<color_space_is_base<DstColorSpace>, mpl::not_< color_space_is_base<_second_t>>>;
|
||||
public:
|
||||
using first_t = typename mpl::if_<swap_t, _second_t, _first_t>::type;
|
||||
using second_t = typename mpl::if_<swap_t, _first_t, _second_t>::type;
|
||||
};
|
||||
*/
|
||||
// TODO: Use the old code for reduce_color_spaces above to do color layout reduction
|
||||
template <typename SrcLayout, typename DstLayout>
|
||||
struct reduce_color_layouts
|
||||
{
|
||||
using first_t = SrcLayout;
|
||||
using second_t = DstLayout;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Reduce for copy_pixels
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
struct copy_pixels_fn;
|
||||
|
||||
/*
|
||||
// 1D reduce for copy_pixels reduces the channel to mutable and the color space to its base with same dimensions
|
||||
template <typename View>
|
||||
struct reduce_view_basic<copy_pixels_fn,View,true> {
|
||||
private:
|
||||
using color_space_t = typename reduce_color_space<typename View::color_space_t>::type color_space_t; // reduce the color space
|
||||
using layout_t = layout<color_space_t, typename View::channel_mapping_t>;
|
||||
public:
|
||||
using type = typename derived_view_type<View, use_default, layout_t, use_default, use_default, mpl::true_>::type;
|
||||
};
|
||||
*/
|
||||
// Incompatible views cannot be used in copy_pixels - will throw std::bad_cast
|
||||
template <typename V1, typename V2, bool Compatible>
|
||||
struct reduce_copy_pixop_compat
|
||||
{
|
||||
using type = error_t;
|
||||
};
|
||||
|
||||
// For compatible basic views, reduce their color spaces based on their channel mapping.
|
||||
// Make the source immutable and the destination mutable (they should already be that way)
|
||||
template <typename V1, typename V2>
|
||||
struct reduce_copy_pixop_compat<V1,V2,true>
|
||||
{
|
||||
using layout1 = layout<typename V1::color_space_t, typename V1::channel_mapping_t>;
|
||||
using layout2 = layout<typename V2::color_space_t, typename V2::channel_mapping_t>;
|
||||
|
||||
using L1 = typename reduce_color_layouts<layout1,layout2>::first_t;
|
||||
using L2 = typename reduce_color_layouts<layout1,layout2>::second_t;
|
||||
|
||||
using DV1 = typename derived_view_type<V1, use_default, L1, use_default, use_default, use_default, mpl::false_>::type;
|
||||
using DV2 = typename derived_view_type<V2, use_default, L2, use_default, use_default, use_default, mpl::true_ >::type;
|
||||
|
||||
using type = std::pair<const DV1*, const DV2*>;
|
||||
};
|
||||
|
||||
// The general 2D version branches into compatible and incompatible views
|
||||
template <typename V1, typename V2>
|
||||
struct reduce_views_basic<copy_pixels_fn, V1, V2, true>
|
||||
: public reduce_copy_pixop_compat<V1, V2, mpl::and_<views_are_compatible<V1,V2>, view_is_mutable<V2>>::value > {
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Reduce for variant destructor (basic views have no destructor)
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
struct destructor_op;
|
||||
template <typename View>
|
||||
struct reduce_view_basic<destructor_op,View,true>
|
||||
{
|
||||
using type = gray8_view_t;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Reduce for get_dimensions (basic views and images have the same structure and the dimensions are contained at the beginning)
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
struct any_type_get_dimensions;
|
||||
|
||||
template <typename View>
|
||||
struct reduce_view_basic<any_type_get_dimensions,View,true>
|
||||
{
|
||||
using type = gray8_view_t;
|
||||
};
|
||||
|
||||
template <typename Img>
|
||||
struct reduce_image_basic<any_type_get_dimensions,Img,true>
|
||||
{
|
||||
using type = gray8_image_t;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Reduce for get_num_channels (only color space matters)
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
struct any_type_get_num_channels;
|
||||
|
||||
template <typename View>
|
||||
struct reduce_view_basic<any_type_get_num_channels,View,true>
|
||||
{
|
||||
using color_space_t = typename View::color_space_t::base;
|
||||
using type = typename view_type<uint8_t,typename reduce_color_space<color_space_t>::type>::type;
|
||||
};
|
||||
|
||||
template <typename Img>
|
||||
struct reduce_image_basic<any_type_get_num_channels,Img,true>
|
||||
{
|
||||
using color_space_t = typename Img::color_space_t::base;
|
||||
using type = typename image_type<uint8_t,typename reduce_color_space<color_space_t>::type>::type;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Reduce for resample_pixels (same as copy_pixels)
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
template <typename Sampler, typename MapFn> struct resample_pixels_fn;
|
||||
|
||||
template <typename S, typename M, typename V, bool IsBasic>
|
||||
struct reduce_view_basic<resample_pixels_fn<S,M>, V, IsBasic> : public reduce_view_basic<copy_pixels_fn, V, IsBasic> {};
|
||||
|
||||
template <typename S, typename M, typename V1, typename V2, bool IsBasic>
|
||||
struct reduce_views_basic<resample_pixels_fn<S,M>, V1, V2, IsBasic> : public reduce_views_basic<copy_pixels_fn, V1, V2, IsBasic> {};
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
////
|
||||
//// Reduce for copy_and_convert_pixels
|
||||
//// (the only reduction could be made when views are compatible and have the same mapping, planarity and stepness)
|
||||
////
|
||||
////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
template <typename CC> class copy_and_convert_pixels_fn;
|
||||
|
||||
// the only thing for 1D reduce is making them all mutable...
|
||||
template <typename CC, typename View, bool IsBasic>
|
||||
struct reduce_view_basic<copy_and_convert_pixels_fn<CC>, View, IsBasic>
|
||||
: public derived_view_type<View, use_default, use_default, use_default, use_default, mpl::true_> {
|
||||
};
|
||||
|
||||
// For 2D reduce, if they have the same channels and color spaces (i.e. the same pixels) then copy_and_convert is just copy.
|
||||
// In this case, reduce their common color space. In general make the first immutable and the second mutable
|
||||
template <typename CC, typename V1, typename V2, bool AreBasic>
|
||||
struct reduce_views_basic<copy_and_convert_pixels_fn<CC>, V1, V2, AreBasic>
|
||||
{
|
||||
using Same = is_same<typename V1::pixel_t, typename V2::pixel_t>;
|
||||
|
||||
using CsR = reduce_color_space<typename V1::color_space_t::base>;
|
||||
using Cs1 = typename mpl::if_<Same, typename CsR::type, typename V1::color_space_t>::type;
|
||||
using Cs2 = typename mpl::if_<Same, typename CsR::type, typename V2::color_space_t>::type;
|
||||
|
||||
using DV1 = typename derived_view_type<V1, use_default, layout<Cs1, typename V1::channel_mapping_t>, use_default, use_default, mpl::false_>::type;
|
||||
using DV2 = typename derived_view_type<V2, use_default, layout<Cs2, typename V2::channel_mapping_t>, use_default, use_default, mpl::true_ >::type;
|
||||
|
||||
using type = std::pair<const DV1*, const DV2*>;
|
||||
};
|
||||
|
||||
|
||||
//integral_image_generator
|
||||
//resize_clobber_image_fnobj
|
||||
//image_default_construct_fnobj
|
||||
//fill_converted_pixels_fn
|
||||
//std::bind(gil::detail::copy_pixels_fn(), std::placeholders::_1, dst)
|
||||
//std::bind(gil::detail::copy_pixels_fn(), src, std::placeholders::_1)
|
||||
|
||||
//std::bind(detail::copy_and_convert_pixels_fn(), std::placeholders::_1, dst)
|
||||
//std::bind(detail::copy_and_convert_pixels_fn(), src, std::placeholders::_1)
|
||||
//gil::detail::fill_pixels_fn<Value>(val)
|
||||
|
||||
//detail::copy_construct_in_place_fn<base_t>
|
||||
//detail::equal_to_fn<typename variant<Types>::base_t>
|
||||
|
||||
//detail::any_image_get_view<typename any_image<Types>::view_t>
|
||||
//detail::any_image_get_const_view<typename any_image<Types>::view_t>
|
||||
//detail::flipped_up_down_view_fn<any_image_view<ViewTypes>>
|
||||
//detail::flipped_left_right_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
|
||||
//detail::tranposed_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
|
||||
//detail::rotated90cw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
|
||||
//detail::rotated90ccw_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
|
||||
//detail::rotated180_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
|
||||
//detail::subimage_view_fn<any_image_view<ViewTypes>>
|
||||
//detail::subsampled_view_fn<typename any_image_view<ViewTypes>::dynamic_step_t>
|
||||
//detail::nth_channel_view_fn<typename nth_channel_view_type<any_image_view<ViewTypes>>
|
||||
//detail::color_converted_view_fn<DstP,typename color_convert_view_type<any_image_view<ViewTypes>, DstP>::type >
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif // defined(BOOST_GIL_REDUCE_CODE_BLOAT)
|
||||
|
||||
#endif
|
||||
172
linx64/include/boost/gil/extension/histogram/std.hpp
Normal file
172
linx64/include/boost/gil/extension/histogram/std.hpp
Normal file
@@ -0,0 +1,172 @@
|
||||
//
|
||||
// Copyright 2020 Debabrata Mandal <mandaldebabrata123@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#ifndef BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
|
||||
#define BOOST_GIL_EXTENSION_HISTOGRAM_STL_HISTOGRAM_HPP
|
||||
|
||||
#include <boost/gil/concepts/concept_check.hpp>
|
||||
#include <boost/gil/gray.hpp>
|
||||
#include <boost/gil/histogram.hpp>
|
||||
#include <boost/gil/image_view.hpp>
|
||||
#include <boost/gil/image_view_factory.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
/// Histogram extension for STL container
|
||||
//////////////////////////////////////////////////////////
|
||||
/// \defgroup Histogram - STL Containers
|
||||
/// \brief Collection of functions to provide histogram support in GIL using Standard
|
||||
/// Template Library Containers
|
||||
/// The conversion from Boost.GIL images to compatible histograms are provided. The supported
|
||||
/// container types would be std::vector, std::array, std::map.
|
||||
///
|
||||
/// Some general constraints on STL extension:-
|
||||
/// 1. Supports only 1D histogram.
|
||||
/// 2. Cannot use signed images with compatible random access containers.
|
||||
/// 3. Automatic resize of std::array in case of shortage of bins, to ensure
|
||||
/// correctness comes before performance.
|
||||
/// 4. Container key type (if exists) has to be one of std::integral types to be
|
||||
/// GIL compatible.
|
||||
/// 5. Container value type has to be of std::arithmetic types.
|
||||
///
|
||||
|
||||
///
|
||||
/// \ingroup Histogram - STL Containers
|
||||
/// \brief Overload for std::vector of fill_histogram
|
||||
///
|
||||
template <typename SrcView, typename T>
|
||||
void fill_histogram(SrcView const& srcview, std::vector<T>& histogram, bool accumulate = false)
|
||||
{
|
||||
gil_function_requires<ImageViewConcept<SrcView>>();
|
||||
static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
|
||||
static_assert(
|
||||
std::is_unsigned<typename channel_type<SrcView>::type>::value,
|
||||
"Improper container type for signed images.");
|
||||
|
||||
using channel_t = typename channel_type<SrcView>::type;
|
||||
using pixel_t = pixel<channel_t, gray_layout_t>;
|
||||
|
||||
if (!accumulate)
|
||||
histogram.clear();
|
||||
histogram.resize(std::numeric_limits<channel_t>::max() + 1);
|
||||
|
||||
for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
|
||||
++histogram[static_cast<std::size_t>(p)];
|
||||
});
|
||||
}
|
||||
|
||||
/// \ingroup Histogram - STL Containers
|
||||
/// \brief Overload for std::array of fill_histogram
|
||||
///
|
||||
template <typename SrcView, typename T, std::size_t N>
|
||||
void fill_histogram(SrcView const& srcview, std::array<T, N>& histogram, bool accumulate = false)
|
||||
{
|
||||
gil_function_requires<ImageViewConcept<SrcView>>();
|
||||
static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
|
||||
static_assert(
|
||||
std::is_unsigned<typename channel_type<SrcView>::type>::value,
|
||||
"Improper container type for signed images.");
|
||||
|
||||
using channel_t = typename channel_type<SrcView>::type;
|
||||
using pixel_t = pixel<channel_t, gray_layout_t>;
|
||||
|
||||
const size_t pixel_max = std::numeric_limits<channel_t>::max();
|
||||
const float scale = (histogram.size() - 1.0f) / pixel_max;
|
||||
|
||||
if (!accumulate)
|
||||
std::fill(std::begin(histogram), std::end(histogram), 0);
|
||||
|
||||
for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
|
||||
++histogram[static_cast<std::size_t>(p * scale)];
|
||||
});
|
||||
}
|
||||
|
||||
/// \ingroup Histogram - STL Containers
|
||||
/// \brief Overload for std::map of fill_histogram
|
||||
///
|
||||
template <typename SrcView, typename T1, typename T2>
|
||||
void fill_histogram(SrcView const& srcview, std::map<T1, T2>& histogram, bool accumulate = false)
|
||||
{
|
||||
gil_function_requires<ImageViewConcept<SrcView>>();
|
||||
static_assert(
|
||||
std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
|
||||
"Improper container type for images.");
|
||||
|
||||
using channel_t = typename channel_type<SrcView>::type;
|
||||
using pixel_t = pixel<channel_t, gray_layout_t>;
|
||||
|
||||
if (!accumulate)
|
||||
histogram.clear();
|
||||
|
||||
for_each_pixel(color_converted_view<pixel_t>(srcview), [&](pixel_t const& p) {
|
||||
++histogram[static_cast<std::size_t>(p)];
|
||||
});
|
||||
}
|
||||
|
||||
/// \ingroup Histogram - STL Containers
|
||||
/// \brief Overload for std::vector of cumulative_histogram
|
||||
///
|
||||
template <typename T>
|
||||
std::vector<T> cumulative_histogram(std::vector<T>& hist)
|
||||
{
|
||||
std::vector<T> cumulative_hist(hist.size());
|
||||
static_assert(std::is_arithmetic<T>::value, "Improper container type for images.");
|
||||
T cumulative_counter = 0;
|
||||
for (std::size_t i = 0; i < hist.size(); i++)
|
||||
{
|
||||
cumulative_counter += hist[i];
|
||||
cumulative_hist[i] = cumulative_counter;
|
||||
}
|
||||
return cumulative_hist;
|
||||
}
|
||||
|
||||
/// \ingroup Histogram - STL Containers
|
||||
/// \brief Overload for std::array of cumulative_histogram
|
||||
///
|
||||
template <typename T, std::size_t N>
|
||||
std::array<T, N> cumulative_histogram(std::array<T, N>& histogram)
|
||||
{
|
||||
std::array<T, N> cumulative_hist;
|
||||
static_assert(std::is_arithmetic<T>::value && N > 0, "Improper container type for images.");
|
||||
T cumulative_counter = 0;
|
||||
for (std::size_t i = 0; i < N; i++)
|
||||
{
|
||||
cumulative_counter += histogram[i];
|
||||
cumulative_hist[i] = cumulative_counter;
|
||||
}
|
||||
return cumulative_hist;
|
||||
}
|
||||
|
||||
/// \ingroup Histogram - STL Containers
|
||||
/// \brief Overload for std::map of cumulative_histogram
|
||||
///
|
||||
template <typename T1, typename T2>
|
||||
std::map<T1, T2> cumulative_histogram(std::map<T1, T2>& histogram)
|
||||
{
|
||||
std::map<T1, T2> cumulative_hist;
|
||||
static_assert(
|
||||
std::is_arithmetic<T1>::value && std::is_integral<T2>::value,
|
||||
"Improper container type for images.");
|
||||
T2 cumulative_counter = 0;
|
||||
for (auto const& it : histogram)
|
||||
{
|
||||
cumulative_counter += it.second;
|
||||
cumulative_hist[it.first] = cumulative_counter;
|
||||
}
|
||||
return cumulative_hist;
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,426 @@
|
||||
//
|
||||
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
|
||||
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// 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_IMAGE_PROCESSING_DIFFUSION_HPP
|
||||
#define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_DIFFUSION_HPP
|
||||
|
||||
#include <boost/gil/detail/math.hpp>
|
||||
#include <boost/gil/algorithm.hpp>
|
||||
#include <boost/gil/color_base_algorithm.hpp>
|
||||
#include <boost/gil/image.hpp>
|
||||
#include <boost/gil/image_view.hpp>
|
||||
#include <boost/gil/image_view_factory.hpp>
|
||||
#include <boost/gil/pixel.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
namespace conductivity {
|
||||
struct perona_malik_conductivity
|
||||
{
|
||||
double kappa;
|
||||
template <typename Pixel>
|
||||
Pixel operator()(Pixel input)
|
||||
{
|
||||
using channel_type = typename channel_type<Pixel>::type;
|
||||
// C++11 doesn't seem to capture members
|
||||
static_transform(input, input, [this](channel_type value) {
|
||||
value /= kappa;
|
||||
return std::exp(-std::abs(value));
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
struct gaussian_conductivity
|
||||
{
|
||||
double kappa;
|
||||
template <typename Pixel>
|
||||
Pixel operator()(Pixel input)
|
||||
{
|
||||
using channel_type = typename channel_type<Pixel>::type;
|
||||
// C++11 doesn't seem to capture members
|
||||
static_transform(input, input, [this](channel_type value) {
|
||||
value /= kappa;
|
||||
return std::exp(-value * value);
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
struct wide_regions_conductivity
|
||||
{
|
||||
double kappa;
|
||||
template <typename Pixel>
|
||||
Pixel operator()(Pixel input)
|
||||
{
|
||||
using channel_type = typename channel_type<Pixel>::type;
|
||||
// C++11 doesn't seem to capture members
|
||||
static_transform(input, input, [this](channel_type value) {
|
||||
value /= kappa;
|
||||
return 1.0 / (1.0 + value * value);
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
};
|
||||
|
||||
struct more_wide_regions_conductivity
|
||||
{
|
||||
double kappa;
|
||||
template <typename Pixel>
|
||||
Pixel operator()(Pixel input)
|
||||
{
|
||||
using channel_type = typename channel_type<Pixel>::type;
|
||||
// C++11 doesn't seem to capture members
|
||||
static_transform(input, input, [this](channel_type value) {
|
||||
value /= kappa;
|
||||
return 1.0 / std::sqrt((1.0 + value * value));
|
||||
});
|
||||
|
||||
return input;
|
||||
}
|
||||
};
|
||||
} // namespace diffusion
|
||||
|
||||
/**
|
||||
\brief contains discrete approximations of 2D Laplacian operator
|
||||
*/
|
||||
namespace laplace_function {
|
||||
// The functions assume clockwise enumeration of stencil points, as such
|
||||
// NW North NE 0 1 2 (-1, -1) (0, -1) (+1, -1)
|
||||
// West East ===> 7 3 ===> (-1, 0) (+1, 0)
|
||||
// SW South SE 6 5 4 (-1, +1) (0, +1) (+1, +1)
|
||||
|
||||
/**
|
||||
\brief This function makes sure all Laplace functions enumerate
|
||||
values in the same order and direction.
|
||||
|
||||
The first element is difference North West direction, second in North,
|
||||
and so on in clockwise manner. Leave element as zero if it is not
|
||||
to be computed.
|
||||
*/
|
||||
inline std::array<gil::point_t, 8> get_directed_offsets()
|
||||
{
|
||||
return {point_t{-1, -1}, point_t{0, -1}, point_t{+1, -1}, point_t{+1, 0},
|
||||
point_t{+1, +1}, point_t{0, +1}, point_t{-1, +1}, point_t{-1, 0}};
|
||||
}
|
||||
|
||||
template <typename PixelType>
|
||||
using stencil_type = std::array<PixelType, 8>;
|
||||
|
||||
/**
|
||||
\brief 5 point stencil approximation of Laplacian
|
||||
|
||||
Only main 4 directions are non-zero, the rest are zero
|
||||
*/
|
||||
struct stencil_5points
|
||||
{
|
||||
double delta_t = 0.25;
|
||||
|
||||
template <typename SubImageView>
|
||||
stencil_type<typename SubImageView::value_type> compute_laplace(SubImageView view,
|
||||
point_t origin)
|
||||
{
|
||||
auto current = view(origin);
|
||||
stencil_type<typename SubImageView::value_type> stencil;
|
||||
using channel_type = typename channel_type<typename SubImageView::value_type>::type;
|
||||
std::array<gil::point_t, 8> offsets(get_directed_offsets());
|
||||
typename SubImageView::value_type zero_pixel;
|
||||
static_fill(zero_pixel, 0);
|
||||
for (std::size_t index = 0; index < offsets.size(); ++index)
|
||||
{
|
||||
if (index % 2 != 0)
|
||||
{
|
||||
static_transform(view(origin.x + offsets[index].x, origin.y + offsets[index].y),
|
||||
current, stencil[index], std::minus<channel_type>{});
|
||||
}
|
||||
else
|
||||
{
|
||||
stencil[index] = zero_pixel;
|
||||
}
|
||||
}
|
||||
return stencil;
|
||||
}
|
||||
|
||||
template <typename Pixel>
|
||||
Pixel reduce(const stencil_type<Pixel>& stencil)
|
||||
{
|
||||
using channel_type = typename channel_type<Pixel>::type;
|
||||
auto result = []() {
|
||||
Pixel zero_pixel;
|
||||
static_fill(zero_pixel, channel_type(0));
|
||||
return zero_pixel;
|
||||
}();
|
||||
|
||||
for (std::size_t index : {1u, 3u, 5u, 7u})
|
||||
{
|
||||
static_transform(result, stencil[index], result, std::plus<channel_type>{});
|
||||
}
|
||||
Pixel delta_t_pixel;
|
||||
static_fill(delta_t_pixel, delta_t);
|
||||
static_transform(result, delta_t_pixel, result, std::multiplies<channel_type>{});
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
\brief 9 point stencil approximation of Laplacian
|
||||
|
||||
This is full 8 way approximation, though diagonal
|
||||
elements are halved during reduction.
|
||||
*/
|
||||
struct stencil_9points_standard
|
||||
{
|
||||
double delta_t = 0.125;
|
||||
|
||||
template <typename SubImageView>
|
||||
stencil_type<typename SubImageView::value_type> compute_laplace(SubImageView view,
|
||||
point_t origin)
|
||||
{
|
||||
stencil_type<typename SubImageView::value_type> stencil;
|
||||
auto out = stencil.begin();
|
||||
auto current = view(origin);
|
||||
using channel_type = typename channel_type<typename SubImageView::value_type>::type;
|
||||
std::array<gil::point_t, 8> offsets(get_directed_offsets());
|
||||
for (auto offset : offsets)
|
||||
{
|
||||
static_transform(view(origin.x + offset.x, origin.y + offset.y), current, *out++,
|
||||
std::minus<channel_type>{});
|
||||
}
|
||||
|
||||
return stencil;
|
||||
}
|
||||
|
||||
template <typename Pixel>
|
||||
Pixel reduce(const stencil_type<Pixel>& stencil)
|
||||
{
|
||||
using channel_type = typename channel_type<Pixel>::type;
|
||||
auto result = []() {
|
||||
Pixel zero_pixel;
|
||||
static_fill(zero_pixel, channel_type(0));
|
||||
return zero_pixel;
|
||||
}();
|
||||
for (std::size_t index : {1u, 3u, 5u, 7u})
|
||||
{
|
||||
static_transform(result, stencil[index], result, std::plus<channel_type>{});
|
||||
}
|
||||
|
||||
for (std::size_t index : {0u, 2u, 4u, 6u})
|
||||
{
|
||||
Pixel half_pixel;
|
||||
static_fill(half_pixel, channel_type(1 / 2.0));
|
||||
static_transform(stencil[index], half_pixel, half_pixel,
|
||||
std::multiplies<channel_type>{});
|
||||
static_transform(result, half_pixel, result, std::plus<channel_type>{});
|
||||
}
|
||||
|
||||
Pixel delta_t_pixel;
|
||||
static_fill(delta_t_pixel, delta_t);
|
||||
static_transform(result, delta_t_pixel, result, std::multiplies<channel_type>{});
|
||||
|
||||
return result;
|
||||
}
|
||||
};
|
||||
} // namespace laplace_function
|
||||
|
||||
namespace brightness_function {
|
||||
using laplace_function::stencil_type;
|
||||
struct identity
|
||||
{
|
||||
template <typename Pixel>
|
||||
stencil_type<Pixel> operator()(const stencil_type<Pixel>& stencil)
|
||||
{
|
||||
return stencil;
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Figure out how to implement color gradient brightness, as it
|
||||
// seems to need dx and dy using sobel or scharr kernels
|
||||
|
||||
struct rgb_luminance
|
||||
{
|
||||
using pixel_type = rgb32f_pixel_t;
|
||||
stencil_type<pixel_type> operator()(const stencil_type<pixel_type>& stencil)
|
||||
{
|
||||
stencil_type<pixel_type> output;
|
||||
std::transform(stencil.begin(), stencil.end(), output.begin(), [](const pixel_type& pixel) {
|
||||
float32_t luminance = 0.2126f * pixel[0] + 0.7152f * pixel[1] + 0.0722f * pixel[2];
|
||||
pixel_type result_pixel;
|
||||
static_fill(result_pixel, luminance);
|
||||
return result_pixel;
|
||||
});
|
||||
return output;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace brightness_function
|
||||
|
||||
enum class matlab_connectivity
|
||||
{
|
||||
minimal,
|
||||
maximal
|
||||
};
|
||||
|
||||
enum class matlab_conduction_method
|
||||
{
|
||||
exponential,
|
||||
quadratic
|
||||
};
|
||||
|
||||
template <typename InputView, typename OutputView>
|
||||
void classic_anisotropic_diffusion(const InputView& input, const OutputView& output,
|
||||
unsigned int num_iter, double kappa)
|
||||
{
|
||||
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
|
||||
brightness_function::identity{},
|
||||
conductivity::perona_malik_conductivity{kappa});
|
||||
}
|
||||
|
||||
template <typename InputView, typename OutputView>
|
||||
void matlab_anisotropic_diffusion(const InputView& input, const OutputView& output,
|
||||
unsigned int num_iter, double kappa,
|
||||
matlab_connectivity connectivity,
|
||||
matlab_conduction_method conduction_method)
|
||||
{
|
||||
if (connectivity == matlab_connectivity::minimal)
|
||||
{
|
||||
if (conduction_method == matlab_conduction_method::exponential)
|
||||
{
|
||||
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
|
||||
brightness_function::identity{},
|
||||
conductivity::gaussian_conductivity{kappa});
|
||||
}
|
||||
else if (conduction_method == matlab_conduction_method::quadratic)
|
||||
{
|
||||
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
|
||||
brightness_function::identity{},
|
||||
conductivity::gaussian_conductivity{kappa});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error("unhandled conduction method found");
|
||||
}
|
||||
}
|
||||
else if (connectivity == matlab_connectivity::maximal)
|
||||
{
|
||||
if (conduction_method == matlab_conduction_method::exponential)
|
||||
{
|
||||
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
|
||||
brightness_function::identity{},
|
||||
conductivity::gaussian_conductivity{kappa});
|
||||
}
|
||||
else if (conduction_method == matlab_conduction_method::quadratic)
|
||||
{
|
||||
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_5points{},
|
||||
brightness_function::identity{},
|
||||
conductivity::gaussian_conductivity{kappa});
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error("unhandled conduction method found");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw std::logic_error("unhandled connectivity found");
|
||||
}
|
||||
}
|
||||
|
||||
template <typename InputView, typename OutputView>
|
||||
void default_anisotropic_diffusion(const InputView& input, const OutputView& output,
|
||||
unsigned int num_iter, double kappa)
|
||||
{
|
||||
anisotropic_diffusion(input, output, num_iter, laplace_function::stencil_9points_standard{},
|
||||
brightness_function::identity{}, conductivity::gaussian_conductivity{kappa});
|
||||
}
|
||||
|
||||
/// \brief Performs diffusion according to Perona-Malik equation
|
||||
///
|
||||
/// WARNING: Output channel type must be floating point,
|
||||
/// otherwise there will be loss in accuracy which most
|
||||
/// probably will lead to incorrect results (input will be unchanged).
|
||||
/// Anisotropic diffusion is a smoothing algorithm that respects
|
||||
/// edge boundaries and can work as an edge detector if suitable
|
||||
/// iteration count is set and grayscale image view is used
|
||||
/// as an input
|
||||
template <typename InputView, typename OutputView,
|
||||
typename LaplaceStrategy = laplace_function::stencil_9points_standard,
|
||||
typename BrightnessFunction = brightness_function::identity,
|
||||
typename DiffusivityFunction = conductivity::gaussian_conductivity>
|
||||
void anisotropic_diffusion(const InputView& input, const OutputView& output, unsigned int num_iter,
|
||||
LaplaceStrategy laplace, BrightnessFunction brightness,
|
||||
DiffusivityFunction diffusivity)
|
||||
{
|
||||
using input_pixel_type = typename InputView::value_type;
|
||||
using pixel_type = typename OutputView::value_type;
|
||||
using channel_type = typename channel_type<pixel_type>::type;
|
||||
using computation_image = image<pixel_type>;
|
||||
const auto width = input.width();
|
||||
const auto height = input.height();
|
||||
const auto zero_pixel = []() {
|
||||
pixel_type pixel;
|
||||
static_fill(pixel, static_cast<channel_type>(0));
|
||||
|
||||
return pixel;
|
||||
}();
|
||||
computation_image result_image(width + 2, height + 2, zero_pixel);
|
||||
auto result = view(result_image);
|
||||
computation_image scratch_result_image(width + 2, height + 2, zero_pixel);
|
||||
auto scratch_result = view(scratch_result_image);
|
||||
transform_pixels(input, subimage_view(result, 1, 1, width, height),
|
||||
[](const input_pixel_type& pixel) {
|
||||
pixel_type converted;
|
||||
for (std::size_t i = 0; i < num_channels<pixel_type>{}; ++i)
|
||||
{
|
||||
converted[i] = pixel[i];
|
||||
}
|
||||
return converted;
|
||||
});
|
||||
|
||||
for (unsigned int iteration = 0; iteration < num_iter; ++iteration)
|
||||
{
|
||||
for (std::ptrdiff_t relative_y = 0; relative_y < height; ++relative_y)
|
||||
{
|
||||
for (std::ptrdiff_t relative_x = 0; relative_x < width; ++relative_x)
|
||||
{
|
||||
auto x = relative_x + 1;
|
||||
auto y = relative_y + 1;
|
||||
auto stencil = laplace.compute_laplace(result, point_t(x, y));
|
||||
auto brightness_stencil = brightness(stencil);
|
||||
laplace_function::stencil_type<pixel_type> diffusivity_stencil;
|
||||
std::transform(brightness_stencil.begin(), brightness_stencil.end(),
|
||||
diffusivity_stencil.begin(), diffusivity);
|
||||
laplace_function::stencil_type<pixel_type> product_stencil;
|
||||
std::transform(stencil.begin(), stencil.end(), diffusivity_stencil.begin(),
|
||||
product_stencil.begin(), [](pixel_type lhs, pixel_type rhs) {
|
||||
static_transform(lhs, rhs, lhs, std::multiplies<channel_type>{});
|
||||
return lhs;
|
||||
});
|
||||
static_transform(result(x, y), laplace.reduce(product_stencil),
|
||||
scratch_result(x, y), std::plus<channel_type>{});
|
||||
}
|
||||
}
|
||||
using std::swap;
|
||||
swap(result, scratch_result);
|
||||
}
|
||||
|
||||
copy_pixels(subimage_view(result, 1, 1, width, height), output);
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,113 @@
|
||||
// Boost.GIL (Generic Image Library) - tests
|
||||
//
|
||||
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
|
||||
//
|
||||
// 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_IMAGE_PROCESSING_HOUGH_PARAMETER_HPP
|
||||
#define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_PARAMETER_HPP
|
||||
|
||||
#include "boost/gil/point.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
|
||||
namespace boost
|
||||
{
|
||||
namespace gil
|
||||
{
|
||||
/// \ingroup HoughTransform
|
||||
/// \brief A type to encapsulate Hough transform parameter range
|
||||
///
|
||||
/// This type provides a way to express value range for a parameter
|
||||
/// as well as some factory functions to simplify initialization
|
||||
template <typename T>
|
||||
struct hough_parameter
|
||||
{
|
||||
T start_point;
|
||||
T step_size;
|
||||
std::size_t step_count;
|
||||
|
||||
/// \ingroup HoughTransform
|
||||
/// \brief Create Hough parameter from value neighborhood and step count
|
||||
///
|
||||
/// This function will take start_point as middle point, and in both
|
||||
/// directions will try to walk half_step_count times until distance of
|
||||
/// neighborhood is reached
|
||||
static hough_parameter<T> from_step_count(T start_point, T neighborhood,
|
||||
std::size_t half_step_count)
|
||||
{
|
||||
T step_size = neighborhood / half_step_count;
|
||||
std::size_t step_count = half_step_count * 2 + 1;
|
||||
// explicitly fill out members, as aggregate init will error out with narrowing
|
||||
hough_parameter<T> parameter;
|
||||
parameter.start_point = start_point - neighborhood;
|
||||
parameter.step_size = step_size;
|
||||
parameter.step_count = step_count;
|
||||
return parameter;
|
||||
}
|
||||
|
||||
/// \ingroup HoughTransform
|
||||
/// \brief Create Hough parameter from value neighborhood and step size
|
||||
///
|
||||
/// This function will take start_point as middle point, and in both
|
||||
/// directions will try to walk step_size at a time until distance of
|
||||
/// neighborhood is reached
|
||||
static hough_parameter<T> from_step_size(T start_point, T neighborhood, T step_size)
|
||||
{
|
||||
std::size_t step_count =
|
||||
2 * static_cast<std::size_t>(std::floor(neighborhood / step_size)) + 1;
|
||||
// do not use step_size - neighborhood, as step_size might not allow
|
||||
// landing exactly on that value when starting from start_point
|
||||
// also use parentheses on step_count / 2 because flooring is exactly
|
||||
// what we want
|
||||
|
||||
// explicitly fill out members, as aggregate init will error out with narrowing
|
||||
hough_parameter<T> parameter;
|
||||
parameter.start_point = start_point - step_size * (step_count / 2);
|
||||
parameter.step_size = step_size;
|
||||
parameter.step_count = step_count;
|
||||
return parameter;
|
||||
}
|
||||
};
|
||||
|
||||
/// \ingroup HoughTransform
|
||||
/// \brief Calculate minimum angle which would be observable if walked on a circle
|
||||
///
|
||||
/// When drawing a circle or moving around a point in circular motion, it is
|
||||
/// important to not do too many steps, but also to not have disconnected
|
||||
/// trajectory. This function will calculate the minimum angle that is observable
|
||||
/// when walking on a circle or tilting a line.
|
||||
/// WARNING: do keep in mind IEEE 754 quirks, e.g. no-associativity,
|
||||
/// no-commutativity and precision. Do not expect expressions that are
|
||||
/// mathematically the same to produce the same values
|
||||
inline double minimum_angle_step(point_t dimensions)
|
||||
{
|
||||
auto longer_dimension = dimensions.x > dimensions.y ? dimensions.x : dimensions.y;
|
||||
return std::atan2(1, longer_dimension);
|
||||
}
|
||||
|
||||
/// \ingroup HoughTransform
|
||||
/// \brief Create a Hough transform parameter with optimal angle step
|
||||
///
|
||||
/// Due to computational intensity and noise sensitivity of Hough transform,
|
||||
/// having any candidates missed or computed again is problematic. This function
|
||||
/// will properly encapsulate optimal value range around approx_angle with amplitude of
|
||||
/// neighborhood in each direction.
|
||||
/// WARNING: do keep in mind IEEE 754 quirks, e.g. no-associativity,
|
||||
/// no-commutativity and precision. Do not expect expressions that are
|
||||
/// mathematically the same to produce the same values
|
||||
inline auto make_theta_parameter(double approx_angle, double neighborhood, point_t dimensions)
|
||||
-> hough_parameter<double>
|
||||
{
|
||||
auto angle_step = minimum_angle_step(dimensions);
|
||||
|
||||
// std::size_t step_count =
|
||||
// 2 * static_cast<std::size_t>(std::floor(neighborhood / angle_step)) + 1;
|
||||
// return {approx_angle - angle_step * (step_count / 2), angle_step, step_count};
|
||||
return hough_parameter<double>::from_step_size(approx_angle, neighborhood, angle_step);
|
||||
}
|
||||
}} // namespace boost::gil
|
||||
#endif
|
||||
@@ -0,0 +1,138 @@
|
||||
// Boost.GIL (Generic Image Library) - tests
|
||||
//
|
||||
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
|
||||
//
|
||||
// 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_IMAGE_PROCESSING_HOUGH_TRANSFORM_HPP
|
||||
#define BOOST_GIL_EXTENSION_IMAGE_PROCESSING_HOUGH_TRANSFORM_HPP
|
||||
|
||||
#include <boost/gil/extension/image_processing/hough_parameter.hpp>
|
||||
#include <boost/gil/extension/rasterization/circle.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
/// \defgroup HoughTransform
|
||||
/// \brief A family of shape detectors that are specified by equation
|
||||
///
|
||||
/// Hough transform is a method of mapping (voting) an object which can be described by
|
||||
/// equation to single point in accumulator array (also called parameter space).
|
||||
/// Each set pixel in edge map votes for every shape it can be part of.
|
||||
/// Circle and ellipse transforms are very costly to brute force, while
|
||||
/// non-brute-forcing algorithms tend to gamble on probabilities.
|
||||
|
||||
/// \ingroup HoughTransform
|
||||
/// \brief Vote for best fit of a line in parameter space
|
||||
///
|
||||
/// The input must be an edge map with grayscale pixels. Be aware of overflow inside
|
||||
/// accumulator array. The theta parameter is best computed through factory function
|
||||
/// provided in hough_parameter.hpp
|
||||
template <typename InputView, typename OutputView>
|
||||
void hough_line_transform(InputView const& input_view, OutputView const& accumulator_array,
|
||||
hough_parameter<double> const& theta,
|
||||
hough_parameter<std::ptrdiff_t> const& radius)
|
||||
{
|
||||
std::ptrdiff_t r_lower_bound = radius.start_point;
|
||||
std::ptrdiff_t r_upper_bound = r_lower_bound + radius.step_size * (radius.step_count - 1);
|
||||
|
||||
for (std::ptrdiff_t y = 0; y < input_view.height(); ++y)
|
||||
{
|
||||
for (std::ptrdiff_t x = 0; x < input_view.width(); ++x)
|
||||
{
|
||||
if (!input_view(x, y)[0])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (std::size_t theta_index = 0; theta_index < theta.step_count; ++theta_index)
|
||||
{
|
||||
double theta_current =
|
||||
theta.start_point + theta.step_size * static_cast<double>(theta_index);
|
||||
std::ptrdiff_t current_r =
|
||||
std::llround(static_cast<double>(x) * std::cos(theta_current) +
|
||||
static_cast<double>(y) * std::sin(theta_current));
|
||||
if (current_r < r_lower_bound || current_r > r_upper_bound)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
std::size_t r_index = static_cast<std::size_t>(
|
||||
std::llround((current_r - radius.start_point) / radius.step_size));
|
||||
// one more safety guard to not get out of bounds
|
||||
if (r_index < radius.step_count)
|
||||
{
|
||||
accumulator_array(theta_index, r_index)[0] += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \ingroup HoughTransform
|
||||
/// \brief Vote for best fit of a circle in parameter space according to rasterizer
|
||||
///
|
||||
/// The input must be an edge map with grayscale pixels. Be aware of overflow inside
|
||||
/// accumulator array. Rasterizer is used to rasterize a circle for voting. The circle
|
||||
/// then is translated for every origin (x, y) in x y parameter space. For available
|
||||
/// circle rasterizers, please look at rasterization/circle.hpp
|
||||
template <typename ImageView, typename ForwardIterator, typename Rasterizer>
|
||||
void hough_circle_transform_brute(ImageView const& input,
|
||||
hough_parameter<std::ptrdiff_t> const& radius_parameter,
|
||||
hough_parameter<std::ptrdiff_t> const& x_parameter,
|
||||
hough_parameter<std::ptrdiff_t> const& y_parameter,
|
||||
ForwardIterator d_first, Rasterizer rasterizer)
|
||||
{
|
||||
for (std::size_t radius_index = 0; radius_index < radius_parameter.step_count; ++radius_index)
|
||||
{
|
||||
const auto radius = radius_parameter.start_point +
|
||||
radius_parameter.step_size * static_cast<std::ptrdiff_t>(radius_index);
|
||||
Rasterizer rasterizer{point_t{}, radius};
|
||||
std::vector<point_t> circle_points(rasterizer.point_count());
|
||||
rasterizer(circle_points.begin());
|
||||
// sort by scanline to improve cache coherence for row major images
|
||||
std::sort(circle_points.begin(), circle_points.end(),
|
||||
[](point_t const& lhs, point_t const& rhs) { return lhs.y < rhs.y; });
|
||||
const auto translate = [](std::vector<point_t>& points, point_t offset) {
|
||||
std::transform(points.begin(), points.end(), points.begin(), [offset](point_t point) {
|
||||
return point_t(point.x + offset.x, point.y + offset.y);
|
||||
});
|
||||
};
|
||||
|
||||
// in case somebody passes iterator to likes of std::vector<bool>
|
||||
typename std::iterator_traits<ForwardIterator>::reference current_image = *d_first;
|
||||
|
||||
// the algorithm has to traverse over parameter space and look at input, instead
|
||||
// of vice versa, as otherwise it will call translate too many times, as input
|
||||
// is usually bigger than the coordinate portion of parameter space.
|
||||
// This might cause extensive cache misses
|
||||
for (std::size_t x_index = 0; x_index < x_parameter.step_count; ++x_index)
|
||||
{
|
||||
for (std::size_t y_index = 0; y_index < y_parameter.step_count; ++y_index)
|
||||
{
|
||||
const std::ptrdiff_t x = x_parameter.start_point + x_index * x_parameter.step_size;
|
||||
const std::ptrdiff_t y = y_parameter.start_point + y_index * y_parameter.step_size;
|
||||
|
||||
auto translated_circle = circle_points;
|
||||
translate(translated_circle, {x, y});
|
||||
for (const auto& point : translated_circle)
|
||||
{
|
||||
if (input(point))
|
||||
{
|
||||
++current_image(x_index, y_index)[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
++d_first;
|
||||
}
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
@@ -11,13 +11,13 @@
|
||||
#include <boost/gil/extension/io/bmp/tags.hpp>
|
||||
#include <boost/gil/channel.hpp>
|
||||
|
||||
#include <boost/mpl/bool_fwd.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
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
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
bmp_bits_per_pixel::type src_bits_per_pixel = 0;
|
||||
@@ -73,7 +73,7 @@ bool is_allowed( const image_read_info< bmp_tag >& info
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< bmp_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
, std::false_type // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -11,17 +11,16 @@
|
||||
#include <boost/gil/extension/io/bmp/detail/is_allowed.hpp>
|
||||
#include <boost/gil/extension/io/bmp/detail/reader_backend.hpp>
|
||||
|
||||
#include <boost/gil/io/detail/dynamic.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/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/row_buffer_helper.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
@@ -99,7 +98,7 @@ public:
|
||||
io_error( "Image header was not read." );
|
||||
}
|
||||
|
||||
using is_read_and_convert_t = typename is_same
|
||||
using is_read_and_convert_t = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
@@ -705,12 +704,12 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
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
|
||||
if( !detail::construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
@@ -726,8 +725,8 @@ public:
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
variant2::visit( op
|
||||
,view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ public:
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( const point_t& img_dim )
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
#include <boost/gil/packed_pixel.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
@@ -106,15 +105,17 @@ struct bmp_write_support<uint8_t
|
||||
|
||||
} // 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
|
||||
>
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel, bmp_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::bmp_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
using parent_t = detail::bmp_read_support
|
||||
<
|
||||
@@ -125,14 +126,18 @@ struct is_read_supported< Pixel
|
||||
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
|
||||
> {};
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, bmp_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::bmp_write_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -194,15 +194,15 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
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
|
||||
variant2::visit( op
|
||||
,views
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -73,7 +73,7 @@ template<>
|
||||
struct image_read_info< bmp_tag >
|
||||
{
|
||||
/// Default contructor.
|
||||
image_read_info< bmp_tag >()
|
||||
image_read_info()
|
||||
: _top_down(false)
|
||||
, _valid( false )
|
||||
{}
|
||||
@@ -136,8 +136,8 @@ struct image_read_settings< bmp_tag > : public 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( point_t const& top_left
|
||||
, point_t const& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
|
||||
#include <boost/gil/extension/io/jpeg/tags.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< jpeg_tag >& info
|
||||
, mpl::true_ // is read_and_no_convert
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
if( info._color_space == JCS_YCbCr )
|
||||
@@ -32,7 +34,7 @@ bool is_allowed( const image_read_info< jpeg_tag >& info
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< jpeg_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
, std::false_type // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -12,14 +12,15 @@
|
||||
#include <boost/gil/extension/io/jpeg/detail/base.hpp>
|
||||
#include <boost/gil/extension/io/jpeg/detail/is_allowed.hpp>
|
||||
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/conversion_policies.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
|
||||
#include <csetjmp>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
@@ -99,7 +100,7 @@ public:
|
||||
|
||||
this->get()->dct_method = this->_settings._dct_method;
|
||||
|
||||
using is_read_and_convert_t = typename is_same
|
||||
using is_read_and_convert_t = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
@@ -275,15 +276,15 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
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
|
||||
if( !detail::construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
@@ -299,8 +300,8 @@ public:
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
variant2::visit( op
|
||||
, view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( const point_t& img_dim )
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
|
||||
@@ -13,8 +13,7 @@
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/gil/color_base.hpp>
|
||||
|
||||
#include <boost/mpl/bool_fwd.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
@@ -78,14 +77,17 @@ struct jpeg_write_support<uint8_t
|
||||
|
||||
} // 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
|
||||
>
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel, jpeg_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::jpeg_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
using parent_t = detail::jpeg_read_support
|
||||
<
|
||||
@@ -96,14 +98,17 @@ struct is_read_supported< Pixel
|
||||
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
|
||||
>
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, jpeg_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::jpeg_write_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -132,6 +132,8 @@ private:
|
||||
, 1
|
||||
);
|
||||
}
|
||||
|
||||
jpeg_finish_compress ( this->get() );
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,14 +160,14 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
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 );
|
||||
variant2::visit( op, views );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -113,7 +113,9 @@ public:
|
||||
|
||||
~writer_backend()
|
||||
{
|
||||
jpeg_finish_compress ( get() );
|
||||
// JPEG compression object destruction does not signal errors,
|
||||
// unlike jpeg_finish_compress called elsewhere,
|
||||
// so there is no need for the setjmp bookmark here.
|
||||
jpeg_destroy_compress( get() );
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ template<>
|
||||
struct image_read_settings< jpeg_tag > : public image_read_settings_base
|
||||
{
|
||||
/// Default constructor
|
||||
image_read_settings<jpeg_tag>()
|
||||
image_read_settings()
|
||||
: image_read_settings_base()
|
||||
, _dct_method( jpeg_dct_method::default_value )
|
||||
{}
|
||||
@@ -150,8 +150,8 @@ struct image_read_settings< jpeg_tag > : public image_read_settings_base
|
||||
/// \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
|
||||
image_read_settings( point_t const& top_left
|
||||
, point_t const& dim
|
||||
, jpeg_dct_method::type dct_method = jpeg_dct_method::default_value
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
|
||||
@@ -62,12 +62,13 @@ private:
|
||||
{
|
||||
if( png_ptr )
|
||||
{
|
||||
BOOST_ASSERT(png_ptr->_struct && png_ptr->_info);
|
||||
|
||||
png_destroy_read_struct( &png_ptr->_struct
|
||||
, &png_ptr->_info
|
||||
, nullptr
|
||||
);
|
||||
if( png_ptr->_struct && png_ptr->_info )
|
||||
{
|
||||
png_destroy_read_struct( &png_ptr->_struct
|
||||
, &png_ptr->_info
|
||||
, nullptr
|
||||
);
|
||||
}
|
||||
|
||||
delete png_ptr;
|
||||
png_ptr = nullptr;
|
||||
@@ -78,11 +79,12 @@ private:
|
||||
{
|
||||
if( png_ptr )
|
||||
{
|
||||
BOOST_ASSERT(png_ptr->_struct && png_ptr->_info);
|
||||
|
||||
png_destroy_write_struct( &png_ptr->_struct
|
||||
, &png_ptr->_info
|
||||
);
|
||||
if( png_ptr->_struct && png_ptr->_info )
|
||||
{
|
||||
png_destroy_write_struct( &png_ptr->_struct
|
||||
, &png_ptr->_info
|
||||
);
|
||||
}
|
||||
|
||||
delete png_ptr;
|
||||
png_ptr = nullptr;
|
||||
|
||||
@@ -10,14 +10,13 @@
|
||||
|
||||
#include <boost/gil/extension/io/png/tags.hpp>
|
||||
|
||||
#include <boost/mpl/bool_fwd.hpp>
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
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
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
using pixel_t = typename get_pixel_type<View>::type;
|
||||
@@ -33,7 +32,7 @@ bool is_allowed( const image_read_info< png_tag >& info
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< png_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
, std::false_type // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -13,14 +13,17 @@
|
||||
#include <boost/gil/extension/io/png/detail/is_allowed.hpp>
|
||||
|
||||
#include <boost/gil.hpp> // FIXME: Include what you use!
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/conversion_policies.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/error.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/row_buffer_helper.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
#if BOOST_WORKAROUND(BOOST_MSVC, >= 1400)
|
||||
@@ -81,6 +84,12 @@ public:
|
||||
template< typename View >
|
||||
void apply( const View& view )
|
||||
{
|
||||
// guard from errors in the following functions
|
||||
if (setjmp( png_jmpbuf( this->get_struct() )))
|
||||
{
|
||||
io_error("png is invalid");
|
||||
}
|
||||
|
||||
// The info structures are filled at this point.
|
||||
|
||||
// Now it's time for some transformations.
|
||||
@@ -184,7 +193,7 @@ public:
|
||||
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." );
|
||||
io_error( "gray_alpha isn't enabled. Define BOOST_GIL_IO_ENABLE_GRAY_ALPHA when building application." );
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
|
||||
@@ -228,11 +237,17 @@ private:
|
||||
>
|
||||
void read_rows( const View& view )
|
||||
{
|
||||
// guard from errors in the following functions
|
||||
if (setjmp( png_jmpbuf( this->get_struct() )))
|
||||
{
|
||||
io_error("png is invalid");
|
||||
}
|
||||
|
||||
using row_buffer_helper_t = detail::row_buffer_helper_view<ImagePixel>;
|
||||
|
||||
using it_t = typename row_buffer_helper_t::iterator_t;
|
||||
|
||||
using is_read_and_convert_t = typename is_same
|
||||
using is_read_and_convert_t = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
@@ -394,14 +409,14 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
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
|
||||
if( !detail::construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
@@ -417,8 +432,8 @@ public:
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
variant2::visit( op
|
||||
, view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -601,7 +601,7 @@ public:
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( const point_t& img_dim )
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#endif // BOOST_GIL_IO_ENABLE_GRAY_ALPHA
|
||||
|
||||
#include <cstddef>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
@@ -318,14 +319,17 @@ struct png_write_support<uint16_t
|
||||
|
||||
} // 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
|
||||
>
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel, png_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::png_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
using parent_t = detail::png_read_support
|
||||
<
|
||||
@@ -337,14 +341,17 @@ struct is_read_supported< Pixel
|
||||
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
|
||||
>
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, png_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::png_write_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
using parent_t = detail::png_write_support
|
||||
<
|
||||
|
||||
@@ -11,13 +11,9 @@
|
||||
#include <boost/gil/extension/io/png/detail/writer_backend.hpp>
|
||||
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
#include <boost/gil/io/row_buffer_helper.hpp>
|
||||
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/equal_to.hpp>
|
||||
#include <boost/mpl/less.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
@@ -85,7 +81,7 @@ private:
|
||||
|
||||
template<typename View>
|
||||
void write_view( const View& view
|
||||
, mpl::false_ // is bit aligned
|
||||
, std::false_type // is bit aligned
|
||||
)
|
||||
{
|
||||
using pixel_t = typename get_pixel_type<View>::type;
|
||||
@@ -125,7 +121,7 @@ private:
|
||||
|
||||
template<typename View>
|
||||
void write_view( const View& view
|
||||
, mpl::true_ // is bit aligned
|
||||
, std::true_type // is bit aligned
|
||||
)
|
||||
{
|
||||
using png_rw_info = detail::png_write_support
|
||||
@@ -166,8 +162,35 @@ private:
|
||||
);
|
||||
}
|
||||
|
||||
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>
|
||||
struct is_less_than_eight : mp11::mp_less
|
||||
<
|
||||
std::integral_constant<int, Info::_bit_depth>,
|
||||
std::integral_constant<int, 8>
|
||||
>
|
||||
{};
|
||||
|
||||
template<typename Info>
|
||||
struct is_equal_to_sixteen : mp11::mp_and
|
||||
<
|
||||
mp11::mp_not
|
||||
<
|
||||
mp11::mp_less
|
||||
<
|
||||
std::integral_constant<int, Info::_bit_depth>,
|
||||
std::integral_constant<int, 16>
|
||||
>
|
||||
>,
|
||||
mp11::mp_not
|
||||
<
|
||||
mp11::mp_less
|
||||
<
|
||||
std::integral_constant<int, 16>,
|
||||
std::integral_constant<int, Info::_bit_depth>
|
||||
>
|
||||
>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename Info>
|
||||
void set_swap(typename std::enable_if<is_less_than_eight<Info>::value>::type* /*ptr*/ = 0)
|
||||
@@ -185,10 +208,10 @@ private:
|
||||
void set_swap(
|
||||
typename std::enable_if
|
||||
<
|
||||
mpl::and_
|
||||
mp11::mp_and
|
||||
<
|
||||
mpl::not_<is_less_than_eight<Info>>,
|
||||
mpl::not_<is_equal_to_sixteen<Info>>
|
||||
mp11::mp_not<is_less_than_eight<Info>>,
|
||||
mp11::mp_not<is_equal_to_sixteen<Info>>
|
||||
>::value
|
||||
>::type* /*ptr*/ = nullptr)
|
||||
{
|
||||
@@ -218,14 +241,14 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
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 );
|
||||
variant2::visit( op, views );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ inline point_t png_read_dimensions(String const& filename)
|
||||
{
|
||||
using backend_t = typename get_reader_backend<String, png_tag>::type;
|
||||
backend_t backend = read_image_info(filename, png_tag());
|
||||
return { backend._info._width, backend._info._height };
|
||||
return { static_cast<std::ptrdiff_t>(backend._info._width), static_cast<std::ptrdiff_t>(backend._info._height) };
|
||||
}
|
||||
|
||||
/// \ingroup PNG_IO
|
||||
|
||||
@@ -573,7 +573,7 @@ template<>
|
||||
struct image_read_info< png_tag > : public png_info_base
|
||||
{
|
||||
/// Default constructor.
|
||||
image_read_info< png_tag >()
|
||||
image_read_info()
|
||||
: png_info_base()
|
||||
{}
|
||||
};
|
||||
@@ -669,7 +669,7 @@ 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()
|
||||
: image_read_settings_base()
|
||||
, png_read_settings_base()
|
||||
, _screen_gamma( 1.0 )
|
||||
@@ -679,8 +679,8 @@ struct image_read_settings< png_tag > : public image_read_settings_base
|
||||
/// \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
|
||||
image_read_settings( point_t const& top_left
|
||||
, point_t const& dim
|
||||
, const bool apply_screen_gamma = false
|
||||
, const png_gamma::type& screen_gamma = 1.0
|
||||
)
|
||||
@@ -708,15 +708,15 @@ 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()
|
||||
: 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( point_t const& top_left
|
||||
, point_t const& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
|
||||
#include <boost/gil/extension/io/pnm/tags.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
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
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
pnm_image_type::type asc_type = is_read_supported< typename get_pixel_type< View >::type
|
||||
@@ -38,7 +40,7 @@ bool is_allowed( const image_read_info< pnm_tag >& info
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< pnm_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
, std::false_type // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -13,11 +13,11 @@
|
||||
#include <boost/gil/extension/io/pnm/detail/is_allowed.hpp>
|
||||
|
||||
#include <boost/gil.hpp> // FIXME: Include what you use!
|
||||
#include <boost/gil/io/detail/dynamic.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/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/row_buffer_helper.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
@@ -85,7 +85,7 @@ public:
|
||||
template<typename View>
|
||||
void apply( const View& view )
|
||||
{
|
||||
using is_read_and_convert_t = typename is_same
|
||||
using is_read_and_convert_t = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
@@ -237,7 +237,7 @@ private:
|
||||
, View_Src >( dst
|
||||
, src
|
||||
, y
|
||||
, typename is_same< View_Dst
|
||||
, typename std::is_same< View_Dst
|
||||
, gray1_image_t::view_t
|
||||
>::type()
|
||||
);
|
||||
@@ -250,7 +250,7 @@ private:
|
||||
void copy_data( const View_Dst& dst
|
||||
, const View_Src& src
|
||||
, typename View_Dst::y_coord_t y
|
||||
, mpl::true_ // is gray1_view
|
||||
, std::true_type // is gray1_view
|
||||
)
|
||||
{
|
||||
if( this->_info._max_value == 1 )
|
||||
@@ -267,11 +267,7 @@ private:
|
||||
}
|
||||
else
|
||||
{
|
||||
copy_data( dst
|
||||
, src
|
||||
, y
|
||||
, mpl::false_()
|
||||
);
|
||||
copy_data(dst, src, y, std::false_type{});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +277,7 @@ private:
|
||||
void copy_data( const View_Dst& view
|
||||
, const View_Src& src
|
||||
, typename View_Dst::y_coord_t y
|
||||
, mpl::false_ // is gray1_view
|
||||
, std::false_type // is gray1_view
|
||||
)
|
||||
{
|
||||
typename View_Src::x_iterator beg = src.row_begin( 0 ) + this->_settings._top_left.x;
|
||||
@@ -420,12 +416,12 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
template< typename ...Images >
|
||||
void apply( any_image< Images... >& images )
|
||||
{
|
||||
detail::pnm_type_format_checker format_checker( this->_info._type );
|
||||
|
||||
if( !construct_matched( images
|
||||
if( !detail::construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
@@ -441,8 +437,8 @@ public:
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
variant2::visit( op
|
||||
,view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public:
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( const point_t& img_dim )
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
#include <boost/gil/color_base.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
@@ -105,14 +104,17 @@ struct pnm_write_support<uint8_t
|
||||
|
||||
} // 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
|
||||
>
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel, pnm_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::pnm_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
using parent_t = detail::pnm_read_support
|
||||
<
|
||||
@@ -124,14 +126,18 @@ struct is_read_supported< Pixel
|
||||
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
|
||||
> {};
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, pnm_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::pnm_write_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
|
||||
@@ -14,10 +14,12 @@
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/bit_operations.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
@@ -108,30 +110,34 @@ public:
|
||||
private:
|
||||
|
||||
template< int Channels >
|
||||
unsigned int get_type( mpl::true_ /* is_bit_aligned */ )
|
||||
unsigned int get_type( std::true_type /* is_bit_aligned */ )
|
||||
{
|
||||
return boost::mpl::if_c< Channels == 1
|
||||
, pnm_image_type::mono_bin_t
|
||||
, pnm_image_type::color_bin_t
|
||||
>::type::value;
|
||||
return mp11::mp_if_c
|
||||
<
|
||||
Channels == 1,
|
||||
pnm_image_type::mono_bin_t,
|
||||
pnm_image_type::color_bin_t
|
||||
>::value;
|
||||
}
|
||||
|
||||
template< int Channels >
|
||||
unsigned int get_type( mpl::false_ /* is_bit_aligned */ )
|
||||
unsigned int get_type( std::false_type /* is_bit_aligned */ )
|
||||
{
|
||||
return boost::mpl::if_c< Channels == 1
|
||||
, pnm_image_type::gray_bin_t
|
||||
, pnm_image_type::color_bin_t
|
||||
>::type::value;
|
||||
return mp11::mp_if_c
|
||||
<
|
||||
Channels == 1,
|
||||
pnm_image_type::gray_bin_t,
|
||||
pnm_image_type::color_bin_t
|
||||
>::value;
|
||||
}
|
||||
|
||||
template< typename View >
|
||||
void write_data( const View& src
|
||||
, std::size_t pitch
|
||||
, const mpl::true_& // bit_aligned
|
||||
, const std::true_type& // bit_aligned
|
||||
)
|
||||
{
|
||||
static_assert(is_same<View, typename gray1_image_t::view_t>::value, "");
|
||||
static_assert(std::is_same<View, typename gray1_image_t::view_t>::value, "");
|
||||
|
||||
byte_vector_t row( pitch / 8 );
|
||||
|
||||
@@ -154,7 +160,7 @@ private:
|
||||
template< typename View >
|
||||
void write_data( const View& src
|
||||
, std::size_t pitch
|
||||
, const mpl::false_& // bit_aligned
|
||||
, const std::false_type& // bit_aligned
|
||||
)
|
||||
{
|
||||
std::vector< pixel< typename channel_type< View >::type
|
||||
@@ -220,14 +226,14 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
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 );
|
||||
variant2::visit( op, views );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/integral_c.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
@@ -24,13 +24,13 @@ struct pnm_tag : format_tag {};
|
||||
/// Defines type for image type property.
|
||||
struct pnm_image_type : property_base< uint32_t >
|
||||
{
|
||||
using mono_asc_t = boost::mpl::integral_c<type, 1>;
|
||||
using gray_asc_t = boost::mpl::integral_c<type, 2>;
|
||||
using color_asc_t = boost::mpl::integral_c<type, 3>;
|
||||
using mono_asc_t = std::integral_constant<type, 1>;
|
||||
using gray_asc_t = std::integral_constant<type, 2>;
|
||||
using color_asc_t = std::integral_constant<type, 3>;
|
||||
|
||||
using mono_bin_t = boost::mpl::integral_c<type, 4>;
|
||||
using gray_bin_t = boost::mpl::integral_c<type, 5>;
|
||||
using color_bin_t = boost::mpl::integral_c<type, 6>;
|
||||
using mono_bin_t = std::integral_constant<type, 4>;
|
||||
using gray_bin_t = std::integral_constant<type, 5>;
|
||||
using color_bin_t = std::integral_constant<type, 6>;
|
||||
};
|
||||
|
||||
/// Defines type for image width property.
|
||||
@@ -65,15 +65,15 @@ template<>
|
||||
struct image_read_settings< pnm_tag > : public image_read_settings_base
|
||||
{
|
||||
/// Default constructor
|
||||
image_read_settings< pnm_tag >()
|
||||
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( point_t const& top_left
|
||||
, point_t const& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
@@ -117,11 +118,7 @@ public:
|
||||
};
|
||||
|
||||
template< typename FormatTag >
|
||||
struct is_adaptable_input_device< FormatTag
|
||||
, LibRaw
|
||||
, void
|
||||
>
|
||||
: mpl::true_
|
||||
struct is_adaptable_input_device<FormatTag, LibRaw, void> : std::true_type
|
||||
{
|
||||
using device_type = file_stream_device<FormatTag>;
|
||||
};
|
||||
|
||||
@@ -11,29 +11,31 @@
|
||||
#include <boost/gil/extension/io/raw/tags.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
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
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
using pixel_t = typename get_pixel_type<View>::type;
|
||||
using num_channel_t = typename num_channels<pixel_t>::value_type;
|
||||
using channel_t = typename channel_traits<typename element_type<typename View::value_type>::type>::value_type;
|
||||
|
||||
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;
|
||||
constexpr num_channel_t dst_samples_per_pixel = num_channels<pixel_t>::value;
|
||||
constexpr unsigned int dst_bits_per_pixel = detail::unsigned_integral_num_bits<channel_t>::value;
|
||||
constexpr bool is_type_signed = std::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 );
|
||||
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
|
||||
, std::false_type // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -13,17 +13,18 @@
|
||||
#include <boost/gil/extension/io/raw/detail/is_allowed.hpp>
|
||||
#include <boost/gil/extension/io/raw/detail/reader_backend.hpp>
|
||||
|
||||
#include <boost/gil/io/detail/dynamic.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/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/row_buffer_helper.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
|
||||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
@@ -100,7 +101,7 @@ public:
|
||||
io_error( "Image header was not read." );
|
||||
}
|
||||
|
||||
using is_read_and_convert_t = typename is_same
|
||||
using is_read_and_convert_t = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
@@ -165,10 +166,7 @@ struct raw_type_format_checker
|
||||
bool apply()
|
||||
{
|
||||
using view_t = typename Image::view_t;
|
||||
|
||||
return is_allowed< view_t >( _info
|
||||
, mpl::true_()
|
||||
);
|
||||
return is_allowed<view_t>(_info, std::true_type{});
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -202,12 +200,12 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
template< typename ...Images >
|
||||
void apply( any_image< Images... >& images )
|
||||
{
|
||||
detail::raw_type_format_checker format_checker( this->_info );
|
||||
|
||||
if( !construct_matched( images
|
||||
if( !detail::construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
@@ -226,8 +224,8 @@ public:
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
variant2::visit( op
|
||||
, view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( const point_t& img_dim )
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
#include <boost/gil/color_base.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
@@ -52,23 +51,24 @@ 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 >
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel,raw_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::raw_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, raw_tag>
|
||||
: std::integral_constant<bool, detail::raw_write_support::is_supported>
|
||||
{};
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,6 +10,15 @@
|
||||
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
// Historically, LibRaw expects WIN32, not _WIN32 (see https://github.com/LibRaw/LibRaw/pull/206)
|
||||
#ifdef _MSC_VER
|
||||
#ifndef WIN32
|
||||
#define WIN32
|
||||
#endif
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable:4251) // 'type' needs to have dll-interface to be used by clients of class
|
||||
#endif
|
||||
|
||||
#include <libraw/libraw.h>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
@@ -114,7 +123,7 @@ template<>
|
||||
struct image_read_info< raw_tag >
|
||||
{
|
||||
/// Default contructor.
|
||||
image_read_info< raw_tag >()
|
||||
image_read_info()
|
||||
: _valid( false )
|
||||
{}
|
||||
|
||||
@@ -173,8 +182,8 @@ struct image_read_settings< raw_tag > : public 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( point_t const& top_left
|
||||
, point_t const& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
@@ -190,7 +199,10 @@ struct image_write_info< raw_tag >
|
||||
{
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,11 +10,13 @@
|
||||
|
||||
#include <boost/gil/extension/io/targa/tags.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
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
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
targa_depth::type src_bits_per_pixel = 0;
|
||||
@@ -42,7 +44,7 @@ bool is_allowed( const image_read_info< targa_tag >& info
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< targa_tag >& /* info */
|
||||
, mpl::false_ // is read_and_convert
|
||||
, std::false_type // is read_and_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -12,15 +12,16 @@
|
||||
#include <boost/gil/extension/io/targa/detail/reader_backend.hpp>
|
||||
#include <boost/gil/extension/io/targa/detail/is_allowed.hpp>
|
||||
|
||||
#include <boost/gil/io/detail/dynamic.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/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/row_buffer_helper.hpp>
|
||||
#include <boost/gil/io/typedefs.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
@@ -82,7 +83,7 @@ public:
|
||||
template< typename View >
|
||||
void apply( const View& dst_view )
|
||||
{
|
||||
using is_read_and_convert_t = typename is_same
|
||||
using is_read_and_convert_t = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
@@ -361,12 +362,12 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
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
|
||||
if( !detail::construct_matched( images
|
||||
, format_checker
|
||||
))
|
||||
{
|
||||
@@ -382,8 +383,8 @@ public:
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
variant2::visit( op
|
||||
,view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ public:
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( const point_t& img_dim )
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
#include <boost/gil/color_base.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
|
||||
@@ -67,15 +66,17 @@ struct targa_write_support<uint8_t
|
||||
|
||||
} // 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
|
||||
>
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel, targa_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::targa_read_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{
|
||||
using parent_t = detail::targa_read_support
|
||||
<
|
||||
@@ -86,17 +87,19 @@ struct is_read_supported< Pixel
|
||||
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
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, targa_tag>
|
||||
: std::integral_constant
|
||||
<
|
||||
bool,
|
||||
detail::targa_write_support
|
||||
<
|
||||
typename channel_type<Pixel>::type,
|
||||
typename color_space_type<Pixel>::type
|
||||
>::is_supported
|
||||
>
|
||||
{};
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
@@ -163,14 +163,14 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
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 );
|
||||
variant2::visit( op, views );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ template<>
|
||||
struct image_read_info< targa_tag >
|
||||
{
|
||||
/// Default contructor.
|
||||
image_read_info< targa_tag >()
|
||||
image_read_info()
|
||||
: _screen_origin_bit(false)
|
||||
, _valid( false )
|
||||
{}
|
||||
@@ -143,8 +143,8 @@ struct image_read_settings< targa_tag > : public 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( point_t const& top_left
|
||||
, point_t const& dim
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
, dim
|
||||
|
||||
@@ -10,15 +10,15 @@
|
||||
|
||||
#include <boost/gil/extension/io/tiff/tags.hpp>
|
||||
#include <boost/gil/extension/io/tiff/detail/log.hpp>
|
||||
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
|
||||
#include <boost/mpl/size.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <type_traits>
|
||||
|
||||
// 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
|
||||
@@ -66,15 +66,13 @@ 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
|
||||
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));
|
||||
mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 0>> length;
|
||||
mp11::mp_at<typename Property::arg_types, std::integral_constant<int, 1>> 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;
|
||||
@@ -106,12 +104,12 @@ template <> struct set_property_f <2>
|
||||
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));
|
||||
using length_t = mp11::mp_at_c<typename Property::arg_types, 0>;
|
||||
auto const length = static_cast<length_t>(values.size());
|
||||
|
||||
using pointer_t = mp11::mp_at_c<typename Property::arg_types, 1>;
|
||||
auto const pointer = static_cast<pointer_t>(&(values.front()));
|
||||
return (1 == TIFFSetField( file.get(), Property:: tag, length, pointer));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,7 +130,7 @@ public:
|
||||
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);
|
||||
return get_property_f<mp11::mp_size<typename Property::arg_types>::value>().template call_me<Property>(value, _tiff_file);
|
||||
}
|
||||
|
||||
template <typename Property>
|
||||
@@ -140,7 +138,7 @@ public:
|
||||
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);
|
||||
return set_property_f<mp11::mp_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
|
||||
@@ -195,7 +193,7 @@ public:
|
||||
{
|
||||
io_error_if( TIFFReadScanline( _tiff_file.get()
|
||||
, reinterpret_cast< tdata_t >( &buffer.front() )
|
||||
, (uint32) row
|
||||
, static_cast<std::uint32_t>( row )
|
||||
, plane ) == -1
|
||||
, "Read error."
|
||||
);
|
||||
@@ -208,7 +206,7 @@ public:
|
||||
{
|
||||
io_error_if( TIFFReadScanline( _tiff_file.get()
|
||||
, reinterpret_cast< tdata_t >( buffer )
|
||||
, (uint32) row
|
||||
, static_cast<std::uint32_t>( row )
|
||||
, plane ) == -1
|
||||
, "Read error."
|
||||
);
|
||||
@@ -224,9 +222,9 @@ public:
|
||||
{
|
||||
if( TIFFReadTile( _tiff_file.get()
|
||||
, reinterpret_cast< tdata_t >( &buffer.front() )
|
||||
, (uint32) x
|
||||
, (uint32) y
|
||||
, (uint32) z
|
||||
, static_cast< std::uint32_t >( x )
|
||||
, static_cast< std::uint32_t >( y )
|
||||
, static_cast< std::uint32_t >( z )
|
||||
, plane
|
||||
) == -1 )
|
||||
{
|
||||
@@ -237,9 +235,9 @@ public:
|
||||
}
|
||||
|
||||
template< typename Buffer >
|
||||
void write_scaline( Buffer& buffer
|
||||
, uint32 row
|
||||
, tsample_t plane
|
||||
void write_scaline( Buffer& buffer
|
||||
, std::uint32_t row
|
||||
, tsample_t plane
|
||||
)
|
||||
{
|
||||
io_error_if( TIFFWriteScanline( _tiff_file.get()
|
||||
@@ -251,9 +249,9 @@ public:
|
||||
);
|
||||
}
|
||||
|
||||
void write_scaline( byte_t* buffer
|
||||
, uint32 row
|
||||
, tsample_t plane
|
||||
void write_scaline( byte_t* buffer
|
||||
, std::uint32_t row
|
||||
, tsample_t plane
|
||||
)
|
||||
{
|
||||
io_error_if( TIFFWriteScanline( _tiff_file.get()
|
||||
@@ -266,11 +264,11 @@ public:
|
||||
}
|
||||
|
||||
template< typename Buffer >
|
||||
void write_tile( Buffer& buffer
|
||||
, uint32 x
|
||||
, uint32 y
|
||||
, uint32 z
|
||||
, tsample_t plane
|
||||
void write_tile( Buffer& buffer
|
||||
, std::uint32_t x
|
||||
, std::uint32_t y
|
||||
, std::uint32_t z
|
||||
, tsample_t plane
|
||||
)
|
||||
{
|
||||
if( TIFFWriteTile( _tiff_file.get()
|
||||
@@ -303,8 +301,8 @@ public:
|
||||
)
|
||||
{
|
||||
bool result = true;
|
||||
uint32 tw = static_cast< uint32 >( width );
|
||||
uint32 th = static_cast< uint32 >( height );
|
||||
std::uint32_t tw = static_cast< std::uint32_t >( width );
|
||||
std::uint32_t th = static_cast< std::uint32_t >( height );
|
||||
|
||||
TIFFDefaultTileSize( _tiff_file.get()
|
||||
, &tw
|
||||
@@ -432,45 +430,55 @@ private:
|
||||
|
||||
/*
|
||||
template< typename T, typename D >
|
||||
struct is_adaptable_input_device< tiff_tag, T, D > : mpl::false_{};
|
||||
struct is_adaptable_input_device< tiff_tag, T, D > : std::false_type {};
|
||||
*/
|
||||
|
||||
template< typename FormatTag >
|
||||
struct is_adaptable_input_device< FormatTag
|
||||
, TIFF*
|
||||
, void
|
||||
>
|
||||
: mpl::true_
|
||||
template<typename FormatTag>
|
||||
struct is_adaptable_input_device<FormatTag, TIFF*, void> : std::true_type
|
||||
{
|
||||
using device_type = file_stream_device<FormatTag>;
|
||||
};
|
||||
|
||||
template< typename FormatTag >
|
||||
struct is_adaptable_output_device< FormatTag
|
||||
, TIFF*
|
||||
, void
|
||||
>
|
||||
: mpl::true_
|
||||
template<typename FormatTag>
|
||||
struct is_adaptable_output_device<FormatTag, TIFF*, void> : std::true_type
|
||||
{
|
||||
using device_type = file_stream_device<FormatTag>;
|
||||
};
|
||||
|
||||
|
||||
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 sample_format : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
|
||||
template<>
|
||||
struct sample_format<uint8_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
|
||||
template<>
|
||||
struct sample_format<uint16_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
|
||||
template<>
|
||||
struct sample_format<uint32_t> : std::integral_constant<int, SAMPLEFORMAT_UINT> {};
|
||||
template<>
|
||||
struct sample_format<float32_t> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
|
||||
template<>
|
||||
struct sample_format<double> : std::integral_constant<int, SAMPLEFORMAT_IEEEFP> {};
|
||||
template<>
|
||||
struct sample_format<int8_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
|
||||
template<>
|
||||
struct sample_format<int16_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
|
||||
template<>
|
||||
struct sample_format<int32_t> : std::integral_constant<int, SAMPLEFORMAT_INT> {};
|
||||
|
||||
template <typename Channel> struct photometric_interpretation {};
|
||||
template<> struct photometric_interpretation< gray_t > : public mpl::int_< PHOTOMETRIC_MINISBLACK > {};
|
||||
template<> struct photometric_interpretation< rgb_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
|
||||
template<> struct photometric_interpretation< rgba_t > : public mpl::int_< PHOTOMETRIC_RGB > {};
|
||||
template<> struct photometric_interpretation< cmyk_t > : public mpl::int_< PHOTOMETRIC_SEPARATED > {};
|
||||
template <typename Channel>
|
||||
struct photometric_interpretation {};
|
||||
template<>
|
||||
struct photometric_interpretation<gray_t>
|
||||
: std::integral_constant<int, PHOTOMETRIC_MINISBLACK> {};
|
||||
template<>
|
||||
struct photometric_interpretation<rgb_t>
|
||||
: std::integral_constant<int, PHOTOMETRIC_RGB> {};
|
||||
template<>
|
||||
struct photometric_interpretation<rgba_t>
|
||||
: std::integral_constant<int, PHOTOMETRIC_RGB> {};
|
||||
template<>
|
||||
struct photometric_interpretation<cmyk_t>
|
||||
: std::integral_constant<int, PHOTOMETRIC_SEPARATED> {};
|
||||
|
||||
} // namespace detail
|
||||
} // namespace gil
|
||||
|
||||
@@ -9,10 +9,10 @@
|
||||
#define BOOST_GIL_EXTENSION_IO_TIFF_DETAIL_IS_ALLOWED_HPP
|
||||
|
||||
#include <boost/gil/extension/io/tiff/tags.hpp>
|
||||
#include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/for_each.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil { namespace detail {
|
||||
@@ -48,13 +48,13 @@ struct Format_Type
|
||||
Channel,
|
||||
typename std::enable_if
|
||||
<
|
||||
mpl::and_
|
||||
mp11::mp_and
|
||||
<
|
||||
mpl::not_
|
||||
mp11::mp_not
|
||||
<
|
||||
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
|
||||
>,
|
||||
is_unsigned<Channel>
|
||||
std::is_unsigned<Channel>
|
||||
>::value
|
||||
>::type
|
||||
>
|
||||
@@ -70,13 +70,13 @@ struct Format_Type
|
||||
Channel,
|
||||
typename std::enable_if
|
||||
<
|
||||
mpl::and_
|
||||
mp11::mp_and
|
||||
<
|
||||
mpl::not_
|
||||
mp11::mp_not
|
||||
<
|
||||
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
|
||||
>,
|
||||
is_signed<Channel>
|
||||
std::is_signed<Channel>
|
||||
>::value
|
||||
>::type
|
||||
>
|
||||
@@ -92,9 +92,9 @@ struct Format_Type
|
||||
Channel,
|
||||
typename std::enable_if
|
||||
<
|
||||
mpl::and_
|
||||
mp11::mp_and
|
||||
<
|
||||
mpl::not_
|
||||
mp11::mp_not
|
||||
<
|
||||
typename is_bit_aligned<typename get_pixel_type<View>::type>::type
|
||||
>,
|
||||
@@ -107,13 +107,13 @@ struct Format_Type
|
||||
};
|
||||
|
||||
//template< typename Channel >
|
||||
//int format_value( mpl::true_ ) // is_bit_aligned
|
||||
//int format_value( std::true_type ) // is_bit_aligned
|
||||
//{
|
||||
// return SAMPLEFORMAT_UINT;
|
||||
//}
|
||||
//
|
||||
//template< typename Channel >
|
||||
//int format_value( mpl::false_ ) // is_bit_aligned
|
||||
//int format_value( std::false_type ) // is_bit_aligned
|
||||
//{
|
||||
// if( is_unsigned< Channel >::value )
|
||||
// {
|
||||
@@ -137,8 +137,8 @@ struct Format_Type
|
||||
// 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
|
||||
, std::false_type // is_bit_aligned
|
||||
, std::true_type // is_homogeneous
|
||||
)
|
||||
{
|
||||
using pixel_t = typename View::value_type;
|
||||
@@ -152,17 +152,14 @@ bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
|
||||
|
||||
template< typename View >
|
||||
bool compare_channel_sizes( const channel_sizes_t& channel_sizes // in bits
|
||||
, mpl::true_ // is_bit_aligned
|
||||
, mpl::true_ // is_homogeneous
|
||||
, std::true_type // is_bit_aligned
|
||||
, std::true_type // is_homogeneous
|
||||
)
|
||||
{
|
||||
using ref_t = typename View::reference;
|
||||
|
||||
using channel_t = typename channel_traits<typename element_type<ref_t>::type>::value_type;
|
||||
channel_t c;
|
||||
|
||||
unsigned int s = detail::unsigned_integral_num_bits< channel_t >::value;
|
||||
|
||||
return ( s == channel_sizes[0] );
|
||||
}
|
||||
|
||||
@@ -197,8 +194,8 @@ struct channel_sizes_type< const bit_aligned_pixel_reference< B, C, L, M > > { u
|
||||
|
||||
template< typename View >
|
||||
bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
|
||||
, mpl::true_ // is_bit_aligned
|
||||
, mpl::false_ // is_homogeneous
|
||||
, std::true_type // is_bit_aligned
|
||||
, std::false_type // is_homogeneous
|
||||
)
|
||||
{
|
||||
// loop through all channels and compare
|
||||
@@ -207,14 +204,14 @@ bool compare_channel_sizes( channel_sizes_t& channel_sizes // in bits
|
||||
using cs_t = typename channel_sizes_type<ref_t>::type;
|
||||
|
||||
compare_channel_sizes_fn fn( &channel_sizes.front() );
|
||||
mpl::for_each< cs_t >( fn );
|
||||
mp11::mp_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
|
||||
, std::true_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
channel_sizes_t channel_sizes( info._samples_per_pixel
|
||||
@@ -243,7 +240,7 @@ bool is_allowed( const image_read_info< tiff_tag >& info
|
||||
|
||||
template< typename View >
|
||||
bool is_allowed( const image_read_info< tiff_tag >& /* info */
|
||||
, mpl::false_ // is read_and_no_convert
|
||||
, std::false_type // is read_and_no_convert
|
||||
)
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
#include <boost/gil/extension/io/tiff/detail/is_allowed.hpp>
|
||||
#include <boost/gil/extension/io/tiff/detail/reader_backend.hpp>
|
||||
|
||||
#include <boost/gil/io/detail/dynamic.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/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/reader_base.hpp>
|
||||
#include <boost/gil/io/row_buffer_helper.hpp>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
// taken from jpegxx - https://bitbucket.org/edd/jpegxx/src/ea2492a1a4a6/src/ijg_headers.hpp
|
||||
@@ -173,7 +174,7 @@ public:
|
||||
// the tiff type need to compatible. Which means:
|
||||
// color_spaces_are_compatible && channels_are_pairwise_compatible
|
||||
|
||||
using is_read_only = typename is_same
|
||||
using is_read_only = typename std::is_same
|
||||
<
|
||||
ConversionPolicy,
|
||||
detail::read_and_no_convert
|
||||
@@ -208,7 +209,7 @@ private:
|
||||
|
||||
template< typename View >
|
||||
void read( View v
|
||||
, mpl::true_ // is_read_only
|
||||
, std::true_type // is_read_only
|
||||
)
|
||||
{
|
||||
read_data< detail::row_buffer_helper_view< View > >( v, 0 );
|
||||
@@ -216,7 +217,7 @@ private:
|
||||
|
||||
template< typename View >
|
||||
void read( View v
|
||||
, mpl::false_ // is_read_only
|
||||
, std::false_type // is_read_only
|
||||
)
|
||||
{
|
||||
// the read_data function needs to know what gil type the source image is
|
||||
@@ -302,11 +303,13 @@ private:
|
||||
, 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_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() );
|
||||
read_palette_image(dst_view, view(indices),
|
||||
typename std::is_same<View, rgb16_view_t>::type());
|
||||
}
|
||||
|
||||
template< typename View
|
||||
@@ -314,7 +317,7 @@ private:
|
||||
>
|
||||
void read_palette_image( const View& dst_view
|
||||
, const Indices_View& indices_view
|
||||
, mpl::true_ // is View rgb16_view_t
|
||||
, std::true_type // is View rgb16_view_t
|
||||
)
|
||||
{
|
||||
tiff_color_map::red_t red = nullptr;
|
||||
@@ -356,7 +359,7 @@ private:
|
||||
inline
|
||||
void read_palette_image( const View& /* dst_view */
|
||||
, const Indices_View& /* indices_view */
|
||||
, mpl::false_ // is View rgb16_view_t
|
||||
, std::false_type // is View rgb16_view_t
|
||||
)
|
||||
{
|
||||
io_error( "User supplied image type must be rgb16_image_t." );
|
||||
@@ -653,7 +656,7 @@ private:
|
||||
|
||||
template< typename Pixel >
|
||||
std::size_t buffer_size( std::size_t width
|
||||
, mpl::false_ // is_bit_aligned
|
||||
, std::false_type // is_bit_aligned
|
||||
)
|
||||
{
|
||||
std::size_t scanline_size_in_bytes = this->_io_dev.get_scanline_size();
|
||||
@@ -669,7 +672,7 @@ private:
|
||||
|
||||
template< typename Pixel >
|
||||
std::size_t buffer_size( std::size_t /* width */
|
||||
, mpl::true_ // is_bit_aligned
|
||||
, std::true_type // is_bit_aligned
|
||||
)
|
||||
{
|
||||
return this->_io_dev.get_scanline_size();
|
||||
@@ -694,7 +697,7 @@ struct tiff_type_format_checker
|
||||
using view_t = typename Image::view_t;
|
||||
|
||||
return is_allowed< view_t >( _info
|
||||
, mpl::true_()
|
||||
, std::true_type()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -742,8 +745,8 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Images >
|
||||
void apply( any_image< Images >& images )
|
||||
template< typename ...Images >
|
||||
void apply( any_image< Images... >& images )
|
||||
{
|
||||
detail::tiff_type_format_checker format_checker( this->_info );
|
||||
|
||||
@@ -763,8 +766,8 @@ public:
|
||||
, parent_t
|
||||
> op( this );
|
||||
|
||||
apply_operation( view( images )
|
||||
, op
|
||||
variant2::visit( op
|
||||
, view( images )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
}
|
||||
|
||||
/// Check if image is large enough.
|
||||
void check_image_size( const point_t& img_dim )
|
||||
void check_image_size( point_t const& img_dim )
|
||||
{
|
||||
if( _settings._dim.x > 0 )
|
||||
{
|
||||
|
||||
@@ -14,8 +14,7 @@
|
||||
#include <boost/gil/color_base.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/type_traits/is_same.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
@@ -35,20 +34,16 @@ 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 >
|
||||
template<typename Pixel>
|
||||
struct is_read_supported<Pixel, tiff_tag>
|
||||
: std::integral_constant<bool, detail::tiff_read_support::is_supported>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
template<typename Pixel>
|
||||
struct is_write_supported<Pixel, tiff_tag>
|
||||
: std::integral_constant<bool, detail::tiff_write_support::is_supported>
|
||||
{};
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,10 +15,12 @@
|
||||
#include <boost/gil/premultiply.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
#include <boost/gil/io/device.hpp>
|
||||
#include <boost/gil/io/dynamic_io_new.hpp>
|
||||
#include <boost/gil/io/detail/dynamic.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
extern "C" {
|
||||
@@ -39,7 +41,8 @@ template <typename PixelReference>
|
||||
struct my_interleaved_pixel_iterator_type_from_pixel_reference
|
||||
{
|
||||
private:
|
||||
using pixel_t = typename remove_reference<PixelReference>::type::value_type;
|
||||
using pixel_t = typename std::remove_reference<PixelReference>::type::value_type;
|
||||
|
||||
public:
|
||||
using type = typename iterator_type_from_pixel
|
||||
<
|
||||
@@ -162,7 +165,7 @@ private:
|
||||
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
|
||||
, const std::true_type& // has_alpha
|
||||
)
|
||||
{
|
||||
byte_vector_t row( row_size_in_bytes );
|
||||
@@ -181,7 +184,7 @@ private:
|
||||
|
||||
|
||||
this->_io_dev.write_scaline( row
|
||||
, (uint32) y
|
||||
, static_cast<std::uint32_t>( y )
|
||||
, 0
|
||||
);
|
||||
|
||||
@@ -192,7 +195,7 @@ private:
|
||||
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
|
||||
, const std::false_type& // has_alpha
|
||||
)
|
||||
{
|
||||
byte_vector_t row( row_size_in_bytes );
|
||||
@@ -209,7 +212,7 @@ private:
|
||||
|
||||
|
||||
this->_io_dev.write_scaline( row
|
||||
, (uint32) y
|
||||
, static_cast<std::uint32_t>( y )
|
||||
, 0
|
||||
);
|
||||
|
||||
@@ -222,11 +225,11 @@ private:
|
||||
template< typename View >
|
||||
void write_data( const View& view
|
||||
, std::size_t row_size_in_bytes
|
||||
, const mpl::true_& // bit_aligned
|
||||
, const std::true_type& // bit_aligned
|
||||
)
|
||||
{
|
||||
using colour_space_t = typename color_space_type<typename View::value_type>::type;
|
||||
using has_alpha_t = mpl::bool_<mpl::contains<colour_space_t, alpha_t>::value>;
|
||||
using has_alpha_t = mp11::mp_contains<colour_space_t, alpha_t>;
|
||||
|
||||
write_bit_aligned_view_to_dev(view, row_size_in_bytes, has_alpha_t());
|
||||
}
|
||||
@@ -235,7 +238,7 @@ private:
|
||||
void write_tiled_data( const View& view
|
||||
, tiff_tile_width::type tw
|
||||
, tiff_tile_length::type th
|
||||
, const mpl::true_& // bit_aligned
|
||||
, const std::true_type& // bit_aligned
|
||||
)
|
||||
{
|
||||
byte_vector_t row( this->_io_dev.get_tile_size() );
|
||||
@@ -249,7 +252,7 @@ private:
|
||||
template< typename View >
|
||||
void write_data( const View& view
|
||||
, std::size_t
|
||||
, const mpl::false_& // bit_aligned
|
||||
, const std::false_type& // bit_aligned
|
||||
)
|
||||
{
|
||||
std::vector< pixel< typename channel_type< View >::type
|
||||
@@ -271,7 +274,7 @@ private:
|
||||
);
|
||||
|
||||
this->_io_dev.write_scaline( row_addr
|
||||
, (uint32) y
|
||||
, static_cast<std::uint32_t>( y )
|
||||
, 0
|
||||
);
|
||||
|
||||
@@ -283,7 +286,7 @@ private:
|
||||
void write_tiled_data( const View& view
|
||||
, tiff_tile_width::type tw
|
||||
, tiff_tile_length::type th
|
||||
, const mpl::false_& // bit_aligned
|
||||
, const std::false_type& // bit_aligned
|
||||
)
|
||||
{
|
||||
byte_vector_t row( this->_io_dev.get_tile_size() );
|
||||
@@ -302,7 +305,7 @@ private:
|
||||
>
|
||||
void write_tiled_view_to_dev( const View& view
|
||||
, IteratorType it
|
||||
, const mpl::true_& // has_alpha
|
||||
, const std::true_type& // has_alpha
|
||||
)
|
||||
{
|
||||
auto pm_view = premultiply_view <typename View:: value_type>( view );
|
||||
@@ -319,7 +322,7 @@ private:
|
||||
>
|
||||
void write_tiled_view_to_dev( const View& view
|
||||
, IteratorType it
|
||||
, const mpl::false_& // has_alpha
|
||||
, const std::false_type& // has_alpha
|
||||
)
|
||||
{
|
||||
std::copy( view.begin()
|
||||
@@ -359,7 +362,7 @@ private:
|
||||
);
|
||||
|
||||
using colour_space_t = typename color_space_type<typename View::value_type>::type;
|
||||
using has_alpha_t = mpl::bool_<mpl::contains<colour_space_t, alpha_t>::value>;
|
||||
using has_alpha_t = mp11::mp_contains<colour_space_t, alpha_t>;
|
||||
|
||||
write_tiled_view_to_dev(tile_subimage_view, it, has_alpha_t());
|
||||
}
|
||||
@@ -391,8 +394,8 @@ private:
|
||||
}
|
||||
|
||||
this->_io_dev.write_tile( row
|
||||
, static_cast< uint32 >( j )
|
||||
, static_cast< uint32 >( i )
|
||||
, static_cast< std::uint32_t >( j )
|
||||
, static_cast< std::uint32_t >( i )
|
||||
, 0
|
||||
, 0
|
||||
);
|
||||
@@ -428,14 +431,14 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
template< typename Views >
|
||||
void apply( const any_image_view< Views >& views )
|
||||
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 );
|
||||
variant2::visit( op, views );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
#include <boost/gil/extension/io/tiff/tags.hpp>
|
||||
#include <boost/gil/extension/io/tiff/detail/device.hpp>
|
||||
|
||||
#include <boost/mpl/contains.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
@@ -78,10 +78,12 @@ protected:
|
||||
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) {
|
||||
if /*constexpr*/ (mp11::mp_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.
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
|
||||
#include <boost/gil/extension/io/tiff/detail/log.hpp>
|
||||
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
#include <boost/gil/io/base.hpp>
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
// 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
|
||||
@@ -44,7 +45,7 @@ struct tiff_property_base : property_base< T >
|
||||
/// this property:
|
||||
/// http://www.remotesensing.org/libtiff/man/TIFFGetField.3tiff.html
|
||||
/// http://www.remotesensing.org/libtiff/man/TIFFSetField.3tiff.html
|
||||
using arg_types = mpl::vector<typename property_base<unsigned short>::type>;
|
||||
using arg_types = mp11::mp_list<typename property_base<unsigned short>::type>;
|
||||
};
|
||||
|
||||
/// baseline tags
|
||||
@@ -153,9 +154,9 @@ struct tiff_color_map
|
||||
};
|
||||
|
||||
/// Defines type for extra samples property.
|
||||
struct tiff_extra_samples : tiff_property_base<std:: vector <uint16_t>, TIFFTAG_EXTRASAMPLES>
|
||||
struct tiff_extra_samples : tiff_property_base<std::vector<uint16_t>, TIFFTAG_EXTRASAMPLES>
|
||||
{
|
||||
using arg_types = mpl::vector<uint16_t, uint16_t const *>;
|
||||
using arg_types = mp11::mp_list<uint16_t, uint16_t const*>;
|
||||
};
|
||||
|
||||
/// Defines type for copyright property.
|
||||
@@ -182,10 +183,9 @@ struct tiff_tile_width : tiff_property_base< long, TIFFTAG_TILEWIDTH > {};
|
||||
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 >
|
||||
{
|
||||
using default_value = boost::mpl::integral_c<type, 0>;
|
||||
using default_value = std::integral_constant<type, 0>;
|
||||
};
|
||||
|
||||
/// Non-baseline tags
|
||||
@@ -193,7 +193,7 @@ struct tiff_directory : property_base< tdir_t >
|
||||
/// Defines type for icc profile property.
|
||||
struct tiff_icc_profile : tiff_property_base<std::vector<uint8_t>, TIFFTAG_ICCPROFILE>
|
||||
{
|
||||
using arg_types = mpl::vector<uint32_t, void const *>;
|
||||
using arg_types = mp11::mp_list<uint32_t, void const*>;
|
||||
};
|
||||
|
||||
/// Read information for tiff images.
|
||||
@@ -270,7 +270,7 @@ template<>
|
||||
struct image_read_settings< tiff_tag > : public image_read_settings_base
|
||||
{
|
||||
/// Default constructor
|
||||
image_read_settings< tiff_tag >()
|
||||
image_read_settings()
|
||||
: image_read_settings_base()
|
||||
, _directory( tiff_directory::default_value::value )
|
||||
{}
|
||||
@@ -279,8 +279,8 @@ struct image_read_settings< tiff_tag > : public image_read_settings_base
|
||||
/// \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
|
||||
image_read_settings( point_t const& top_left
|
||||
, point_t const& dim
|
||||
, const tiff_directory::type& directory = tiff_directory::default_value::value
|
||||
)
|
||||
: image_read_settings_base( top_left
|
||||
|
||||
@@ -89,6 +89,85 @@ point<F> transform(matrix3x2<F> const& mat, point<F2> const& src)
|
||||
return src * mat;
|
||||
}
|
||||
|
||||
/// Returns the inverse of the given affine transformation matrix
|
||||
///
|
||||
/// \warning Floating point arithmetic, use Boost.Rational if precision maters
|
||||
template <typename T>
|
||||
boost::gil::matrix3x2<T> inverse(boost::gil::matrix3x2<T> m)
|
||||
{
|
||||
T const determinant = m.a * m.d - m.b * m.c;
|
||||
|
||||
boost::gil::matrix3x2<T> res;
|
||||
res.a = m.d / determinant;
|
||||
res.b = -m.b / determinant;
|
||||
res.c = -m.c / determinant;
|
||||
res.d = m.a / determinant;
|
||||
res.e = (m.c * m.f - m.d * m.e) / determinant;
|
||||
res.f = (m.b * m.e - m.a * m.f) / determinant;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// \fn gil::matrix3x2 center_rotate
|
||||
/// \tparam T Data type for source image dimensions
|
||||
/// \tparam F Data type for angle through which image is to be rotated
|
||||
/// @param dims dimensions of source image
|
||||
/// @param rads angle through which image is to be rotated
|
||||
/// @return A transformation matrix for rotating the source image about its center
|
||||
/// \brief rotates an image from its center point
|
||||
/// using consecutive affine transformations.
|
||||
template<typename T, typename F>
|
||||
boost::gil::matrix3x2<F> center_rotate(boost::gil::point<T> dims,F rads)
|
||||
{
|
||||
const F PI = F(3.141592653589793238);
|
||||
const F c_theta = std::abs(std::cos(rads));
|
||||
const F s_theta = std::abs(std::sin(rads));
|
||||
|
||||
// Bound checks for angle rads
|
||||
while(rads + PI < 0)
|
||||
{
|
||||
rads = rads + PI;
|
||||
}
|
||||
|
||||
while(rads > PI)
|
||||
{
|
||||
rads = rads - PI;
|
||||
}
|
||||
|
||||
// Basic Rotation Matrix
|
||||
boost::gil::matrix3x2<F> rotate = boost::gil::matrix3x2<F>::get_rotate(rads);
|
||||
|
||||
// Find distance for translating the image into view
|
||||
boost::gil::matrix3x2<F> translation(0,0,0,0,0,0);
|
||||
if(rads > 0)
|
||||
{
|
||||
translation.b = s_theta;
|
||||
}
|
||||
else
|
||||
{
|
||||
translation.c = s_theta;
|
||||
}
|
||||
|
||||
if(std::abs(rads) > PI/2)
|
||||
{
|
||||
translation.a = c_theta;
|
||||
translation.d = c_theta;
|
||||
}
|
||||
|
||||
// To bring the complete image into view
|
||||
boost::gil::matrix3x2<F> translate =
|
||||
boost::gil::matrix3x2<F>::get_translate(-1 * dims * translation);
|
||||
|
||||
// To fit inside the source dimensions
|
||||
boost::gil::matrix3x2<F> scale =
|
||||
boost::gil::matrix3x2<F>::get_scale(
|
||||
s_theta * dims.y / dims.x + c_theta ,
|
||||
s_theta * dims.x / dims.y + c_theta
|
||||
);
|
||||
|
||||
return scale * translate * rotate;
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2019-2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,142 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_ALGORITHM_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/gil/metafunctions.hpp>
|
||||
#include <boost/gil/pixel_iterator.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <numeric>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \brief Returns the reference proxy associated with a type that has a \p "reference" member type alias.
|
||||
///
|
||||
/// 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) {
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
|
||||
using kernel_type = typename std::iterator_traits<KernelIterator>::value_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) {
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename std::iterator_traits<SrcIterator>::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename std::iterator_traits<DstIterator>::value_type>::type;
|
||||
using kernel_type = typename std::iterator_traits<KernelIterator>::value_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) {
|
||||
BOOST_ASSERT(src.dimensions() == dst.dimensions());
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename SrcView::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename DstView::value_type>::type;
|
||||
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
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/algorithm.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,140 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_CHANNEL_NUMERIC_OPERATIONS_HPP
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// Structures for channel-wise numeric operations
|
||||
// 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 (=)
|
||||
|
||||
/// \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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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 {
|
||||
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
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/channel_numeric_operations.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2019 Miral Shah <miralshah2211@gmail.com>
|
||||
// Copyright 2019-2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,210 +10,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_CONVOLVE_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/algorithm.hpp>
|
||||
#include <boost/gil/extension/numeric/kernel.hpp>
|
||||
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/gil/algorithm.hpp>
|
||||
#include <boost/gil/image_view_factory.hpp>
|
||||
#include <boost/gil/metafunctions.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// 2D seperable convolutions and correlations
|
||||
|
||||
/// \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) {
|
||||
BOOST_ASSERT(src.dimensions() == dst.dimensions());
|
||||
BOOST_ASSERT(ker.size() != 0);
|
||||
|
||||
using PIXEL_SRC_REF = typename pixel_proxy<typename SrcView::value_type>::type;
|
||||
using PIXEL_DST_REF = typename pixel_proxy<typename DstView::value_type>::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& kernel, const DstView& dst,
|
||||
convolve_boundary_option option=convolve_option_extend_zero)
|
||||
{
|
||||
using correlator = detail::correlator_k
|
||||
<
|
||||
std::extent<Kernel>::value,
|
||||
PixelAccum
|
||||
>;
|
||||
detail::correlate_rows_imp<PixelAccum>(
|
||||
src, kernel, dst, option, correlator{});
|
||||
}
|
||||
|
||||
/// \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
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/image_processing/convolve.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,118 +1,18 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2019 Miral Shah <miralshah2211@gmail.com>
|
||||
// Copyright 2022 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
// http://www.boost.org/LICENSE_1_0.txt
|
||||
//
|
||||
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_KERNEL_HPP
|
||||
|
||||
#include <boost/gil/utilities.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// Definitions of 1D fixed-size and variable-size kernels and related operations
|
||||
|
||||
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)
|
||||
{
|
||||
BOOST_ASSERT(_center < this->size());
|
||||
}
|
||||
|
||||
kernel_1d_adaptor(std::size_t size_in, std::size_t center_in)
|
||||
: Core(size_in)
|
||||
, _center(center_in)
|
||||
{
|
||||
BOOST_ASSERT(_center < this->size());
|
||||
}
|
||||
|
||||
kernel_1d_adaptor(kernel_1d_adaptor const& 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
|
||||
{
|
||||
BOOST_ASSERT(_center < this->size());
|
||||
return _center;
|
||||
}
|
||||
|
||||
std::size_t right_size() const
|
||||
{
|
||||
BOOST_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>>
|
||||
{
|
||||
using parent_t = detail::kernel_1d_adaptor<std::vector<T,Alloc>>;
|
||||
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>>
|
||||
{
|
||||
using parent_t = detail::kernel_1d_adaptor<std::array<T,Size>>;
|
||||
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
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/image_processing/kernel.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,165 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_PIXEL_NUMERIC_OPERATIONS_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/channel_numeric_operations.hpp>
|
||||
#include <boost/config/header_deprecated.hpp>
|
||||
|
||||
#include <boost/gil/color_base_algorithm.hpp>
|
||||
#include <boost/gil/pixel.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// Structures for pixel-wise numeric operations
|
||||
// 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 (=)
|
||||
|
||||
/// \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::bind(channel_multiplies_scalar_t<typename channel_type<PixelRef>::type,
|
||||
Scalar,
|
||||
typename channel_type<PixelR>::type>(),
|
||||
std::placeholders::_1, 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::bind(channel_divides_scalar_t<typename channel_type<PixelRef>::type,
|
||||
Scalar,
|
||||
typename channel_type<PixelR>::type>(),
|
||||
std::placeholders::_1, 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
|
||||
BOOST_HEADER_DEPRECATED("<boost/gil/pixel_numeric_operations.hpp>")
|
||||
|
||||
#endif
|
||||
|
||||
@@ -70,34 +70,34 @@ namespace detail {
|
||||
/// \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())
|
||||
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, std::bind(
|
||||
variant2::visit(std::bind(
|
||||
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
|
||||
std::placeholders::_1,
|
||||
dst));
|
||||
dst), src);
|
||||
}
|
||||
|
||||
/// \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())
|
||||
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())
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
apply_operation(dst, std::bind(
|
||||
variant2::visit(std::bind(
|
||||
detail::resample_pixels_fn<Sampler, MapFn>(dst_to_src, sampler),
|
||||
src,
|
||||
std::placeholders::_1));
|
||||
std::placeholders::_1), dst);
|
||||
}
|
||||
|
||||
/// \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));
|
||||
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()) {
|
||||
variant2::visit(detail::resample_pixels_fn<Sampler,MapFn>(dst_to_src,sampler), src, dst);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
//
|
||||
// Copyright 2005-2007 Adobe Systems Incorporated
|
||||
// Copyright 2021 Pranam Lashkari <plashkari628@gmail.com>
|
||||
//
|
||||
// Distributed under the Boost Software License, Version 1.0
|
||||
// See accompanying file LICENSE_1_0.txt or copy at
|
||||
@@ -8,8 +9,8 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
|
||||
#define BOOST_GIL_EXTENSION_NUMERIC_SAMPLER_HPP
|
||||
|
||||
#include <boost/gil/extension/numeric/pixel_numeric_operations.hpp>
|
||||
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
|
||||
#include <boost/gil/pixel_numeric_operations.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
@@ -180,7 +181,6 @@ bool sample(bilinear_sampler, SrcView const& src, point<F> const& p, DstP& resul
|
||||
cast_pixel(mp,src_result);
|
||||
|
||||
color_convert(src_result, result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_RASTERIZATION_APPLY_RASTERIZER
|
||||
#define BOOST_GIL_EXTENSION_RASTERIZATION_APPLY_RASTERIZER
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename View, typename Rasterizer, typename Pixel, typename Tag>
|
||||
struct apply_rasterizer_op
|
||||
{
|
||||
void operator()(
|
||||
View const& view, Rasterizer const& rasterizer, Pixel const& pixel);
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename View, typename Rasterizer, typename Pixel>
|
||||
void apply_rasterizer(
|
||||
View const& view, Rasterizer const& rasterizer, Pixel const& pixel)
|
||||
{
|
||||
using tag_t = typename Rasterizer::type;
|
||||
detail::apply_rasterizer_op<View, Rasterizer, Pixel, tag_t>{}(
|
||||
view, rasterizer, pixel);
|
||||
}
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
179
linx64/include/boost/gil/extension/rasterization/circle.hpp
Normal file
179
linx64/include/boost/gil/extension/rasterization/circle.hpp
Normal file
@@ -0,0 +1,179 @@
|
||||
//
|
||||
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
|
||||
//
|
||||
// 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_RASTERIZATION_CIRCLE_HPP
|
||||
#define BOOST_GIL_EXTENSION_RASTERIZATION_CIRCLE_HPP
|
||||
|
||||
#include <boost/gil/detail/math.hpp>
|
||||
#include <boost/gil/extension/rasterization/apply_rasterizer.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
struct circle_rasterizer_t{};
|
||||
|
||||
/// \defgroup CircleRasterization
|
||||
/// \ingroup Rasterization
|
||||
/// \brief Circle rasterization algorithms
|
||||
///
|
||||
/// The main problems are connectivity and equation following. Circle can be easily moved
|
||||
/// to new offset, and rotation has no effect on it (not recommended to do rotation).
|
||||
|
||||
/// \ingroup CircleRasterization
|
||||
/// \brief Rasterize trigonometric circle according to radius by sine and radius by cosine
|
||||
///
|
||||
/// This rasterizer is the one used that is used in standard Hough circle transform in
|
||||
/// the books. It is also quite expensive to compute.
|
||||
/// WARNING: the product of this rasterizer does not follow circle equation, even though it
|
||||
/// produces quite round like shapes.
|
||||
struct trigonometric_circle_rasterizer
|
||||
{
|
||||
using type = circle_rasterizer_t;
|
||||
|
||||
/// \brief Creates a trigonometric circle rasterizer
|
||||
/// \param center_point - Point containing positive integer x co-ordinate and y co-ordinate of the
|
||||
/// center respectively.
|
||||
/// \param circle_radius - Radius of the circle
|
||||
trigonometric_circle_rasterizer(point_t center_point, std::ptrdiff_t circle_radius)
|
||||
: center(center_point), radius(circle_radius)
|
||||
{}
|
||||
|
||||
/// \brief Calculates minimum angle step that is distinguishable when walking on circle
|
||||
///
|
||||
/// It is important to not have disconnected circle and to not compute unnecessarily,
|
||||
/// thus the result of this function is used when rendering.
|
||||
double minimum_angle_step() const noexcept
|
||||
{
|
||||
const auto diameter = radius * 2 - 1;
|
||||
return std::atan2(1.0, diameter);
|
||||
}
|
||||
|
||||
/// \brief Calculate the amount of points that rasterizer will output
|
||||
std::ptrdiff_t point_count() const noexcept
|
||||
{
|
||||
return 8 * static_cast<std::ptrdiff_t>(
|
||||
std::round(detail::pi / 4 / minimum_angle_step()) + 1);
|
||||
}
|
||||
|
||||
/// \brief perform rasterization and output into d_first
|
||||
template <typename OutputIterator>
|
||||
void operator()(OutputIterator d_first) const
|
||||
{
|
||||
const double minimum_angle_step = std::atan2(1.0, radius);
|
||||
auto translate_mirror_points = [this, &d_first](point_t p) {
|
||||
*d_first++ = point_t{center.x + p.x, center.y + p.y};
|
||||
*d_first++ = point_t{center.x + p.x, center.y - p.y};
|
||||
*d_first++ = point_t{center.x - p.x, center.y + p.y};
|
||||
*d_first++ = point_t{center.x - p.x, center.y - p.y};
|
||||
*d_first++ = point_t{center.x + p.y, center.y + p.x};
|
||||
*d_first++ = point_t{center.x + p.y, center.y - p.x};
|
||||
*d_first++ = point_t{center.x - p.y, center.y + p.x};
|
||||
*d_first++ = point_t{center.x - p.y, center.y - p.x};
|
||||
};
|
||||
const std::ptrdiff_t iteration_count = point_count() / 8;
|
||||
double angle = 0;
|
||||
// do note that + 1 was done inside count estimation, thus <= is not needed, only <
|
||||
for (std::ptrdiff_t i = 0; i < iteration_count; ++i, angle += minimum_angle_step)
|
||||
{
|
||||
std::ptrdiff_t x = static_cast<std::ptrdiff_t>(std::round(radius * std::cos(angle)));
|
||||
std::ptrdiff_t y = static_cast<std::ptrdiff_t>(std::round(radius * std::sin(angle)));
|
||||
translate_mirror_points({x, y});
|
||||
}
|
||||
}
|
||||
|
||||
point_t center;
|
||||
std::ptrdiff_t radius;
|
||||
};
|
||||
|
||||
/// \ingroup CircleRasterization
|
||||
/// \brief Perform circle rasterization according to Midpoint algorithm
|
||||
///
|
||||
/// This algorithm givess reasonable output and is cheap to compute.
|
||||
/// reference:
|
||||
/// https://en.wikipedia.org/wiki/Midpoint_circle_algorithm
|
||||
struct midpoint_circle_rasterizer
|
||||
{
|
||||
using type = circle_rasterizer_t;
|
||||
|
||||
/// \brief Creates a midpoint circle rasterizer
|
||||
/// \param center_point - Point containing positive integer x co-ordinate and y co-ordinate of the
|
||||
/// center respectively.
|
||||
/// \param circle_radius - Radius of the circle
|
||||
midpoint_circle_rasterizer(point_t center_point, std::ptrdiff_t circle_radius)
|
||||
: center(center_point), radius(circle_radius)
|
||||
{}
|
||||
|
||||
/// \brief Calculate the amount of points that rasterizer will output
|
||||
std::ptrdiff_t point_count() const noexcept
|
||||
{
|
||||
// the reason for pulling 8 out is so that when the expression radius * cos(45 degrees)
|
||||
// is used, it would yield the same result as here
|
||||
// + 1 at the end is because the point at radius itself is computed as well
|
||||
return 8 * static_cast<std::ptrdiff_t>(
|
||||
std::round(radius * std::cos(boost::gil::detail::pi / 4)) + 1);
|
||||
}
|
||||
|
||||
/// \brief perform rasterization and output into d_first
|
||||
template <typename OutputIterator>
|
||||
void operator()(OutputIterator d_first) const
|
||||
{
|
||||
auto translate_mirror_points = [this, &d_first](point_t p) {
|
||||
*d_first++ = point_t{center.x + p.x, center.y + p.y};
|
||||
*d_first++ = point_t{center.x + p.x, center.y - p.y};
|
||||
*d_first++ = point_t{center.x - p.x, center.y + p.y};
|
||||
*d_first++ = point_t{center.x - p.x, center.y - p.y};
|
||||
*d_first++ = point_t{center.x + p.y, center.y + p.x};
|
||||
*d_first++ = point_t{center.x + p.y, center.y - p.x};
|
||||
*d_first++ = point_t{center.x - p.y, center.y + p.x};
|
||||
*d_first++ = point_t{center.x - p.y, center.y - p.x};
|
||||
};
|
||||
std::ptrdiff_t iteration_distance = point_count() / 8;
|
||||
std::ptrdiff_t y_current = radius;
|
||||
std::ptrdiff_t r_squared = radius * radius;
|
||||
translate_mirror_points({0, y_current});
|
||||
for (std::ptrdiff_t x = 1; x < iteration_distance; ++x)
|
||||
{
|
||||
std::ptrdiff_t midpoint = x * x + y_current * y_current - y_current - r_squared;
|
||||
if (midpoint > 0)
|
||||
{
|
||||
--y_current;
|
||||
}
|
||||
translate_mirror_points({x, y_current});
|
||||
}
|
||||
}
|
||||
|
||||
point_t center;
|
||||
std::ptrdiff_t radius;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename View, typename Rasterizer, typename Pixel>
|
||||
struct apply_rasterizer_op<View, Rasterizer, Pixel, circle_rasterizer_t>
|
||||
{
|
||||
void operator()(
|
||||
View const& view, Rasterizer const& rasterizer, Pixel const& pixel)
|
||||
{
|
||||
std::vector<point_t> trajectory(rasterizer.point_count());
|
||||
rasterizer(std::begin(trajectory));
|
||||
|
||||
for (auto const& point : trajectory)
|
||||
{
|
||||
view(point) = pixel;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
209
linx64/include/boost/gil/extension/rasterization/ellipse.hpp
Normal file
209
linx64/include/boost/gil/extension/rasterization/ellipse.hpp
Normal file
@@ -0,0 +1,209 @@
|
||||
//
|
||||
// Copyright 2021 Prathamesh Tagore <prathameshtagore@gmail.com>
|
||||
//
|
||||
// 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_RASTERIZATION_ELLIPSE_HPP
|
||||
#define BOOST_GIL_EXTENSION_RASTERIZATION_ELLIPSE_HPP
|
||||
|
||||
#include <boost/gil/concepts/pixel.hpp>
|
||||
#include <boost/gil/extension/rasterization/apply_rasterizer.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
struct ellipse_rasterizer_t{};
|
||||
|
||||
/// \defgroup EllipseRasterization
|
||||
/// \ingroup Rasterization
|
||||
/// \brief Ellipse rasterization algorithms.
|
||||
|
||||
/// \ingroup EllipseRasterization
|
||||
/// \brief Performs ellipse rasterization using midpoint algorithm. Initially, program considers
|
||||
/// origin as center of ellipse and obtains first quadrant trajectory points. After that,
|
||||
/// it shifts origin to provided co-ordinates of center and then draws the curve.
|
||||
struct midpoint_ellipse_rasterizer
|
||||
{
|
||||
using type = ellipse_rasterizer_t;
|
||||
|
||||
/// \brief Creates a midpoint ellipse rasterizer
|
||||
/// \param center - Point containing positive integer x co-ordinate and y co-ordinate of the
|
||||
/// center respectively.
|
||||
/// \param semi_axes - Point containing positive integer lengths of horizontal semi-axis
|
||||
/// and vertical semi-axis respectively.
|
||||
midpoint_ellipse_rasterizer(point<unsigned int> center_point,
|
||||
point<unsigned int> semi_axes_values)
|
||||
: center(center_point)
|
||||
, semi_axes(semi_axes_values)
|
||||
{}
|
||||
|
||||
/// \brief Returns a vector containing co-ordinates of first quadrant points which lie on
|
||||
/// rasterizer trajectory of the ellipse.
|
||||
auto obtain_trajectory() const
|
||||
-> std::vector<point_t>
|
||||
{
|
||||
// Citation : J. Van Aken, "An Efficient Ellipse-Drawing Algorithm" in IEEE Computer
|
||||
// Graphics and Applications, vol. 4, no. 09, pp. 24-35, 1984.
|
||||
// doi: 10.1109/MCG.1984.275994
|
||||
// keywords: {null}
|
||||
// url: https://doi.ieeecomputersociety.org/10.1109/MCG.1984.275994
|
||||
std::vector<point_t> trajectory_points;
|
||||
std::ptrdiff_t x = semi_axes[0], y = 0;
|
||||
|
||||
// Variables declared on following lines are temporary variables used for improving
|
||||
// performance since they help in converting all multiplicative operations inside the while
|
||||
// loop into additive/subtractive operations.
|
||||
long long int const t1 = semi_axes[0] * semi_axes[0];
|
||||
long long int const t4 = semi_axes[1] * semi_axes[1];
|
||||
long long int t2, t3, t5, t6, t8, t9;
|
||||
t2 = 2 * t1, t3 = 2 * t2;
|
||||
t5 = 2 * t4, t6 = 2 * t5;
|
||||
long long int const t7 = semi_axes[0] * t5;
|
||||
t8 = 2 * t7, t9 = 0;
|
||||
|
||||
// Following variables serve as decision parameters and help in choosing the right point
|
||||
// to be included in rasterizer trajectory.
|
||||
long long int d1, d2;
|
||||
d1 = t2 - t7 + t4 / 2, d2 = t1 / 2 - t8 + t5;
|
||||
|
||||
while (d2 < 0)
|
||||
{
|
||||
trajectory_points.push_back({x, y});
|
||||
y += 1;
|
||||
t9 += t3;
|
||||
if (d1 < 0)
|
||||
{
|
||||
d1 += t9 + t2;
|
||||
d2 += t9;
|
||||
}
|
||||
else
|
||||
{
|
||||
x -= 1;
|
||||
t8 -= t6;
|
||||
d1 += t9 + t2 - t8;
|
||||
d2 += t5 + t9 - t8;
|
||||
}
|
||||
}
|
||||
while (x >= 0)
|
||||
{
|
||||
trajectory_points.push_back({x, y});
|
||||
x -= 1;
|
||||
t8 -= t6;
|
||||
if (d2 < 0)
|
||||
{
|
||||
y += 1;
|
||||
t9 += t3;
|
||||
d2 += t5 + t9 - t8;
|
||||
}
|
||||
else
|
||||
{
|
||||
d2 += t5 - t8;
|
||||
}
|
||||
}
|
||||
return trajectory_points;
|
||||
}
|
||||
|
||||
/// \brief Fills pixels returned by function 'obtain_trajectory' as well as pixels
|
||||
/// obtained from their reflection along major axis, minor axis and line passing through
|
||||
/// center with slope -1 using colours provided by user.
|
||||
/// \param view - Gil view of image on which the elliptical curve is to be drawn.
|
||||
/// \param pixel - Pixel value for the elliptical curve to be drawn.
|
||||
/// \param trajectory_points - Constant vector specifying pixel co-ordinates of points lying
|
||||
/// on rasterizer trajectory.
|
||||
/// \tparam View - Type of input image view.
|
||||
/// \tparam Pixel - Type of pixel. Must be compatible to the pixel type of the image view
|
||||
template<typename View, typename Pixel>
|
||||
void draw_curve(View& view, Pixel const& pixel,
|
||||
std::vector<point_t> const& trajectory_points) const
|
||||
{
|
||||
using pixel_t = typename View::value_type;
|
||||
if (!pixels_are_compatible<pixel_t, Pixel>())
|
||||
{
|
||||
throw std::runtime_error("Pixel type of the given image is not compatible to the "
|
||||
"type of the provided pixel.");
|
||||
}
|
||||
|
||||
// mutable center copy
|
||||
point<unsigned int> center2(center);
|
||||
--center2[0], --center2[1]; // For converting center co-ordinate values to zero based indexing.
|
||||
for (point_t pnt : trajectory_points)
|
||||
{
|
||||
std::array<std::ptrdiff_t, 4> co_ords = {center2[0] + pnt[0],
|
||||
center2[0] - pnt[0], center2[1] + pnt[1], center2[1] - pnt[1]
|
||||
};
|
||||
bool validity[4]{};
|
||||
if (co_ords[0] < view.width())
|
||||
{
|
||||
validity[0] = true;
|
||||
}
|
||||
if (co_ords[1] >= 0 && co_ords[1] < view.width())
|
||||
{
|
||||
validity[1] = true;
|
||||
}
|
||||
if (co_ords[2] < view.height())
|
||||
{
|
||||
validity[2] = true;
|
||||
}
|
||||
if (co_ords[3] >= 0 && co_ords[3] < view.height())
|
||||
{
|
||||
validity[3] = true;
|
||||
}
|
||||
|
||||
if (validity[0] && validity[2])
|
||||
{
|
||||
view(co_ords[0], co_ords[2]) = pixel;
|
||||
}
|
||||
if (validity[1] && validity[2])
|
||||
{
|
||||
view(co_ords[1], co_ords[2]) = pixel;
|
||||
}
|
||||
if (validity[1] && validity[3])
|
||||
{
|
||||
view(co_ords[1], co_ords[3]) = pixel;
|
||||
}
|
||||
if (validity[0] && validity[3])
|
||||
{
|
||||
view(co_ords[0], co_ords[3]) = pixel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Calls the function 'obtain_trajectory' and then passes obtained trajectory points
|
||||
/// in the function 'draw_curve' for drawing the desired ellipse.
|
||||
/// \param view - Gil view of image on which the elliptical curve is to be drawn.
|
||||
/// \param pixel - Pixel value for the elliptical curve to be drawn.
|
||||
/// \tparam View - Type of input image view.
|
||||
/// \tparam Pixel - Type of pixel. Must be compatible to the pixel type of the image view
|
||||
template<typename View, typename Pixel>
|
||||
void operator()(View& view, Pixel const& pixel) const
|
||||
{
|
||||
draw_curve(view, pixel, obtain_trajectory());
|
||||
}
|
||||
|
||||
point<unsigned int> center;
|
||||
point<unsigned int> semi_axes;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename View, typename Rasterizer, typename Pixel>
|
||||
struct apply_rasterizer_op<View, Rasterizer, Pixel, ellipse_rasterizer_t>
|
||||
{
|
||||
void operator()(
|
||||
View const& view, Rasterizer const& rasterizer, Pixel const& pixel)
|
||||
{
|
||||
rasterizer(view, pixel);
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
132
linx64/include/boost/gil/extension/rasterization/line.hpp
Normal file
132
linx64/include/boost/gil/extension/rasterization/line.hpp
Normal file
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// Copyright 2020 Olzhas Zhumabek <anonymous.from.applecity@gmail.com>
|
||||
//
|
||||
// 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_RASTERIZATION_LINE_HPP
|
||||
#define BOOST_GIL_EXTENSION_RASTERIZATION_LINE_HPP
|
||||
|
||||
#include <boost/gil/extension/rasterization/apply_rasterizer.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
|
||||
#include <cmath>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <vector>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
struct line_rasterizer_t{};
|
||||
|
||||
/// \defgroup Rasterization
|
||||
/// \brief A set of functions to rasterize shapes
|
||||
///
|
||||
/// Due to images being discrete, most shapes require specialized algorithms to
|
||||
/// handle rasterization efficiently and solve problem of connectivity and being
|
||||
/// close to the original shape.
|
||||
|
||||
/// \defgroup LineRasterization
|
||||
/// \ingroup Rasterization
|
||||
/// \brief A set of rasterizers for lines
|
||||
///
|
||||
/// The main problem with line rasterization is to do it efficiently, e.g. less
|
||||
/// floating point operations. There are multiple algorithms that on paper
|
||||
/// should reach the same result, but due to quirks of IEEE-754 they don't.
|
||||
/// Please select one and stick to it if possible. At the moment only Bresenham
|
||||
/// rasterizer is implemented.
|
||||
|
||||
/// \ingroup LineRasterization
|
||||
/// \brief Rasterize a line according to Bresenham algorithm
|
||||
///
|
||||
/// Do note that if either width or height is 1, slope is set to zero.
|
||||
/// reference:
|
||||
/// https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm#:~:text=Bresenham's%20line%20algorithm%20is%20a,straight%20line%20between%20two%20points.
|
||||
struct bresenham_line_rasterizer
|
||||
{
|
||||
using type = line_rasterizer_t;
|
||||
|
||||
bresenham_line_rasterizer(point_t start, point_t end)
|
||||
: start_point(start), end_point(end)
|
||||
{}
|
||||
|
||||
std::ptrdiff_t point_count() const noexcept
|
||||
{
|
||||
const auto abs_width = std::abs(end_point.x - start_point.x) + 1;
|
||||
const auto abs_height = std::abs(end_point.y - start_point.y) + 1;
|
||||
return abs_width > abs_height ? abs_width : abs_height;
|
||||
}
|
||||
|
||||
template <typename OutputIterator>
|
||||
void operator()(OutputIterator d_first) const
|
||||
{
|
||||
// mutable stack copies
|
||||
point_t start = start_point;
|
||||
point_t end = end_point;
|
||||
|
||||
if (start == end)
|
||||
{
|
||||
// put the point and immediately exit, as later on division by zero will
|
||||
// occur
|
||||
*d_first = start;
|
||||
return;
|
||||
}
|
||||
|
||||
auto width = std::abs(end.x - start.x) + 1;
|
||||
auto height = std::abs(end.y - start.y) + 1;
|
||||
bool const needs_flip = width < height;
|
||||
if (needs_flip)
|
||||
{
|
||||
// transpose the coordinate system if uncomfortable angle detected
|
||||
std::swap(width, height);
|
||||
std::swap(start.x, start.y);
|
||||
std::swap(end.x, end.y);
|
||||
}
|
||||
std::ptrdiff_t const x_increment = end.x >= start.x ? 1 : -1;
|
||||
std::ptrdiff_t const y_increment = end.y >= start.y ? 1 : -1;
|
||||
double const slope =
|
||||
height == 1 ? 0 : static_cast<double>(height) / static_cast<double>(width);
|
||||
std::ptrdiff_t y = start.y;
|
||||
double error_term = 0;
|
||||
for (std::ptrdiff_t x = start.x; x != end.x; x += x_increment)
|
||||
{
|
||||
// transpose coordinate system back to proper form if needed
|
||||
*d_first++ = needs_flip ? point_t{y, x} : point_t{x, y};
|
||||
error_term += slope;
|
||||
if (error_term >= 0.5)
|
||||
{
|
||||
--error_term;
|
||||
y += y_increment;
|
||||
}
|
||||
}
|
||||
*d_first++ = needs_flip ? point_t{end.y, end.x} : end;
|
||||
}
|
||||
|
||||
point_t start_point;
|
||||
point_t end_point;
|
||||
};
|
||||
|
||||
namespace detail {
|
||||
|
||||
template <typename View, typename Rasterizer, typename Pixel>
|
||||
struct apply_rasterizer_op<View, Rasterizer, Pixel, line_rasterizer_t>
|
||||
{
|
||||
void operator()(
|
||||
View const& view, Rasterizer const& rasterizer, Pixel const& pixel)
|
||||
{
|
||||
std::vector<point_t> trajectory(rasterizer.point_count());
|
||||
rasterizer(std::begin(trajectory));
|
||||
|
||||
for (auto const& point : trajectory)
|
||||
{
|
||||
view(point) = pixel;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} //namespace detail
|
||||
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
@@ -12,24 +12,23 @@
|
||||
#include <boost/gil/color_convert.hpp>
|
||||
#include <boost/gil/rgba.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
using cmyka_t = mpl::vector5<cyan_t, magenta_t, yellow_t, black_t, alpha_t>;
|
||||
using cmyka_t = mp11::mp_list<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)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, cmyka)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(8s, int8_t, cmyka)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(16, uint16_t, cmyka)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(16s, int16_t, cmyka)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32, uint32_t, cmyka)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32s, int32_t, cmyka)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, cmyka)
|
||||
|
||||
///// \ingroup ColorConvert
|
||||
///// \brief Converting CMYKA to any pixel type. Note: Supports homogeneous pixels only.
|
||||
|
||||
@@ -12,31 +12,30 @@
|
||||
#include <boost/gil/gray.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
|
||||
#include <boost/mpl/contains.hpp>
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
using gray_alpha_t = mpl::vector2<gray_color_t,alpha_t>;
|
||||
using gray_alpha_t = mp11::mp_list<gray_color_t,alpha_t>;
|
||||
|
||||
using gray_alpha_layout_t = layout<gray_alpha_t>;
|
||||
using alpha_gray_layout_t = layout<gray_alpha_layout_t, mpl::vector2_c<int,1,0>>;
|
||||
using alpha_gray_layout_t = layout<gray_alpha_layout_t, mp11::mp_list_c<int,1,0>>;
|
||||
|
||||
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)
|
||||
BOOST_GIL_DEFINE_BASE_TYPEDEFS(8, uint8_t, alpha_gray)
|
||||
BOOST_GIL_DEFINE_BASE_TYPEDEFS(8s, int8_t, alpha_gray)
|
||||
BOOST_GIL_DEFINE_BASE_TYPEDEFS(16, uint16_t, alpha_gray)
|
||||
BOOST_GIL_DEFINE_BASE_TYPEDEFS(16s, int16_t, alpha_gray)
|
||||
BOOST_GIL_DEFINE_BASE_TYPEDEFS(32, uint32_t, alpha_gray)
|
||||
BOOST_GIL_DEFINE_BASE_TYPEDEFS(32s, int32_t, alpha_gray)
|
||||
BOOST_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)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, gray_alpha)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(8s, int8_t, gray_alpha)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(16, uint16_t, gray_alpha)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(16s, int16_t, gray_alpha)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32, uint32_t, gray_alpha)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32s, int32_t, gray_alpha)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, gray_alpha)
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief Gray Alpha to RGBA
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <boost/gil/color_convert.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
@@ -27,18 +28,18 @@ struct lightness_t {};
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
using hsl_t = mpl::vector3
|
||||
<
|
||||
hsl_color_space::hue_t,
|
||||
hsl_color_space::saturation_t,
|
||||
hsl_color_space::lightness_t
|
||||
>;
|
||||
using hsl_t = mp11::mp_list
|
||||
<
|
||||
hsl_color_space::hue_t,
|
||||
hsl_color_space::saturation_t,
|
||||
hsl_color_space::lightness_t
|
||||
>;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
using hsl_layout_t = layout<hsl_t>;
|
||||
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsl)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsl)
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to HSL
|
||||
@@ -74,6 +75,7 @@ struct default_color_converter_impl< rgb_t, hsl_t >
|
||||
{
|
||||
|
||||
float32_t diff = max_color - min_color;
|
||||
float32_t sum = max_color + min_color;
|
||||
|
||||
// lightness calculation
|
||||
|
||||
@@ -83,13 +85,11 @@ struct default_color_converter_impl< rgb_t, hsl_t >
|
||||
|
||||
if( lightness < 0.5f )
|
||||
{
|
||||
saturation = diff
|
||||
/ ( min_color + max_color );
|
||||
saturation = diff / ( sum );
|
||||
}
|
||||
else
|
||||
{
|
||||
saturation = ( max_color - min_color )
|
||||
/ ( 2.f - diff );
|
||||
saturation = diff / ( 2.f - sum );
|
||||
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ struct default_color_converter_impl< rgb_t, hsl_t >
|
||||
{
|
||||
// max_color is blue
|
||||
hue = 4.f
|
||||
+ ( temp_red - temp_blue )
|
||||
+ ( temp_red - temp_green )
|
||||
/ diff;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,9 @@
|
||||
#ifndef BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSV_HPP
|
||||
#define BOOST_GIL_EXTENSION_TOOLBOX_COLOR_SPACES_HSV_HPP
|
||||
|
||||
#include <boost/numeric/conversion/cast.hpp>
|
||||
|
||||
#include <boost/gil/color_convert.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
@@ -34,17 +31,17 @@ struct value_t {};
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
using hsv_t = mpl::vector3
|
||||
<
|
||||
hsv_color_space::hue_t,
|
||||
hsv_color_space::saturation_t,
|
||||
hsv_color_space::value_t
|
||||
>;
|
||||
using hsv_t = mp11::mp_list
|
||||
<
|
||||
hsv_color_space::hue_t,
|
||||
hsv_color_space::saturation_t,
|
||||
hsv_color_space::value_t
|
||||
>;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
using hsv_layout_t = layout<hsv_t>;
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsv)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, hsv)
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to HSV
|
||||
@@ -87,7 +84,7 @@ struct default_color_converter_impl< rgb_t, hsv_t >
|
||||
}
|
||||
else
|
||||
{
|
||||
if( (std::abs)( boost::numeric_cast<float32_t>(temp_red - max_color) ) < 0.0001f )
|
||||
if( (std::abs)( temp_red - max_color ) < 0.0001f )
|
||||
{
|
||||
hue = ( temp_green - temp_blue )
|
||||
/ diff;
|
||||
@@ -131,7 +128,7 @@ struct default_color_converter_impl<hsv_t,rgb_t>
|
||||
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 (std::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() );
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
|
||||
#include <boost/gil/color_convert.hpp>
|
||||
#include <boost/gil.hpp> // FIXME: Include what you use, not everything, even in extensions!
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
@@ -31,17 +30,17 @@ struct b_color_opponent_t {};
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
using lab_t = mpl::vector3
|
||||
<
|
||||
lab_color_space::luminance_t,
|
||||
lab_color_space::a_color_opponent_t,
|
||||
lab_color_space::b_color_opponent_t
|
||||
>;
|
||||
using lab_t = mp11::mp_list
|
||||
<
|
||||
lab_color_space::luminance_t,
|
||||
lab_color_space::a_color_opponent_t,
|
||||
lab_color_space::b_color_opponent_t
|
||||
>;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
using lab_layout_t = layout<lab_t>;
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, lab)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, lab)
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief LAB to XYZ
|
||||
|
||||
@@ -10,8 +10,7 @@
|
||||
|
||||
#include <boost/gil/color_convert.hpp>
|
||||
#include <boost/gil/typedefs.hpp>
|
||||
|
||||
#include <boost/mpl/vector.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
@@ -29,17 +28,17 @@ struct z_t {};
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
using xyz_t = mpl::vector3
|
||||
<
|
||||
xyz_color_space::x_t,
|
||||
xyz_color_space::y_t,
|
||||
xyz_color_space::z_t
|
||||
>;
|
||||
using xyz_t = mp11::mp_list
|
||||
<
|
||||
xyz_color_space::x_t,
|
||||
xyz_color_space::y_t,
|
||||
xyz_color_space::z_t
|
||||
>;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
using xyz_layout_t = layout<xyz_t>;
|
||||
|
||||
GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, xyz)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(32f, float32_t, xyz)
|
||||
|
||||
/// \ingroup ColorConvert
|
||||
/// \brief RGB to XYZ
|
||||
|
||||
@@ -12,16 +12,14 @@
|
||||
|
||||
#include <boost/gil/color_convert.hpp>
|
||||
#include <boost/gil.hpp> // FIXME: Include what you use!
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/mpl/identity.hpp>
|
||||
#include <boost/mpl/range_c.hpp>
|
||||
#include <boost/mpl/vector_c.hpp>
|
||||
|
||||
#include <cstdint>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
namespace boost { namespace gil {
|
||||
|
||||
/// \addtogroup ColorNameModel
|
||||
/// \{
|
||||
@@ -47,36 +45,38 @@ struct cr_t {};
|
||||
/// \}
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
using ycbcr_601__t = boost::mpl::vector3
|
||||
<
|
||||
ycbcr_601_color_space::y_t,
|
||||
ycbcr_601_color_space::cb_t,
|
||||
ycbcr_601_color_space::cr_t>
|
||||
;
|
||||
using ycbcr_601__t = mp11::mp_list
|
||||
<
|
||||
ycbcr_601_color_space::y_t,
|
||||
ycbcr_601_color_space::cb_t,
|
||||
ycbcr_601_color_space::cr_t
|
||||
>;
|
||||
|
||||
/// \ingroup ColorSpaceModel
|
||||
using ycbcr_709__t = boost::mpl::vector3
|
||||
<
|
||||
ycbcr_709_color_space::y_t,
|
||||
ycbcr_709_color_space::cb_t,
|
||||
ycbcr_709_color_space::cr_t
|
||||
>;
|
||||
using ycbcr_709__t = mp11::mp_list
|
||||
<
|
||||
ycbcr_709_color_space::y_t,
|
||||
ycbcr_709_color_space::cb_t,
|
||||
ycbcr_709_color_space::cr_t
|
||||
>;
|
||||
|
||||
/// \ingroup LayoutModel
|
||||
using ycbcr_601__layout_t = boost::gil::layout<ycbcr_601__t>;
|
||||
using ycbcr_709__layout_t = boost::gil::layout<ycbcr_709__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_)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, ycbcr_601_)
|
||||
BOOST_GIL_DEFINE_ALL_TYPEDEFS(8, uint8_t, ycbcr_709_)
|
||||
|
||||
namespace detail {
|
||||
|
||||
// Source:boost/algorithm/clamp.hpp
|
||||
template<typename T>
|
||||
BOOST_CXX14_CONSTEXPR T const& clamp(T const& val,
|
||||
typename boost::mpl::identity<T>::type const & lo,
|
||||
typename boost::mpl::identity<T>::type const & hi)
|
||||
BOOST_CXX14_CONSTEXPR
|
||||
T const& clamp(
|
||||
T const& val,
|
||||
typename boost::mp11::mp_identity<T>::type const & lo,
|
||||
typename boost::mp11::mp_identity<T>::type const & hi)
|
||||
{
|
||||
// assert ( !p ( hi, lo )); // Can't assert p ( lo, hi ) b/c they might be equal
|
||||
auto const p = std::less<T>();
|
||||
@@ -105,8 +105,8 @@ struct default_color_converter_impl<ycbcr_601__t, rgb_t>
|
||||
using dst_channel_t = typename channel_type<DSTP>::type;
|
||||
convert(src, dst, typename std::is_same
|
||||
<
|
||||
typename mpl::int_<sizeof(dst_channel_t)>::type,
|
||||
typename mpl::int_<1>::type
|
||||
std::integral_constant<int, sizeof(dst_channel_t)>,
|
||||
std::integral_constant<int, 1>
|
||||
>::type());
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ private:
|
||||
>
|
||||
void convert( const Src_Pixel& src
|
||||
, Dst_Pixel& dst
|
||||
, mpl::true_ // is 8 bit channel
|
||||
, std::true_type // is 8 bit channel
|
||||
) const
|
||||
{
|
||||
using namespace ycbcr_601_color_space;
|
||||
@@ -149,7 +149,7 @@ private:
|
||||
>
|
||||
void convert( const Src_Pixel& src
|
||||
, Dst_Pixel& dst
|
||||
, mpl::false_ // is 8 bit channel
|
||||
, std::false_type // is 8 bit channel
|
||||
) const
|
||||
{
|
||||
using namespace ycbcr_601_color_space;
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
|
||||
#include <boost/gil/extension/dynamic_image/dynamic_image_all.hpp>
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/size.hpp>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
// need this for various meta functions.
|
||||
|
||||
@@ -13,20 +13,24 @@
|
||||
#include <boost/gil/image.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
#include <boost/gil/virtual_locator.hpp>
|
||||
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/gil/detail/is_channel_integral.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
namespace boost { namespace gil {
|
||||
|
||||
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
|
||||
> {};
|
||||
struct get_pixel_type_locator
|
||||
{
|
||||
using type = mp11::mp_if
|
||||
<
|
||||
typename is_bit_aligned<typename Locator::value_type>::type,
|
||||
typename Locator::reference,
|
||||
typename Locator::value_type
|
||||
>;
|
||||
};
|
||||
|
||||
// used for virtual locator
|
||||
template< typename IndicesLoc
|
||||
@@ -96,7 +100,7 @@ struct indexed_image_deref_fn : indexed_image_deref_fn_base< IndicesLoc
|
||||
)
|
||||
{}
|
||||
|
||||
typename base_t::result_type operator()( const point_t& p ) const
|
||||
typename base_t::result_type operator()( point_t const& p ) const
|
||||
{
|
||||
return * this->_palette_loc.xy_at( at_c<0>( *this->_indices_loc.xy_at( p )), 0 );
|
||||
}
|
||||
@@ -110,7 +114,7 @@ struct indexed_image_deref_fn
|
||||
PaletteLoc,
|
||||
typename std::enable_if
|
||||
<
|
||||
std::is_integral<typename IndicesLoc::value_type>::value
|
||||
detail::is_channel_integral<typename IndicesLoc::value_type>::value
|
||||
>::type
|
||||
> : indexed_image_deref_fn_base<IndicesLoc, PaletteLoc>
|
||||
{
|
||||
@@ -162,7 +166,7 @@ public:
|
||||
, _num_colors( 0 )
|
||||
{}
|
||||
|
||||
indexed_image_view( const point_t& dimensions
|
||||
indexed_image_view( point_t const& dimensions
|
||||
, std::size_t num_colors
|
||||
, const Locator& locator
|
||||
)
|
||||
@@ -276,7 +280,7 @@ public:
|
||||
init( point_t( width, height ), num_colors );
|
||||
}
|
||||
|
||||
indexed_image( const point_t& dimensions
|
||||
indexed_image( point_t const& dimensions
|
||||
, const std::size_t num_colors = 1
|
||||
, const std::size_t indices_alignment = 0
|
||||
, const std::size_t palette_alignment = 0
|
||||
@@ -319,7 +323,7 @@ public:
|
||||
|
||||
private:
|
||||
|
||||
void init( const point_t& dimensions
|
||||
void init( point_t const& dimensions
|
||||
, const std::size_t num_colors
|
||||
)
|
||||
{
|
||||
|
||||
@@ -13,17 +13,11 @@
|
||||
#include <boost/gil/image_view.hpp>
|
||||
#include <boost/gil/point.hpp>
|
||||
#include <boost/gil/virtual_locator.hpp>
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/mpl/divides.hpp>
|
||||
#include <boost/mpl/equal_to.hpp>
|
||||
#include <boost/mpl/if.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/or.hpp>
|
||||
#include <boost/mpl/vector_c.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace boost { namespace gil {
|
||||
|
||||
@@ -32,41 +26,36 @@ namespace detail {
|
||||
template< int J, int A, int B>
|
||||
struct scaling_factors
|
||||
{
|
||||
static_assert(mpl::equal_to< mpl::int_< J >, mpl::int_< 4 > >::value, "");
|
||||
static_assert(std::integral_constant<int, J>::value == 4, "");
|
||||
|
||||
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 > >
|
||||
>
|
||||
>::value, "");
|
||||
static_assert(
|
||||
std::integral_constant<int, A>::value == 4 ||
|
||||
std::integral_constant<int, A>::value == 2 ||
|
||||
std::integral_constant<int, A>::value == 1,
|
||||
"");
|
||||
|
||||
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 > >
|
||||
>
|
||||
>
|
||||
>::value, "");
|
||||
static_assert(
|
||||
std::integral_constant<int, B>::value == 4 ||
|
||||
std::integral_constant<int, B>::value == 2 ||
|
||||
std::integral_constant<int, B>::value == 1 ||
|
||||
std::integral_constant<int, B>::value == 0,
|
||||
"");
|
||||
|
||||
static constexpr int ss_X =
|
||||
mpl::divides
|
||||
<
|
||||
mpl::int_<J>,
|
||||
mpl::int_<A>
|
||||
>::value;
|
||||
std::integral_constant<int, J>::value / std::integral_constant<int, A>::value;
|
||||
|
||||
static constexpr int ss_Y =
|
||||
mpl::if_
|
||||
mp11::mp_if_c
|
||||
<
|
||||
mpl::equal_to<mpl::int_<B>, mpl::int_<0>>,
|
||||
mpl::int_<2>,
|
||||
typename mpl::if_
|
||||
std::integral_constant<int, B>::value == 0,
|
||||
std::integral_constant<int, 2>,
|
||||
mp11::mp_if_c
|
||||
<
|
||||
mpl::equal_to<mpl::int_<A>, mpl::int_<B>>,
|
||||
mpl::int_<1>,
|
||||
mpl::int_<4>
|
||||
>::type
|
||||
>::type::value;
|
||||
std::integral_constant<int, A>::value == std::integral_constant<int, B>::value,
|
||||
std::integral_constant<int, 1>,
|
||||
std::integral_constant<int, 4>
|
||||
>
|
||||
>::value;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
@@ -107,13 +96,13 @@ struct subchroma_image_deref_fn
|
||||
{}
|
||||
|
||||
/// operator()
|
||||
result_type operator()( const point_t& p ) const
|
||||
result_type operator()( point_t const& p ) const
|
||||
{
|
||||
using scaling_factors_t = detail::scaling_factors
|
||||
<
|
||||
mpl::at_c<Factors, 0>::type::value,
|
||||
mpl::at_c<Factors, 1>::type::value,
|
||||
mpl::at_c<Factors, 2>::type::value
|
||||
mp11::mp_at_c<Factors, 0>::value,
|
||||
mp11::mp_at_c<Factors, 1>::value,
|
||||
mp11::mp_at_c<Factors, 2>::value
|
||||
>;
|
||||
|
||||
plane_locator_t y = _y_locator.xy_at( p );
|
||||
@@ -215,10 +204,12 @@ struct transposed_type< subchroma_image_locator< Locator, Factors > >
|
||||
/// \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 >
|
||||
template
|
||||
<
|
||||
typename Locator,
|
||||
typename Factors = mp11::mp_list_c<int, 4, 4, 4>
|
||||
>
|
||||
class subchroma_image_view : public image_view<Locator>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -237,9 +228,9 @@ public:
|
||||
{}
|
||||
|
||||
/// constructor
|
||||
subchroma_image_view( const point_t& y_dimensions
|
||||
, const point_t& v_dimensions
|
||||
, const point_t& u_dimensions
|
||||
subchroma_image_view( point_t const& y_dimensions
|
||||
, point_t const& v_dimensions
|
||||
, point_t const& u_dimensions
|
||||
, const Locator& locator
|
||||
)
|
||||
: image_view< Locator >( y_dimensions, locator )
|
||||
@@ -254,20 +245,20 @@ public:
|
||||
: 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() ); }
|
||||
point_t v_ssfactors() const { return point_t( get_deref_fn().vx_ssfactor(), get_deref_fn().vx_ssfactor() ); }
|
||||
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; }
|
||||
point_t const& y_dimension() const { return _y_dimensions; }
|
||||
point_t const& v_dimension() const { return _v_dimensions; }
|
||||
point_t const& 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() ); }
|
||||
plane_view_t y_plane_view() const { return plane_view_t( _y_dimensions, y_plane() ); }
|
||||
plane_view_t v_plane_view() const { return plane_view_t( _v_dimensions, v_plane() ); }
|
||||
plane_view_t u_plane_view() const { return plane_view_t( _u_dimensions, u_plane() ); }
|
||||
|
||||
|
||||
private:
|
||||
@@ -339,21 +330,27 @@ struct transposed_type< subchroma_image_view< Locator, Factors > >
|
||||
/// 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 detail::scaling_factors< mpl::at_c< Factors, 0 >::type::value
|
||||
, mpl::at_c< Factors, 1 >::type::value
|
||||
, mpl::at_c< Factors, 2 >::type::value
|
||||
>
|
||||
template
|
||||
<
|
||||
typename Pixel,
|
||||
typename Factors = mp11::mp_list_c<int, 4, 4, 4>,
|
||||
typename Allocator = std::allocator<unsigned char>
|
||||
>
|
||||
class subchroma_image : public detail::scaling_factors
|
||||
<
|
||||
mp11::mp_at_c<Factors, 0>::value,
|
||||
mp11::mp_at_c<Factors, 1>::value,
|
||||
mp11::mp_at_c<Factors, 2>::value
|
||||
>
|
||||
{
|
||||
|
||||
private:
|
||||
using parent_t = detail::scaling_factors< mpl::at_c< Factors, 0 >::type::value
|
||||
, mpl::at_c< Factors, 1 >::type::value
|
||||
, mpl::at_c< Factors, 2 >::type::value
|
||||
>;
|
||||
using parent_t = detail::scaling_factors
|
||||
<
|
||||
mp11::mp_at_c<Factors, 0>::value,
|
||||
mp11::mp_at_c<Factors, 1>::value,
|
||||
mp11::mp_at_c<Factors, 2>::value
|
||||
>;
|
||||
|
||||
public:
|
||||
|
||||
@@ -436,19 +433,20 @@ private:
|
||||
|
||||
template < typename Pixel, typename Factors, typename Alloc >
|
||||
struct channel_type< subchroma_image< Pixel, Factors, Alloc > >
|
||||
: public channel_type< Pixel > {};
|
||||
: channel_type< Pixel > {};
|
||||
|
||||
template < typename Pixel, typename Factors, typename Alloc >
|
||||
struct color_space_type< subchroma_image< Pixel, Factors, Alloc > >
|
||||
: public color_space_type< Pixel > {};
|
||||
: 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 > {};
|
||||
: channel_mapping_type< Pixel > {};
|
||||
|
||||
template < typename Pixel, typename Factors, typename Alloc >
|
||||
struct is_planar< subchroma_image< Pixel, Factors, Alloc > >
|
||||
: public mpl::bool_< false > {};
|
||||
: std::integral_constant<bool, false>
|
||||
{};
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -514,9 +512,9 @@ typename subchroma_image< Pixel
|
||||
{
|
||||
using scaling_factors_t = detail::scaling_factors
|
||||
<
|
||||
mpl::at_c<Factors, 0>::type::value,
|
||||
mpl::at_c<Factors, 1>::type::value,
|
||||
mpl::at_c<Factors, 2>::type::value
|
||||
mp11::mp_at_c<Factors, 0>::type::value,
|
||||
mp11::mp_at_c<Factors, 1>::type::value,
|
||||
mp11::mp_at_c<Factors, 2>::type::value
|
||||
>;
|
||||
|
||||
std::size_t y_channel_size = 1;
|
||||
@@ -527,23 +525,24 @@ typename subchroma_image< Pixel
|
||||
* u_channel_size;
|
||||
|
||||
using plane_view_t = typename subchroma_image<Pixel, Factors>::plane_view_t;
|
||||
using plane_value_t = typename plane_view_t::value_type;
|
||||
|
||||
plane_view_t y_plane = interleaved_view( y_width
|
||||
, y_height
|
||||
, (typename plane_view_t::value_type*) y_base // pixels
|
||||
, y_width // rowsize_in_bytes
|
||||
, (plane_value_t*) 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
|
||||
, (typename plane_view_t::value_type*) v_base // pixels
|
||||
, y_width // rowsize_in_bytes
|
||||
, (plane_value_t*) 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
|
||||
, (typename plane_view_t::value_type*) u_base // pixels
|
||||
, y_width // rowsize_in_bytes
|
||||
, (plane_value_t*) u_base // pixels
|
||||
, y_width // rowsize_in_bytes
|
||||
);
|
||||
|
||||
using defer_fn_t = subchroma_image_deref_fn
|
||||
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
#include <boost/gil/bit_aligned_pixel_reference.hpp>
|
||||
#include <boost/gil/channel.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <boost/utility/enable_if.hpp> // boost::lazy_enable_if
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
@@ -29,7 +29,7 @@ struct gen_chan_ref
|
||||
using type = packed_dynamic_channel_reference
|
||||
<
|
||||
B,
|
||||
mpl::at_c<C, 0>::type::value,
|
||||
mp11::mp_at_c<C, 0>::value,
|
||||
M
|
||||
>;
|
||||
};
|
||||
@@ -58,27 +58,27 @@ struct gen_chan_ref_p
|
||||
using type = packed_dynamic_channel_reference
|
||||
<
|
||||
B,
|
||||
get_num_bits<typename mpl::at_c<C, 0>::type>::value,
|
||||
get_num_bits<mp11::mp_at_c<C, 0>>::value,
|
||||
true
|
||||
>;
|
||||
};
|
||||
|
||||
// packed_pixel
|
||||
template < typename BitField
|
||||
, typename ChannelRefVec
|
||||
, typename ChannelRefs
|
||||
, typename Layout
|
||||
>
|
||||
struct channel_type< packed_pixel< BitField
|
||||
, ChannelRefVec
|
||||
, ChannelRefs
|
||||
, Layout
|
||||
>
|
||||
> : lazy_enable_if< is_homogeneous< packed_pixel< BitField
|
||||
, ChannelRefVec
|
||||
, ChannelRefs
|
||||
, Layout
|
||||
>
|
||||
>
|
||||
, gen_chan_ref_p< BitField
|
||||
, ChannelRefVec
|
||||
, ChannelRefs
|
||||
, Layout
|
||||
>
|
||||
> {};
|
||||
|
||||
@@ -13,28 +13,28 @@
|
||||
namespace boost {
|
||||
namespace gil {
|
||||
|
||||
template < typename Channel
|
||||
, typename View
|
||||
>
|
||||
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
|
||||
>::value; //< index of the channel in the color (mpl::vector)
|
||||
static constexpr int value = detail::type_to_index
|
||||
<
|
||||
typename color_space_type<View>::type, // color (Boost.MP11-compatible list)
|
||||
Channel // channel type
|
||||
>::value; // index of the channel in the color (Boost.MP11-compatible list)
|
||||
};
|
||||
|
||||
template< typename Channel
|
||||
, typename View
|
||||
>
|
||||
struct channel_view_type : public kth_channel_view_type< channel_type_to_index< Channel
|
||||
, View
|
||||
>::value
|
||||
, View
|
||||
>
|
||||
template<typename Channel, typename View>
|
||||
struct channel_view_type : kth_channel_view_type
|
||||
<
|
||||
channel_type_to_index<Channel, View>::value,
|
||||
View
|
||||
>
|
||||
{
|
||||
static const int index = channel_type_to_index< Channel
|
||||
, View
|
||||
>::value;
|
||||
static constexpr int index = channel_type_to_index
|
||||
<
|
||||
Channel,
|
||||
View
|
||||
>::value;
|
||||
|
||||
using parent_t = kth_channel_view_type<index, View>;
|
||||
using type = typename parent_t::type;
|
||||
@@ -46,19 +46,13 @@ struct channel_view_type : public kth_channel_view_type< channel_type_to_index<
|
||||
};
|
||||
|
||||
/// \ingroup ImageViewTransformationsKthChannel
|
||||
template< typename Channel
|
||||
, typename View
|
||||
>
|
||||
typename channel_view_type< Channel
|
||||
, View
|
||||
>::type channel_view( const View& src )
|
||||
template<typename Channel, typename View>
|
||||
auto channel_view(View const& src)
|
||||
-> typename channel_view_type<Channel, View>::type
|
||||
{
|
||||
return channel_view_type< Channel
|
||||
, View
|
||||
>::make( src );
|
||||
return channel_view_type<Channel, View>::make(src);
|
||||
}
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,13 +9,8 @@
|
||||
#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_GET_NUM_BITS_HPP
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
#include <boost/mpl/not.hpp>
|
||||
#include <boost/mpl/size_t.hpp>
|
||||
#include <boost/type_traits/is_integral.hpp>
|
||||
#include <boost/type_traits/is_class.hpp>
|
||||
#include <boost/gil/detail/is_channel_integral.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
@@ -24,50 +19,53 @@ namespace boost{ namespace gil {
|
||||
/// get_num_bits metafunctions
|
||||
/// \brief Determines the numbers of bits for the given channel type.
|
||||
|
||||
template <typename T, class = void >
|
||||
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<packed_channel_reference<B, I, S, M>>
|
||||
: std::integral_constant<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, int S, bool M>
|
||||
struct get_num_bits<packed_channel_reference<B, I, S, M> const>
|
||||
: std::integral_constant<int, S>
|
||||
{};
|
||||
|
||||
template<typename B, int I, bool M>
|
||||
struct get_num_bits< packed_dynamic_channel_reference< B, I, M > > : mpl::int_< I >
|
||||
struct get_num_bits<packed_dynamic_channel_reference<B, I, M>>
|
||||
: std::integral_constant<int, I>
|
||||
{};
|
||||
|
||||
template<typename B, int I, bool M>
|
||||
struct get_num_bits< const packed_dynamic_channel_reference< B, I, M > > : mpl::int_< I >
|
||||
struct get_num_bits<packed_dynamic_channel_reference<B, I, M> const>
|
||||
: std::integral_constant<int, I>
|
||||
{};
|
||||
|
||||
template< int N >
|
||||
struct get_num_bits< packed_channel_value< N > > : mpl::int_< N >
|
||||
template<int N>
|
||||
struct get_num_bits<packed_channel_value<N>> : std::integral_constant<int, N>
|
||||
{};
|
||||
|
||||
template< int N >
|
||||
struct get_num_bits< const packed_channel_value< N > > : mpl::int_< N >
|
||||
template<int N>
|
||||
struct get_num_bits<packed_channel_value<N> const> : std::integral_constant<int, N>
|
||||
{};
|
||||
|
||||
template <typename T>
|
||||
struct get_num_bits
|
||||
<
|
||||
T,
|
||||
typename std::enable_if
|
||||
<
|
||||
mpl::and_
|
||||
T,
|
||||
typename std::enable_if
|
||||
<
|
||||
is_integral<T>,
|
||||
mpl::not_<is_class<T>>
|
||||
>::value
|
||||
>::type
|
||||
> : mpl::size_t<sizeof(T) * 8>
|
||||
{
|
||||
};
|
||||
mp11::mp_and
|
||||
<
|
||||
detail::is_channel_integral<T>,
|
||||
mp11::mp_not<std::is_class<T>>
|
||||
>::value
|
||||
>::type
|
||||
>
|
||||
: std::integral_constant<std::size_t, sizeof(T) * 8>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,25 +11,31 @@
|
||||
#include <boost/gil/extension/toolbox/dynamic_images.hpp>
|
||||
#include <boost/gil/extension/toolbox/metafunctions/is_bit_aligned.hpp>
|
||||
|
||||
#include <boost/gil/detail/mp11.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 View>
|
||||
struct get_pixel_type
|
||||
{
|
||||
using type = mp11::mp_if
|
||||
<
|
||||
is_bit_aligned<typename View::value_type>,
|
||||
typename View::reference,
|
||||
typename View::value_type
|
||||
>;
|
||||
};
|
||||
|
||||
template< typename ImageViewTypes >
|
||||
struct get_pixel_type< any_image_view< ImageViewTypes > >
|
||||
template<typename ...Views>
|
||||
struct get_pixel_type<any_image_view<Views...>>
|
||||
{
|
||||
using type = any_image_pixel_t;
|
||||
};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,27 +10,28 @@
|
||||
|
||||
#include <boost/gil/bit_aligned_pixel_reference.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
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_{};
|
||||
struct is_bit_aligned : std::false_type {};
|
||||
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct is_bit_aligned<bit_aligned_pixel_reference<B,C,L,M> > : mpl::true_{};
|
||||
struct is_bit_aligned<bit_aligned_pixel_reference<B, C, L, M>> : std::true_type {};
|
||||
|
||||
template <typename B, typename C, typename L, bool M>
|
||||
struct is_bit_aligned<const bit_aligned_pixel_reference<B,C,L,M> > : mpl::true_{};
|
||||
struct is_bit_aligned<bit_aligned_pixel_reference<B, C, L, M> const> : std::true_type {};
|
||||
|
||||
template <typename B, typename C, typename L>
|
||||
struct is_bit_aligned<packed_pixel<B,C,L> > : mpl::true_{};
|
||||
struct is_bit_aligned<packed_pixel<B, C, L>> : std::true_type {};
|
||||
|
||||
template <typename B, typename C, typename L>
|
||||
struct is_bit_aligned<const packed_pixel<B,C,L> > : mpl::true_{};
|
||||
struct is_bit_aligned<packed_pixel<B, C, L> const> : std::true_type {};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -9,74 +9,91 @@
|
||||
#define BOOST_GIL_EXTENSION_TOOLBOX_METAFUNCTIONS_IS_HOMOGENEOUS_HPP
|
||||
|
||||
#include <boost/gil/pixel.hpp>
|
||||
#include <boost/gil/detail/mp11.hpp>
|
||||
|
||||
#include <boost/mpl/and.hpp>
|
||||
#include <boost/mpl/at.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
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
|
||||
> > {};
|
||||
struct is_homogeneous_impl;
|
||||
|
||||
template < typename P > struct is_homogeneous : mpl::false_ {};
|
||||
template<typename C, typename CMP, int Last>
|
||||
struct is_homogeneous_impl<C, CMP, Last, Last> : std::true_type {};
|
||||
|
||||
template<typename C, typename CMP, int Next, int Last>
|
||||
struct is_homogeneous_impl
|
||||
: mp11::mp_and
|
||||
<
|
||||
is_homogeneous_impl<C, CMP, Next + 1, Last>,
|
||||
std::is_same<CMP, mp11::mp_at_c<C, Next>>
|
||||
>
|
||||
{};
|
||||
|
||||
template <typename P>
|
||||
struct is_homogeneous : std::false_type {};
|
||||
|
||||
// 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_ {};
|
||||
template <typename C, typename L>
|
||||
struct is_homogeneous<pixel<C, L>> : std::true_type {};
|
||||
|
||||
template <typename C, typename L >
|
||||
struct is_homogeneous<pixel<C, L> const> : std::true_type {};
|
||||
|
||||
template <typename C, typename L>
|
||||
struct is_homogeneous<pixel<C, L>&> : std::true_type {};
|
||||
|
||||
template <typename C, typename L>
|
||||
struct is_homogeneous<pixel<C, L> const&> : std::true_type {};
|
||||
|
||||
// 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_ {};
|
||||
struct is_homogeneous<planar_pixel_reference<Channel, ColorSpace>> : std::true_type {};
|
||||
|
||||
template<typename C,typename CMP, int I,int Last>
|
||||
template <typename Channel, typename ColorSpace>
|
||||
struct is_homogeneous<planar_pixel_reference<Channel, ColorSpace> const> : std::true_type {};
|
||||
|
||||
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 >::value
|
||||
> {};
|
||||
template <typename B, typename C, typename L>
|
||||
struct is_homogeneous<packed_pixel<B, C, L>>
|
||||
: is_homogeneous_impl_p
|
||||
<
|
||||
C,
|
||||
mp11::mp_at_c<C, 0>,
|
||||
1,
|
||||
mp11::mp_size<C>::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 >::value
|
||||
> {};
|
||||
struct is_homogeneous<packed_pixel<B, C, L> const>
|
||||
: is_homogeneous_impl_p
|
||||
<
|
||||
C,
|
||||
mp11::mp_at_c<C, 0>,
|
||||
1,
|
||||
mp11::mp_size<C>::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>::value>
|
||||
struct is_homogeneous<bit_aligned_pixel_reference<B, C, L, M>>
|
||||
: is_homogeneous_impl<C, mp11::mp_at_c<C, 0>, 1, mp11::mp_size<C>::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>::value>
|
||||
struct is_homogeneous<const bit_aligned_pixel_reference<B, C, L, M> >
|
||||
: is_homogeneous_impl<C, mp11::mp_at_c<C, 0>, 1, mp11::mp_size<C>::value>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -10,23 +10,26 @@
|
||||
|
||||
#include <boost/gil/channel.hpp>
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
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, typename B>
|
||||
struct is_similar : std::false_type {};
|
||||
|
||||
template<typename A>
|
||||
struct is_similar< A, A > : mpl::true_ {};
|
||||
struct is_similar<A, A> : std::true_type {};
|
||||
|
||||
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_ {};
|
||||
struct is_similar
|
||||
<
|
||||
packed_channel_reference<B, I, S, M>,
|
||||
packed_channel_reference<B, I2, S, M>
|
||||
> : std::true_type {};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,9 +11,6 @@
|
||||
#include <boost/gil/bit_aligned_pixel_reference.hpp>
|
||||
#include <boost/gil/packed_pixel.hpp>
|
||||
|
||||
#include <boost/mpl/accumulate.hpp>
|
||||
#include <boost/mpl/int.hpp>
|
||||
|
||||
namespace boost{ namespace gil {
|
||||
|
||||
/// pixel_bit_size metafunctions
|
||||
@@ -23,22 +20,50 @@ namespace boost{ namespace gil {
|
||||
/// using image_t = bit_aligned_image5_type<16, 16, 16, 8, 8, devicen_layout_t<5>>::type;
|
||||
/// 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 PixelRef>
|
||||
struct pixel_bit_size : std::integral_constant<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 >{};
|
||||
struct pixel_bit_size<bit_aligned_pixel_reference<B, C, L, M>>
|
||||
: mp11::mp_fold
|
||||
<
|
||||
C,
|
||||
std::integral_constant<int, 0>,
|
||||
mp11::mp_plus
|
||||
>
|
||||
{};
|
||||
|
||||
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 >{};
|
||||
struct pixel_bit_size<bit_aligned_pixel_reference<B, C, L, M> const>
|
||||
: mp11::mp_fold
|
||||
<
|
||||
C,
|
||||
std::integral_constant<int, 0>,
|
||||
mp11::mp_plus
|
||||
>
|
||||
{};
|
||||
|
||||
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 >{};
|
||||
struct pixel_bit_size<packed_pixel<B, C, L>>
|
||||
: mp11::mp_fold
|
||||
<
|
||||
C,
|
||||
std::integral_constant<int, 0>,
|
||||
mp11::mp_plus
|
||||
>
|
||||
|
||||
{};
|
||||
|
||||
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 >{};
|
||||
struct pixel_bit_size<const packed_pixel<B,C,L> >
|
||||
: mp11::mp_fold
|
||||
<
|
||||
C,
|
||||
std::integral_constant<int, 0>,
|
||||
mp11::mp_plus
|
||||
>
|
||||
{};
|
||||
|
||||
} // namespace gil
|
||||
} // namespace boost
|
||||
}} // namespace boost::gil
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user