Skip to content

Commit

Permalink
refactor: Deprecate apply_operation in favor of variant2::visit for a…
Browse files Browse the repository at this point in the history
…ny_image (#656)

build: Add /bigobj to MSVC flags

Avoid test\extension\dynamic_image\algorithm\copy_and_convert_pixels.cpp
compilation error:

fatal error C1128: number of sections exceeded object file format limit: compile with /bigobj

Co-authored-by: Mateusz Łoskot <mateusz@loskot.net>
  • Loading branch information
marco-langer and mloskot authored Jun 26, 2022
1 parent 151fd9c commit bfed3de
Show file tree
Hide file tree
Showing 35 changed files with 804 additions and 116 deletions.
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

0 comments on commit bfed3de

Please sign in to comment.