Skip to content

Commit

Permalink
Support constructing a planar image from interleaved image (#552)
Browse files Browse the repository at this point in the history
Fixes #478
  • Loading branch information
theroyn authored Jan 30, 2021
1 parent 422ca82 commit 2e27642
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 16 deletions.
61 changes: 54 additions & 7 deletions include/boost/gil/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 <typename It1, typename It2>
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 {
Expand All @@ -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 <typename It1, typename It2>
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 <typename It1, typename It2>
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<It1,It2>()(first1, n, first2);
}
} // namespace detail

/// \ingroup ImageViewSTLAlgorithmsUninitializedCopyPixels
Expand All @@ -777,13 +812,24 @@ void uninitialized_copy_aux(It1 first1, It1 last1, It2 first2, std::false_type)
template <typename View1, typename View2>
void uninitialized_copy_pixels(View1 const& view1, View2 const& view2)
{
using is_planar = std::integral_constant<bool, is_planar<View1>::value && is_planar<View2>::value>;
using copy_planarity_condition = detail::copy_planarity_condition;
using copy_planarity_condition_type =
std::integral_constant
<
copy_planarity_condition,
!is_planar<View2>::value
? copy_planarity_condition::mixed_to_interleaved
: (is_planar<View1>::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
{
Expand All @@ -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<View2>());
throw;
}
}
Expand Down
27 changes: 18 additions & 9 deletions test/core/image/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<pixel_t, true> 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<pixel_t, true> 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()
{
Expand All @@ -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<pixel_t, true> 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()
{
Expand Down

0 comments on commit 2e27642

Please sign in to comment.