update boost

This commit is contained in:
2023-11-24 12:56:13 -06:00
parent cfc99971af
commit 19d727037a
9260 changed files with 849256 additions and 299957 deletions

View File

@@ -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

View File

@@ -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);
}
///@}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View 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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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 )
{

View File

@@ -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

View File

@@ -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
);
}
};

View File

@@ -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

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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 )
{

View File

@@ -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

View File

@@ -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 );
}
};

View File

@@ -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() );
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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 )
{

View File

@@ -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
<

View File

@@ -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 );
}
};

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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 )
{

View File

@@ -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

View File

@@ -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 );
}
};

View File

@@ -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

View File

@@ -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>;
};

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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 )
{

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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 )
{

View File

@@ -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

View File

@@ -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 );
}
};

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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 )
);
}
}

View File

@@ -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 )
{

View File

@@ -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

View File

@@ -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 );
}
};

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
///////////////////////////////////////////////////////////////////////////

View File

@@ -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;
}

View File

@@ -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

View 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

View 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

View 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

View File

@@ -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.

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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() );

View File

@@ -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

View File

@@ -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

View File

@@ -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;

View File

@@ -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.

View File

@@ -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
)
{

View File

@@ -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

View File

@@ -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
>
> {};

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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