From d2d5c3789d480fada7e3a83b456ea141b4d2de55 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Wed, 4 May 2022 18:16:37 +0200 Subject: [PATCH 1/3] use std::size_t as channel index type in nth_channel_view This unifies the channel index type in nth_channel_view and image_view::num_channels - the latter one already uses std::size_t. Fixes #373. --- .../dynamic_image/image_view_factory.hpp | 7 ++-- include/boost/gil/image_view_factory.hpp | 34 +++++++++---------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/include/boost/gil/extension/dynamic_image/image_view_factory.hpp b/include/boost/gil/extension/dynamic_image/image_view_factory.hpp index a41dc32c54..d4fafc6dd7 100644 --- a/include/boost/gil/extension/dynamic_image/image_view_factory.hpp +++ b/include/boost/gil/extension/dynamic_image/image_view_factory.hpp @@ -15,6 +15,7 @@ #include #include +#include #include namespace boost { namespace gil { @@ -136,7 +137,7 @@ struct nth_channel_view_fn { using result_type = ResultView; - nth_channel_view_fn(int n) : _n(n) {} + nth_channel_view_fn(std::size_t n) : _n(n) {} template auto operator()(View const& src) const -> result_type @@ -144,7 +145,7 @@ struct nth_channel_view_fn return result_type(nth_channel_view(src,_n)); } - int _n; + std::size_t _n; }; template @@ -305,7 +306,7 @@ struct nth_channel_view_type> /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept template inline -auto nth_channel_view(any_image_view const& src, int n) +auto nth_channel_view(any_image_view const& src, std::size_t n) -> typename nth_channel_view_type>::type { using result_view_t = typename nth_channel_view_type>::type; diff --git a/include/boost/gil/image_view_factory.hpp b/include/boost/gil/image_view_factory.hpp index 73c2da6ecf..9bd7e491a0 100644 --- a/include/boost/gil/image_view_factory.hpp +++ b/include/boost/gil/image_view_factory.hpp @@ -338,7 +338,7 @@ namespace detail { struct __nth_channel_view_basic { using type = typename view_type::type, gray_layout_t, false, true, view_is_mutable::value>::type; - static type make(View const& src, int n) { + static type make(View const& src, std::size_t n) { using locator_t = typename type::xy_locator; using x_iterator_t = typename type::x_iterator; using x_iterator_base_t = typename iterator_adaptor_get_base::type; @@ -351,7 +351,7 @@ namespace detail { template struct __nth_channel_view_basic { using type = typename view_type::type, gray_layout_t, false, false, view_is_mutable::value>::type; - static type make(View const& src, int n) { + static type make(View const& src, std::size_t n) { using x_iterator_t = typename type::x_iterator; return interleaved_view(src.width(),src.height(),(x_iterator_t)&(src(0,0)[n]), src.pixels().row_size()); } @@ -375,7 +375,7 @@ namespace detail { public: using type = typename __nth_channel_view_basic::type; - static type make(View const& src, int n) { + static type make(View const& src, std::size_t n) { return __nth_channel_view_basic::make(src,n); } }; @@ -403,11 +403,11 @@ namespace detail { using reference = mp11::mp_if_c; using result_type = reference; - nth_channel_deref_fn(int n=0) : _n(n) {} + nth_channel_deref_fn(std::size_t n=0) : _n(n) {} template nth_channel_deref_fn(const nth_channel_deref_fn

& d) : _n(d._n) {} - int _n; // the channel to use + std::size_t _n; // the channel to use auto operator()(argument_type srcP) const -> result_type { @@ -421,7 +421,7 @@ namespace detail { using AD = typename View::template add_deref; public: using type = typename AD::type; - static type make(View const& src, int n) { + static type make(View const& src, std::size_t n) { return AD::make(src, deref_t(n)); } }; @@ -440,12 +440,12 @@ struct nth_channel_view_type { using VB = detail::__nth_channel_view::value>; public: using type = typename VB::type; - static type make(View const& src, int n) { return VB::make(src,n); } + static type make(View const& src, std::size_t n) { return VB::make(src,n); } }; /// \ingroup ImageViewTransformationsNthChannel template -typename nth_channel_view_type::type nth_channel_view(View const& src, int n) { +typename nth_channel_view_type::type nth_channel_view(View const& src, std::size_t n) { return nth_channel_view_type::make(src,n); } @@ -454,11 +454,11 @@ typename nth_channel_view_type::type nth_channel_view(View const& src, int /// \brief single-channel (grayscale) view of the K-th channel of a given image_view. The channel index is a template parameter namespace detail { - template struct __kth_channel_view_basic; + template struct __kth_channel_view_basic; // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images // or images with a step - template + template struct __kth_channel_view_basic { private: using channel_t = typename kth_element_type::type; @@ -475,7 +475,7 @@ namespace detail { }; // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images) - template + template struct __kth_channel_view_basic { private: using channel_t = typename kth_element_type::type; @@ -487,10 +487,10 @@ namespace detail { } }; - template struct __kth_channel_view; + template struct __kth_channel_view; // For basic (memory-based) views dispatch to __kth_channel_view_basic - template struct __kth_channel_view + template struct __kth_channel_view { private: using src_x_iterator = typename View::x_iterator; @@ -515,7 +515,7 @@ namespace detail { /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the k-th channel) /// \tparam SrcP reference to PixelConcept (could be pixel value or const/non-const reference) /// Examples: pixel, pixel&, const pixel&, planar_pixel_reference, planar_pixel_reference - template + template struct kth_channel_deref_fn { static constexpr bool is_mutable = @@ -544,7 +544,7 @@ namespace detail { } }; - template struct __kth_channel_view { + template struct __kth_channel_view { private: using deref_t = kth_channel_deref_fn; using AD = typename View::template add_deref; @@ -562,7 +562,7 @@ namespace detail { /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the /// return view is a single-channel non-step view. /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view. -template +template struct kth_channel_view_type { private: BOOST_GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept) @@ -573,7 +573,7 @@ struct kth_channel_view_type { }; /// \ingroup ImageViewTransformationsKthChannel -template +template auto kth_channel_view(View const& src) -> typename kth_channel_view_type::type { From b9ecb132e26fce94eb1230c5921f559dc2628126 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Tue, 31 May 2022 17:03:16 +0200 Subject: [PATCH 2/3] switch channel index type in nth_channel_view to boost::gil::index_t --- .../dynamic_image/image_view_factory.hpp | 7 ++-- include/boost/gil/image_view_factory.hpp | 35 ++++++++++--------- include/boost/gil/typedefs.hpp | 5 +++ 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/include/boost/gil/extension/dynamic_image/image_view_factory.hpp b/include/boost/gil/extension/dynamic_image/image_view_factory.hpp index d4fafc6dd7..885de7f53f 100644 --- a/include/boost/gil/extension/dynamic_image/image_view_factory.hpp +++ b/include/boost/gil/extension/dynamic_image/image_view_factory.hpp @@ -13,6 +13,7 @@ #include #include #include +#include #include #include @@ -137,7 +138,7 @@ struct nth_channel_view_fn { using result_type = ResultView; - nth_channel_view_fn(std::size_t n) : _n(n) {} + nth_channel_view_fn(index_t n) : _n(n) {} template auto operator()(View const& src) const -> result_type @@ -145,7 +146,7 @@ struct nth_channel_view_fn return result_type(nth_channel_view(src,_n)); } - std::size_t _n; + index_t _n; }; template @@ -306,7 +307,7 @@ struct nth_channel_view_type> /// \tparam Views Models Boost.MP11-compatible list of models of ImageViewConcept template inline -auto nth_channel_view(any_image_view const& src, std::size_t n) +auto nth_channel_view(any_image_view const& src, index_t n) -> typename nth_channel_view_type>::type { using result_view_t = typename nth_channel_view_type>::type; diff --git a/include/boost/gil/image_view_factory.hpp b/include/boost/gil/image_view_factory.hpp index 9bd7e491a0..57ba592607 100644 --- a/include/boost/gil/image_view_factory.hpp +++ b/include/boost/gil/image_view_factory.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -338,7 +339,7 @@ namespace detail { struct __nth_channel_view_basic { using type = typename view_type::type, gray_layout_t, false, true, view_is_mutable::value>::type; - static type make(View const& src, std::size_t n) { + static type make(View const& src, index_t n) { using locator_t = typename type::xy_locator; using x_iterator_t = typename type::x_iterator; using x_iterator_base_t = typename iterator_adaptor_get_base::type; @@ -351,7 +352,7 @@ namespace detail { template struct __nth_channel_view_basic { using type = typename view_type::type, gray_layout_t, false, false, view_is_mutable::value>::type; - static type make(View const& src, std::size_t n) { + static type make(View const& src, index_t n) { using x_iterator_t = typename type::x_iterator; return interleaved_view(src.width(),src.height(),(x_iterator_t)&(src(0,0)[n]), src.pixels().row_size()); } @@ -375,7 +376,7 @@ namespace detail { public: using type = typename __nth_channel_view_basic::type; - static type make(View const& src, std::size_t n) { + static type make(View const& src, index_t n) { return __nth_channel_view_basic::make(src,n); } }; @@ -403,11 +404,11 @@ namespace detail { using reference = mp11::mp_if_c; using result_type = reference; - nth_channel_deref_fn(std::size_t n=0) : _n(n) {} + nth_channel_deref_fn(index_t n=0) : _n(n) {} template nth_channel_deref_fn(const nth_channel_deref_fn

& d) : _n(d._n) {} - std::size_t _n; // the channel to use + index_t _n; // the channel to use auto operator()(argument_type srcP) const -> result_type { @@ -421,7 +422,7 @@ namespace detail { using AD = typename View::template add_deref; public: using type = typename AD::type; - static type make(View const& src, std::size_t n) { + static type make(View const& src, index_t n) { return AD::make(src, deref_t(n)); } }; @@ -440,12 +441,12 @@ struct nth_channel_view_type { using VB = detail::__nth_channel_view::value>; public: using type = typename VB::type; - static type make(View const& src, std::size_t n) { return VB::make(src,n); } + static type make(View const& src, index_t n) { return VB::make(src,n); } }; /// \ingroup ImageViewTransformationsNthChannel template -typename nth_channel_view_type::type nth_channel_view(View const& src, std::size_t n) { +typename nth_channel_view_type::type nth_channel_view(View const& src, index_t n) { return nth_channel_view_type::make(src,n); } @@ -454,11 +455,11 @@ typename nth_channel_view_type::type nth_channel_view(View const& src, std /// \brief single-channel (grayscale) view of the K-th channel of a given image_view. The channel index is a template parameter namespace detail { - template struct __kth_channel_view_basic; + template struct __kth_channel_view_basic; // kth_channel_view when the channels are not adjacent in memory. This can happen for multi-channel interleaved images // or images with a step - template + template struct __kth_channel_view_basic { private: using channel_t = typename kth_element_type::type; @@ -475,7 +476,7 @@ namespace detail { }; // kth_channel_view when the channels are together in memory (true for simple grayscale or planar images) - template + template struct __kth_channel_view_basic { private: using channel_t = typename kth_element_type::type; @@ -487,10 +488,10 @@ namespace detail { } }; - template struct __kth_channel_view; + template struct __kth_channel_view; // For basic (memory-based) views dispatch to __kth_channel_view_basic - template struct __kth_channel_view + template struct __kth_channel_view { private: using src_x_iterator = typename View::x_iterator; @@ -515,7 +516,7 @@ namespace detail { /// If the input is a pixel value or constant reference, the function object is immutable. Otherwise it is mutable (and returns non-const reference to the k-th channel) /// \tparam SrcP reference to PixelConcept (could be pixel value or const/non-const reference) /// Examples: pixel, pixel&, const pixel&, planar_pixel_reference, planar_pixel_reference - template + template struct kth_channel_deref_fn { static constexpr bool is_mutable = @@ -544,7 +545,7 @@ namespace detail { } }; - template struct __kth_channel_view { + template struct __kth_channel_view { private: using deref_t = kth_channel_deref_fn; using AD = typename View::template add_deref; @@ -562,7 +563,7 @@ namespace detail { /// If the channels in the source view are adjacent in memory (such as planar non-step view or single-channel view) then the /// return view is a single-channel non-step view. /// If the channels are non-adjacent (interleaved and/or step view) then the return view is a single-channel step view. -template +template struct kth_channel_view_type { private: BOOST_GIL_CLASS_REQUIRE(View, boost::gil, ImageViewConcept) @@ -573,7 +574,7 @@ struct kth_channel_view_type { }; /// \ingroup ImageViewTransformationsKthChannel -template +template auto kth_channel_view(View const& src) -> typename kth_channel_view_type::type { diff --git a/include/boost/gil/typedefs.hpp b/include/boost/gil/typedefs.hpp index 44673954ce..82470d5e80 100644 --- a/include/boost/gil/typedefs.hpp +++ b/include/boost/gil/typedefs.hpp @@ -1,6 +1,7 @@ // // Copyright 2005-2007 Adobe Systems Incorporated // Copyright 2018 Mateusz Loskot +// Copyright 2022 Dirk Stolle // // Use, modification and distribution are subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -16,6 +17,7 @@ #include #include +#include #include #include #if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE) @@ -120,6 +122,9 @@ template struct scoped_channel_value; template struct float_point_zero; template struct float_point_one; +// general-purpose index type +using index_t = std::ptrdiff_t; + ////////////////////////////////////////////////////////////////////////////////////////// /// Built-in channel models ////////////////////////////////////////////////////////////////////////////////////////// From 0f932761650d5a034f07ffc65431cb271f124c27 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Sat, 3 Sep 2022 00:49:00 +0200 Subject: [PATCH 3/3] switch uses of nth_channel_view to boost::gil::index_t --- .../adaptive_histogram_equalization.hpp | 8 ++++---- include/boost/gil/image_processing/convolve.hpp | 2 +- include/boost/gil/image_processing/filter.hpp | 2 +- .../gil/image_processing/histogram_equalization.hpp | 12 ++++++------ .../gil/image_processing/histogram_matching.hpp | 4 ++-- include/boost/gil/image_processing/morphology.hpp | 4 ++-- include/boost/gil/image_processing/threshold.hpp | 2 +- 7 files changed, 17 insertions(+), 17 deletions(-) diff --git a/include/boost/gil/image_processing/adaptive_histogram_equalization.hpp b/include/boost/gil/image_processing/adaptive_histogram_equalization.hpp index 1b5de48682..223e16c8b9 100644 --- a/include/boost/gil/image_processing/adaptive_histogram_equalization.hpp +++ b/include/boost/gil/image_processing/adaptive_histogram_equalization.hpp @@ -157,9 +157,9 @@ void non_overlapping_interpolated_clahe( using dst_channel_t = typename channel_type::type; using coord_t = typename SrcView::x_coord_t; - std::size_t const channels = num_channels::value; - coord_t const width = src_view.width(); - coord_t const height = src_view.height(); + index_t const channels = num_channels::value; + coord_t const width = src_view.width(); + coord_t const height = src_view.height(); // Find control points @@ -184,7 +184,7 @@ void non_overlapping_interpolated_clahe( copy_pixels(src_view, subimage_view(view(padded_img), top_left_x, top_left_y, width, height)); - for (std::size_t k = 0; k < channels; k++) + for (index_t k = 0; k < channels; k++) { std::vector> prev_row(new_width / tile_width_x), next_row((new_width / tile_width_x)); diff --git a/include/boost/gil/image_processing/convolve.hpp b/include/boost/gil/image_processing/convolve.hpp index 91384f1626..8f11bb6318 100644 --- a/include/boost/gil/image_processing/convolve.hpp +++ b/include/boost/gil/image_processing/convolve.hpp @@ -430,7 +430,7 @@ void convolve_2d(SrcView const& src_view, Kernel const& kernel, DstView const& d typename color_space_type::type >::value, "Source and destination views must have pixels with the same color space"); - for (std::size_t i = 0; i < src_view.num_channels(); i++) + for (index_t i = 0; i < src_view.num_channels(); i++) { detail::convolve_2d_impl( nth_channel_view(src_view, i), diff --git a/include/boost/gil/image_processing/filter.hpp b/include/boost/gil/image_processing/filter.hpp index 1fc4902323..241ea9625e 100644 --- a/include/boost/gil/image_processing/filter.hpp +++ b/include/boost/gil/image_processing/filter.hpp @@ -124,7 +124,7 @@ void median_filter(SrcView const& src_view, DstView const& dst_view, std::size_t src_view.height() ); - for (std::size_t channel = 0; channel < extended_view.num_channels(); channel++) + for (index_t channel = 0; channel < extended_view.num_channels(); channel++) { detail::filter_median_impl( nth_channel_view(extended_view, channel), diff --git a/include/boost/gil/image_processing/histogram_equalization.hpp b/include/boost/gil/image_processing/histogram_equalization.hpp index fba98f87ce..bbf5d0aecd 100644 --- a/include/boost/gil/image_processing/histogram_equalization.hpp +++ b/include/boost/gil/image_processing/histogram_equalization.hpp @@ -117,13 +117,13 @@ void histogram_equalization( using dst_channel_t = typename channel_type::type; using coord_t = typename SrcView::x_coord_t; - std::size_t const channels = num_channels::value; - coord_t const width = src_view.width(); - coord_t const height = src_view.height(); - std::size_t pixel_max = (std::numeric_limits::max)(); - std::size_t pixel_min = (std::numeric_limits::min)(); + index_t const channels = num_channels::value; + coord_t const width = src_view.width(); + coord_t const height = src_view.height(); + std::size_t pixel_max = (std::numeric_limits::max)(); + std::size_t pixel_min = (std::numeric_limits::min)(); - for (std::size_t i = 0; i < channels; i++) + for (index_t i = 0; i < channels; i++) { histogram h; fill_histogram(nth_channel_view(src_view, i), h, bin_width, false, false, mask, src_mask); diff --git a/include/boost/gil/image_processing/histogram_matching.hpp b/include/boost/gil/image_processing/histogram_matching.hpp index 1b947c426f..d254f4cd3d 100644 --- a/include/boost/gil/image_processing/histogram_matching.hpp +++ b/include/boost/gil/image_processing/histogram_matching.hpp @@ -163,7 +163,7 @@ void histogram_matching( using dst_channel_t = typename channel_type::type; using coord_t = typename SrcView::x_coord_t; - std::size_t const channels = num_channels::value; + index_t const channels = num_channels::value; coord_t const width = src_view.width(); coord_t const height = src_view.height(); source_channel_t src_pixel_min = (std::numeric_limits::min)(); @@ -171,7 +171,7 @@ void histogram_matching( ref_channel_t ref_pixel_min = (std::numeric_limits::min)(); ref_channel_t ref_pixel_max = (std::numeric_limits::max)(); - for (std::size_t i = 0; i < channels; i++) + for (index_t i = 0; i < channels; i++) { histogram src_histogram; histogram ref_histogram; diff --git a/include/boost/gil/image_processing/morphology.hpp b/include/boost/gil/image_processing/morphology.hpp index babe1acb89..d6a80f497e 100644 --- a/include/boost/gil/image_processing/morphology.hpp +++ b/include/boost/gil/image_processing/morphology.hpp @@ -112,7 +112,7 @@ void morph(SrcView const& src_view, DstView const& dst_view, Kernel const& ker_m gil::image intermediate_img(src_view.dimensions()); - for (std::size_t i = 0; i < src_view.num_channels(); i++) + for (index_t i = 0; i < src_view.num_channels(); i++) { morph_impl(nth_channel_view(src_view, i), nth_channel_view(view(intermediate_img), i), ker_mat, identifier); @@ -153,7 +153,7 @@ void difference(SrcView const& src_view1, SrcView const& src_view2, DiffView con gil_function_requires::type, typename color_space_type::type>>(); - for (std::size_t i = 0; i < src_view1.num_channels(); i++) + for (index_t i = 0; i < src_view1.num_channels(); i++) { difference_impl(nth_channel_view(src_view1, i), nth_channel_view(src_view2, i), nth_channel_view(diff_view, i)); diff --git a/include/boost/gil/image_processing/threshold.hpp b/include/boost/gil/image_processing/threshold.hpp index b3b56356fc..7b106abc09 100644 --- a/include/boost/gil/image_processing/threshold.hpp +++ b/include/boost/gil/image_processing/threshold.hpp @@ -337,7 +337,7 @@ void threshold_optimal { if (mode == threshold_optimal_value::otsu) { - for (std::size_t i = 0; i < src_view.num_channels(); i++) + for (index_t i = 0; i < src_view.num_channels(); i++) { detail::otsu_impl (nth_channel_view(src_view, i), nth_channel_view(dst_view, i), direction);