Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: Deprecate apply_operation in favor of variant2::visit for any_image #656

Merged
merged 3 commits into from
Jun 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
support at least C++14 are considered unsupported as of now.
- BREAKING: `any_color_converted_view()` is deprecated and will be removed in the next release.
Use `color_converted_view()` instead, which provides the same feature.
- BREAKING: `apply_operation` for `any_image` is deprecated and will be removed in the next release.
Use `variant2::visit` instead, which provides the same feature.
- documentation: Display that GIL is a header-only library
- Moved numeric extension to core ([PR #573](https://github.com/boostorg/gil/pull/573))
- Added support for C++17's `<filesystem>` ([PR #636](https://github.com/boostorg/gil/pull/636)).
Expand Down Expand Up @@ -327,18 +329,18 @@ linked PDF documents with detailed changes.

### Changed
- Updated the design guide and tutorial, updated syntax of concepts to the latest concepts proposal.
- In `image`, `image_view`, `any_image`, `any_image_view`:
- In `image`, `image_view`, `any_image`, `any_image_view`:
There are no longer global functions `get_width()`, `get_height()`, `get_dimensions()`, `num_channels()`.
Use methods `width()`, `height()`, `dimensions()` instead.
- In models of pixel, pixel iterator, pixel locator, image view and image:
- In models of pixel, pixel iterator, pixel locator, image view and image:
There used to be different ways of getting to a pixel, channel, color space, etc. of an image view,
pixel, locator, iterator and image (e.g. traits, member typedefs).
Now all pixel-based GIL constructs (pixels, pixel iterators, locators, image views and images) model
`PixelBasedConcept`, which means they provide the following metafunctions: `color_space_type`, `channel_mapping_type`, `is_planar`, `num_channels`
and for homogeneous constructs we also have: `channel_type`.
To get the pixel type or pixel reference/const reference type of an image, image view, locator
and pixel, use member typedefs `value_type`, `reference` and `const_reference`.
- In `locator`, `image`, `image_view`, `any_image` and `any_image_view`:
- In `locator`, `image`, `image_view`, `any_image` and `any_image_view`:
Removed `dynamic_x_step_t`, `dynamic_y_step_t`, `dynamic_xy_step_t` and `dynamic_xy_step_transposed_t`
as member typedefs of locators and image views.
Instead, there are separate concepts `HasDynamicXStepTypeConcept`, `HasDynamicYStepTypeConcept`,
Expand Down
16 changes: 8 additions & 8 deletions doc/design/dynamic_image.rst
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ GIL ``any_image_view`` and ``any_image`` are subclasses of ``variant``:
y_coord_t height() const;
};

Operations are invoked on variants via ``apply_operation`` passing a
Operations are invoked on variants via ``variant2::visit`` passing a
function object to perform the operation. The code for every allowed
type in the variant is instantiated and the appropriate instantiation
is selected via a switch statement. Since image view algorithms
Expand All @@ -129,7 +129,7 @@ pixels. There is no "any_pixel" or "any_pixel_iterator" in GIL. Such
constructs could be provided via the ``variant`` mechanism, but doing
so would result in inefficient algorithms, since the type resolution
would have to be performed per pixel. Image-level algorithms should be
implemented via ``apply_operation``. That said, many common operations
implemented via ``variant2::visit``. That said, many common operations
are shared between the static and dynamic types. In addition, all of
the image view transformations and many STL-like image view algorithms
have overloads operating on ``any_image_view``, as illustrated with
Expand Down Expand Up @@ -180,25 +180,25 @@ implemented:
template <typename View>
typename dynamic_xy_step_type<View>::type rotated180_view(const View& src) { ... }

namespace detail
{
namespace detail {
// the function, wrapped inside a function object
template <typename Result> struct rotated180_view_fn
{
typedef Result result_type;
template <typename View> result_type operator()(const View& src) const
{
{
return result_type(rotated180_view(src));
}
};
}

// overloading of the function using variant. Takes and returns run-time bound view.
// The returned view has a dynamic step
template <typename ViewTypes> inline // Models MPL Random Access Container of models of ImageViewConcept
typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type rotated180_view(const any_image_view<ViewTypes>& src)
template <typename ...ViewTypes> inline
typename dynamic_xy_step_type<any_image_view<ViewTypes...>>::type rotated180_view(const any_image_view<ViewTypes...>& src)
{
return apply_operation(src,detail::rotated180_view_fn<typename dynamic_xy_step_type<any_image_view<ViewTypes> >::type>());
using result_view_t = typename dynamic_xy_step_type<any_image_view<ViewTypes...>>::type;
return variant2::visit(detail::rotated180_view_fn<result_view_t>(), src);
}

Variants should be used with caution (especially algorithms that take
Expand Down
14 changes: 7 additions & 7 deletions doc/tutorial/gradient.rst
Original file line number Diff line number Diff line change
Expand Up @@ -870,22 +870,22 @@ source view:
};

The second step is to provide an overload of ``x_luminosity_gradient`` that
takes image view variant and calls GIL's ``apply_operation`` passing it the
takes image view variant and calls ``variant2::visit`` passing it the
function object:

.. code-block:: cpp

template <typename SrcViews, typename DstView>
void x_luminosity_gradient(const any_image_view<SrcViews>& src, const DstView& dst)
template <typename ...SrcViews, typename DstView>
void x_luminosity_gradient(const any_image_view<SrcViews...>& src, const DstView& dst)
{
apply_operation(src, x_gradient_obj<DstView>(dst));
variant2::visit(x_gradient_obj<DstView>(dst), src);
}

``any_image_view<SrcViews>`` is the image view variant. It is
templated over ``SrcViews``, an enumeration of all possible view types
``any_image_view<SrcViews...>`` is the image view variant. It is
templated over ``SrcViews...``, an enumeration of all possible view types
the variant can take. ``src`` contains inside an index of the
currently instantiated type, as well as a block of memory containing
the instance. ``apply_operation`` goes through a switch statement
the instance. ``variant2::visit`` goes through a switch statement
over the index, each case of which casts the memory to the correct
view type and invokes the function object with it. Invoking an
algorithm on a variant has the overhead of one switch
Expand Down
52 changes: 28 additions & 24 deletions include/boost/gil/extension/dynamic_image/algorithm.hpp
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -12,7 +13,10 @@

#include <boost/gil/algorithm.hpp>

#include <boost/variant2/variant.hpp>

#include <functional>
#include <utility>

////////////////////////////////////////////////////////////////////////////////////////
/// \file
Expand Down Expand Up @@ -43,31 +47,31 @@ struct equal_pixels_fn : binary_operation_obj<equal_pixels_fn, bool>
/// \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)
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 Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename View, typename ...Types>
bool equal_pixels(View const& src, any_image_view<Types...> const& dst)
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 Boost.MP11-compatible list of models of ImageViewConcept
/// \tparam Types2 Model Boost.MP11-compatible list of models of MutableImageViewConcept
template <typename ...Types1, typename ...Types2>
bool equal_pixels(any_image_view<Types1...> const& src, any_image_view<Types2...> const& dst)
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 {
Expand All @@ -90,7 +94,7 @@ struct copy_pixels_fn : public binary_operation_obj<copy_pixels_fn>
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
Expand All @@ -99,7 +103,7 @@ void copy_pixels(any_image_view<Types...> const& src, View 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
Expand All @@ -108,7 +112,7 @@ void copy_pixels(View const& src, any_image_view<Types...> const& dst)
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)
Expand All @@ -122,7 +126,7 @@ 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
Expand All @@ -132,7 +136,7 @@ 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
Expand All @@ -143,7 +147,7 @@ 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
Expand All @@ -153,7 +157,7 @@ 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
Expand All @@ -165,7 +169,7 @@ void copy_and_convert_pixels(
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
Expand All @@ -176,8 +180,8 @@ void copy_and_convert_pixels(
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 {
Expand All @@ -186,15 +190,15 @@ 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
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>
Expand Down Expand Up @@ -227,7 +231,7 @@ struct fill_pixels_fn
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 {
Expand All @@ -236,7 +240,7 @@ 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
{
Expand Down
11 changes: 5 additions & 6 deletions include/boost/gil/extension/dynamic_image/any_image.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
#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>
Expand Down Expand Up @@ -121,7 +120,7 @@ class any_image : public variant2::variant<Images...>

void recreate(const point_t& dims, unsigned alignment=1)
{
apply_operation(*this, detail::recreate_image_fnobj(dims, alignment));
variant2::visit(detail::recreate_image_fnobj(dims, alignment), *this);
}

void recreate(x_coord_t width, y_coord_t height, unsigned alignment=1)
Expand All @@ -131,12 +130,12 @@ class any_image : public variant2::variant<Images...>

std::size_t num_channels() const
{
return apply_operation(*this, detail::any_type_get_num_channels());
return variant2::visit(detail::any_type_get_num_channels(), *this);
}

point_t dimensions() const
{
return apply_operation(*this, detail::any_type_get_dimensions());
return variant2::visit(detail::any_type_get_dimensions(), *this);
}

x_coord_t width() const { return dimensions().x; }
Expand All @@ -156,7 +155,7 @@ BOOST_FORCEINLINE
auto view(any_image<Images...>& img) -> typename any_image<Images...>::view_t
{
using view_t = typename any_image<Images...>::view_t;
return apply_operation(img, detail::any_image_get_view<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.
Expand All @@ -166,7 +165,7 @@ 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 apply_operation(img, detail::any_image_get_const_view<view_t>());
return variant2::visit(detail::any_image_get_const_view<view_t>(), img);
}
///@}

Expand Down
8 changes: 4 additions & 4 deletions include/boost/gil/extension/dynamic_image/any_image_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ struct any_type_get_size
/// 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 ...Views>
Expand Down Expand Up @@ -105,9 +105,9 @@ class any_image_view : public variant2::variant<Views...>
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()); }
size_type size() const { return apply_operation(*this, detail::any_type_get_size()); }
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; }
};
Expand Down
2 changes: 2 additions & 0 deletions include/boost/gil/extension/dynamic_image/apply_operation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace boost { namespace gil {
/// \ingroup Variant
/// \brief Applies the visitor op to the variants
template <typename Variant1, typename Visitor>
[[deprecated("Use variant2::visit instead.")]]
BOOST_FORCEINLINE
auto apply_operation(Variant1&& arg1, Visitor&& op)
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
Expand All @@ -27,6 +28,7 @@ auto apply_operation(Variant1&& arg1, Visitor&& op)
/// \ingroup Variant
/// \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(Variant1&& arg1, Variant2&& arg2, Visitor&& op)
#if defined(BOOST_NO_CXX14_DECLTYPE_AUTO) || defined(BOOST_NO_CXX11_DECLTYPE_N3276)
Expand Down
Loading