From 94f9e339260e060afe06daea4eb8586c9dd02a4c Mon Sep 17 00:00:00 2001 From: theroyn Date: Sat, 30 Jan 2021 22:11:51 +0200 Subject: [PATCH] Support constructing a planar image from interleaved image (#552) Fixes #478 --- include/boost/gil/algorithm.hpp | 61 +++++++++++++++++++++++++++++---- test/core/image/image.cpp | 27 ++++++++++----- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/include/boost/gil/algorithm.hpp b/include/boost/gil/algorithm.hpp index b67d54a35c..cbd1716868 100644 --- a/include/boost/gil/algorithm.hpp +++ b/include/boost/gil/algorithm.hpp @@ -734,10 +734,33 @@ void default_construct_pixels(View const& view) namespace detail { +enum class copy_planarity_condition +{ + planar_to_planar, + interleaved_to_planar, + mixed_to_interleaved +}; + +using planar_to_planar_type = + std::integral_constant + < + copy_planarity_condition, copy_planarity_condition::planar_to_planar + >; +using interleaved_to_planar_type = + std::integral_constant + < + copy_planarity_condition, copy_planarity_condition::interleaved_to_planar + >; +using mixed_to_interleaved_type = + std::integral_constant + < + copy_planarity_condition, copy_planarity_condition::mixed_to_interleaved + >; + /// std::uninitialized_copy for pairs of planar iterators template BOOST_FORCEINLINE -void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::true_type) +void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, planar_to_planar_type) { std::size_t channel=0; try { @@ -761,13 +784,25 @@ void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::true_type) } } -/// std::uninitialized_copy for interleaved or mixed iterators +/// std::uninitialized_copy for interleaved or mixed(planar into interleaved) iterators template BOOST_FORCEINLINE -void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::false_type) +void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, mixed_to_interleaved_type) { std::uninitialized_copy(first1, last1, first2); } + +/// std::uninitialized_copy for interleaved to planar iterators +template +BOOST_FORCEINLINE +void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, It2 last2, +interleaved_to_planar_type) +{ + default_construct_aux(first2, last2, std::true_type()); + + typename It2::difference_type n = last2 - first2; + copier_n()(first1, n, first2); +} } // namespace detail /// \ingroup ImageViewSTLAlgorithmsUninitializedCopyPixels @@ -777,13 +812,24 @@ void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::false_type) template void uninitialized_copy_pixels(View1 const& view1, View2 const& view2) { - using is_planar = std::integral_constant::value && is_planar::value>; + using copy_planarity_condition = detail::copy_planarity_condition; + using copy_planarity_condition_type = + std::integral_constant + < + copy_planarity_condition, + !is_planar::value + ? copy_planarity_condition::mixed_to_interleaved + : (is_planar::value + ? copy_planarity_condition::planar_to_planar + : copy_planarity_condition::interleaved_to_planar) + >; BOOST_ASSERT(view1.dimensions() == view2.dimensions()); if (view1.is_1d_traversable() && view2.is_1d_traversable()) { detail::uninitialized_copy_aux( - view1.begin().x(), view1.end().x(), view2.begin().x(), is_planar()); + view1.begin().x(), view1.end().x(), view2.begin().x(), view2.end().x(), + copy_planarity_condition_type()); } else { @@ -792,12 +838,13 @@ void uninitialized_copy_pixels(View1 const& view1, View2 const& view2) { for (y = 0; y < view1.height(); ++y) detail::uninitialized_copy_aux( - view1.row_begin(y), view1.row_end(y), view2.row_begin(y), is_planar()); + view1.row_begin(y), view1.row_end(y), view2.row_begin(y), view2.row_end(y), + copy_planarity_condition_type()); } catch(...) { for (typename View1::y_coord_t y0 = 0; y0 < y; ++y0) - detail::destruct_aux(view2.row_begin(y0), view2.row_end(y0), is_planar()); + detail::destruct_aux(view2.row_begin(y0), view2.row_end(y0), is_planar()); throw; } } diff --git a/test/core/image/image.cpp b/test/core/image/image.cpp index 52d7bd7034..df61a3df92 100644 --- a/test/core/image/image.cpp +++ b/test/core/image/image.cpp @@ -56,15 +56,15 @@ struct test_constructor_from_other_image auto v2 = gil::const_view(image2); BOOST_TEST_ALL_EQ(v1.begin(), v1.end(), v2.begin(), v2.end()); } - // { - // //constructor planar from interleaved - // image_t image1(dimensions, rnd_pixel); - // gil::image image2(image1); - // BOOST_TEST_EQ(image2.dimensions(), dimensions); - // auto v1 = gil::const_view(image1); - // auto v2 = gil::const_view(image2); - // BOOST_TEST_ALL_EQ(v1.begin(), v1.end(), v2.begin(), v2.end()); - // } + { + // constructor planar from interleaved + image_t image1(dimensions, rnd_pixel); + gil::image image2(image1); + BOOST_TEST_EQ(image2.dimensions(), dimensions); + auto v1 = gil::const_view(image1); + auto v2 = gil::const_view(image2); + BOOST_TEST_ALL_EQ(v1.begin(), v1.end(), v2.begin(), v2.end()); + } } static void run() { @@ -90,6 +90,15 @@ struct test_constructor_from_view auto v2 = gil::const_view(image2); BOOST_TEST_ALL_EQ(v1.begin(), v1.end(), v2.begin(), v2.end()); } + { + //constructor planar from interleaved + image_t image1(dimensions, rnd_pixel); + auto v1 = gil::transposed_view(gil::const_view(image1)); + gil::image image2(gil::transposed_view(v1)); + BOOST_TEST_EQ(image2.dimensions(), dimensions); + auto v2 = gil::const_view(image2); + BOOST_TEST_ALL_EQ(v1.begin(), v1.end(), v2.begin(), v2.end()); + } } static void run() {