Skip to content

Commit

Permalink
Merge branch 'develop' into ml/add-image-class-test
Browse files Browse the repository at this point in the history
  • Loading branch information
mloskot authored Jun 28, 2022
2 parents 57c1f4d + 4dbf35a commit 9a4d72c
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 61 deletions.
7 changes: 7 additions & 0 deletions include/boost/gil/image.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,14 @@ class image
swap(_align_in_bytes, img._align_in_bytes);
swap(_memory, img._memory);
swap(_view, img._view);
#ifdef BOOST_NO_CXX17_HDR_MEMORY_RESOURCE
swap(_alloc, img._alloc);
#else
if constexpr (std::allocator_traits<Alloc>::propagate_on_container_swap::value)
swap(_alloc, img._alloc);
else
BOOST_ASSERT(_alloc == img._alloc);
#endif
swap(_allocated_bytes, img._allocated_bytes );
}

Expand Down
147 changes: 88 additions & 59 deletions include/boost/gil/typedefs.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,71 +18,100 @@

#include <cstdint>
#include <memory>
#if !defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
# include <memory_resource>
#endif //!defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)

// B - bits size/signedness, CM - channel model, CS - colour space, LAYOUT - pixel layout
// Example: B = '8', CM = 'uint8_t', CS = 'bgr, LAYOUT='bgr_layout_t'
#define BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, LAYOUT) \
template <typename, typename> struct pixel; \
template <typename, typename> struct planar_pixel_reference; \
template <typename, typename> struct planar_pixel_iterator; \
template <typename> class memory_based_step_iterator; \
template <typename> class point; \
template <typename> class memory_based_2d_locator; \
template <typename> class image_view; \
template <typename, bool, typename> class image; \
using CS##B##_pixel_t = pixel<CM, LAYOUT>; \
using CS##B##c_pixel_t = pixel<CM, LAYOUT> const; \
using CS##B##_ref_t = pixel<CM, LAYOUT>&; \
using CS##B##c_ref_t = pixel<CM, LAYOUT> const&; \
using CS##B##_ptr_t = CS##B##_pixel_t*; \
using CS##B##c_ptr_t = CS##B##c_pixel_t*; \
using CS##B##_step_ptr_t = memory_based_step_iterator<CS##B##_ptr_t>; \
using CS##B##c_step_ptr_t = memory_based_step_iterator<CS##B##c_ptr_t>; \
using CS##B##_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##_ptr_t>>; \
using CS##B##c_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##c_ptr_t>>; \
using CS##B##_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##_step_ptr_t>>; \
using CS##B##c_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##c_step_ptr_t>>; \
using CS##B##_view_t = image_view<CS##B##_loc_t>; \
using CS##B##c_view_t = image_view<CS##B##c_loc_t>; \
using CS##B##_step_view_t = image_view<CS##B##_step_loc_t>; \
using CS##B##c_step_view_t = image_view<CS##B##c_step_loc_t>; \
#define BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, LAYOUT) \
template <typename, typename> \
struct pixel; \
template <typename, typename> \
struct planar_pixel_reference; \
template <typename, typename> \
struct planar_pixel_iterator; \
template <typename> \
class memory_based_step_iterator; \
template <typename> \
class point; \
template <typename> \
class memory_based_2d_locator; \
template <typename> \
class image_view; \
template <typename, bool, typename> \
class image; \
using CS##B##_pixel_t = pixel<CM, LAYOUT>; \
using CS##B##c_pixel_t = pixel<CM, LAYOUT> const; \
using CS##B##_ref_t = pixel<CM, LAYOUT>&; \
using CS##B##c_ref_t = pixel<CM, LAYOUT> const&; \
using CS##B##_ptr_t = CS##B##_pixel_t*; \
using CS##B##c_ptr_t = CS##B##c_pixel_t*; \
using CS##B##_step_ptr_t = memory_based_step_iterator<CS##B##_ptr_t>; \
using CS##B##c_step_ptr_t = memory_based_step_iterator<CS##B##c_ptr_t>; \
using CS##B##_loc_t = memory_based_2d_locator<memory_based_step_iterator<CS##B##_ptr_t>>; \
using CS##B##c_loc_t = memory_based_2d_locator<memory_based_step_iterator<CS##B##c_ptr_t>>; \
using CS##B##_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##_step_ptr_t>>; \
using CS##B##c_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##c_step_ptr_t>>; \
using CS##B##_view_t = image_view<CS##B##_loc_t>; \
using CS##B##c_view_t = image_view<CS##B##c_loc_t>; \
using CS##B##_step_view_t = image_view<CS##B##_step_loc_t>; \
using CS##B##c_step_view_t = image_view<CS##B##c_step_loc_t>; \
using CS##B##_image_t = image<CS##B##_pixel_t, false, std::allocator<unsigned char>>;

// Example: B = '8', CM = 'uint8_t', CS = 'bgr' CS_FULL = 'rgb_t' LAYOUT='bgr_layout_t'
#define BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(B, CM, CS, CS_FULL, LAYOUT) \
BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, LAYOUT) \
using CS##B##_planar_ref_t = planar_pixel_reference<CM&, CS_FULL>; \
using CS##B##c_planar_ref_t = planar_pixel_reference<CM const&, CS_FULL>; \
using CS##B##_planar_ptr_t = planar_pixel_iterator<CM*, CS_FULL>; \
using CS##B##c_planar_ptr_t = planar_pixel_iterator<CM const*, CS_FULL>; \
using CS##B##_planar_step_ptr_t = memory_based_step_iterator<CS##B##_planar_ptr_t>; \
using CS##B##c_planar_step_ptr_t \
= memory_based_step_iterator<CS##B##c_planar_ptr_t>; \
using CS##B##_planar_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##_planar_ptr_t>>; \
using CS##B##c_planar_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##c_planar_ptr_t>>; \
using CS##B##_planar_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##_planar_step_ptr_t>>; \
using CS##B##c_planar_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##c_planar_step_ptr_t>>; \
using CS##B##_planar_view_t = image_view<CS##B##_planar_loc_t>; \
using CS##B##c_planar_view_t = image_view<CS##B##c_planar_loc_t>; \
using CS##B##_planar_step_view_t = image_view<CS##B##_planar_step_loc_t>; \
using CS##B##c_planar_step_view_t = image_view<CS##B##c_planar_step_loc_t>; \
using CS##B##_planar_image_t \
= image<CS##B##_pixel_t, true, std::allocator<unsigned char>>;

#define BOOST_GIL_DEFINE_BASE_TYPEDEFS(B, CM, CS) \
BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, CS##_layout_t)

#define BOOST_GIL_DEFINE_ALL_TYPEDEFS(B, CM, CS) \
BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(B, CM, CS, CS##_t, CS##_layout_t)
#define BOOST_GIL_DEFINE_BASE_PMR_TYPEDEFS_INTERNAL(B, CM, CS, LAYOUT) \
namespace pmr { \
using CS##B##_image_t \
= image<CS##B##_pixel_t, false, std::pmr::polymorphic_allocator<unsigned char>>; \
}

// Example: B = '8', CM = 'uint8_t', CS = 'bgr' CS_FULL = 'rgb_t' LAYOUT='bgr_layout_t'
#define BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(B, CM, CS, CS_FULL, LAYOUT) \
BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, LAYOUT) \
using CS##B##_planar_ref_t = planar_pixel_reference<CM&, CS_FULL>; \
using CS##B##c_planar_ref_t = planar_pixel_reference<CM const&, CS_FULL>; \
using CS##B##_planar_ptr_t = planar_pixel_iterator<CM*, CS_FULL>; \
using CS##B##c_planar_ptr_t = planar_pixel_iterator<CM const*, CS_FULL>; \
using CS##B##_planar_step_ptr_t = memory_based_step_iterator<CS##B##_planar_ptr_t>; \
using CS##B##c_planar_step_ptr_t = memory_based_step_iterator<CS##B##c_planar_ptr_t>; \
using CS##B##_planar_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##_planar_ptr_t>>; \
using CS##B##c_planar_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##c_planar_ptr_t>>; \
using CS##B##_planar_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##_planar_step_ptr_t>>; \
using CS##B##c_planar_step_loc_t \
= memory_based_2d_locator<memory_based_step_iterator<CS##B##c_planar_step_ptr_t>>; \
using CS##B##_planar_view_t = image_view<CS##B##_planar_loc_t>; \
using CS##B##c_planar_view_t = image_view<CS##B##c_planar_loc_t>; \
using CS##B##_planar_step_view_t = image_view<CS##B##_planar_step_loc_t>; \
using CS##B##c_planar_step_view_t = image_view<CS##B##c_planar_step_loc_t>; \
using CS##B##_planar_image_t = image<CS##B##_pixel_t, true, std::allocator<unsigned char>>;

#define BOOST_GIL_DEFINE_ALL_PMR_TYPEDEFS_INTERNAL(B, CM, CS, CS_FULL, LAYOUT) \
BOOST_GIL_DEFINE_BASE_PMR_TYPEDEFS_INTERNAL(B, CM, CS, LAYOUT) \
namespace pmr { \
using CS##B##_planar_image_t \
= image<CS##B##_pixel_t, true, std::pmr::polymorphic_allocator<unsigned char>>; \
}

#if defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
# define BOOST_GIL_DEFINE_BASE_TYPEDEFS(B, CM, CS) \
BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, CS##_layout_t)

# define BOOST_GIL_DEFINE_ALL_TYPEDEFS(B, CM, CS) \
BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(B, CM, CS, CS##_t, CS##_layout_t)
#else
# define BOOST_GIL_DEFINE_BASE_TYPEDEFS(B, CM, CS) \
BOOST_GIL_DEFINE_BASE_TYPEDEFS_INTERNAL(B, CM, CS, CS##_layout_t) \
BOOST_GIL_DEFINE_BASE_PMR_TYPEDEFS_INTERNAL(B, CM, CS, CS##_layout_t)

# define BOOST_GIL_DEFINE_ALL_TYPEDEFS(B, CM, CS) \
BOOST_GIL_DEFINE_ALL_TYPEDEFS_INTERNAL(B, CM, CS, CS##_t, CS##_layout_t) \
BOOST_GIL_DEFINE_ALL_PMR_TYPEDEFS_INTERNAL(B, CM, CS, CS##_t, CS##_layout_t)
#endif //!defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)

namespace boost { namespace gil {

Expand Down
1 change: 1 addition & 0 deletions test/core/image/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
foreach(_name
concepts
alignment
empty_dimensions
image)
set(_test t_core_image_${_name})
set(_target test_core_image_${_name})
Expand Down
3 changes: 2 additions & 1 deletion test/core/image/Jamfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ import testing ;

compile concepts.cpp ;

run image.cpp ;
run alignment.cpp ;
run empty_dimensions.cpp ;
run image.cpp ;
91 changes: 91 additions & 0 deletions test/core/image/empty_dimensions.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
//
// Copyright 2019-2020 Mateusz Loskot <mateusz at loskot dot net>
//
// Distributed under the Boost Software License, Version 1.0
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//
#include <boost/gil.hpp>

#include <boost/core/lightweight_test.hpp>

#include "test_fixture.hpp"
#include "test_utility_output_stream.hpp"
#include "core/pixel/test_fixture.hpp"

namespace gil = boost::gil;
namespace fixture = boost::gil::test::fixture;

// Test cases of memory leak potential for image created with empty dimesions,
// see https://github.com/boostorg/gil/pull/649
// The main goal of these test cases is to trigger any memory leak detectors.

void test_default_constructor()
{
boost::gil::rgb8_image_t image;
BOOST_TEST_EQ(image.width(), 0);
BOOST_TEST_EQ(image.height(), 0);
}

void test_copy_constructor_with_empty_image()
{
boost::gil::rgb8_image_t image1;
boost::gil::rgb8_image_t image2(image1);
BOOST_TEST_EQ(image2.width(), 0);
BOOST_TEST_EQ(image2.height(), 0);
}

struct test_constructor_with_empty_dimensions
{
template <typename Image>
void operator()(Image const &)
{
using image_t = Image;
image_t image(0, 0);
BOOST_TEST_EQ(image.width(), 0);
BOOST_TEST_EQ(image.height(), 0);
}

static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(test_constructor_with_empty_dimensions{});
}
};

struct test_constructor_with_empty_dimensions_with_pixel
{
template <typename Image>
void operator()(Image const &)
{
using image_t = Image;
gil::point_t const dimensions{0, 0};
using pixel_t = typename image_t::view_t::value_type;
pixel_t const rnd_pixel = fixture::pixel_generator<pixel_t>::random();
image_t image(dimensions, rnd_pixel);
BOOST_TEST_EQ(image.width(), dimensions.x);
BOOST_TEST_EQ(image.height(), dimensions.y);

bool none_visited = true;
for (pixel_t const &p : gil::view(image))
{
none_visited = false;
BOOST_TEST_EQ(p, rnd_pixel);
}
BOOST_TEST(none_visited);
}

static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(test_constructor_with_empty_dimensions_with_pixel{});
}
};

int main()
{
test_default_constructor();
test_copy_constructor_with_empty_image();
test_constructor_with_empty_dimensions::run();
test_constructor_with_empty_dimensions_with_pixel::run();

return ::boost::report_errors();
}
29 changes: 28 additions & 1 deletion test/core/image/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ struct test_constructor_with_dimensions_pixel
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(test_constructor_with_dimensions_pixel{});
boost::mp11::mp_for_each<fixture::pmr_image_types>(test_constructor_with_dimensions_pixel{});
}
};

Expand All @@ -44,12 +45,13 @@ struct test_constructor_from_other_image
void operator()(Image const &)
{
using image_t = Image;
using allocator_t = typename Image::allocator_type;
gil::point_t const dimensions{256, 128};
using pixel_t = typename image_t::view_t::value_type;
pixel_t const rnd_pixel = fixture::pixel_generator<pixel_t>::random();
{
//constructor interleaved from planar
gil::image<pixel_t, true> image1(dimensions, rnd_pixel);
gil::image<pixel_t, true, allocator_t> image1(dimensions, rnd_pixel);
image_t image2(image1);
BOOST_TEST_EQ(image2.dimensions(), dimensions);
auto v1 = gil::const_view(image1);
Expand Down Expand Up @@ -106,6 +108,27 @@ struct test_constructor_from_view
}
};

struct test_copy_assignement
{
template <typename Image>
void operator()(Image const&)
{
using image_t = Image;
gil::point_t const dimensions{ 256, 128 };
{
image_t image = fixture::create_image<image_t>(dimensions.x, dimensions.y, 0);
image_t image2;
image2 = image;
BOOST_TEST_EQ(image2.dimensions(), dimensions);
}
}
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(test_copy_assignement{});
boost::mp11::mp_for_each<fixture::pmr_image_types>(test_copy_assignement{});
}
};

struct test_move_constructor
{
template <typename Image>
Expand All @@ -124,6 +147,7 @@ struct test_move_constructor
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(test_move_constructor{});
boost::mp11::mp_for_each<fixture::pmr_image_types>(test_move_constructor{});
}
};

Expand All @@ -146,6 +170,7 @@ struct test_move_assignement
static void run()
{
boost::mp11::mp_for_each<fixture::image_types>(test_move_assignement{});
boost::mp11::mp_for_each<fixture::pmr_image_types>(test_move_assignement{});
}
};

Expand All @@ -155,6 +180,8 @@ int main()
test_constructor_from_other_image::run();
test_constructor_from_view::run();

test_copy_assignement::run();

test_move_constructor::run();
test_move_assignement::run();

Expand Down
20 changes: 20 additions & 0 deletions test/core/image/test_fixture.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,26 @@ using image_types = std::tuple
gil::rgba32_image_t
>;

#if defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)
using pmr_image_types = std::tuple<>;
#else
using pmr_image_types = std::tuple
<
gil::pmr::gray8_image_t,
gil::pmr::gray16_image_t,
gil::pmr::gray32_image_t,
gil::pmr::bgr8_image_t,
gil::pmr::bgr16_image_t,
gil::pmr::bgr32_image_t,
gil::pmr::rgb8_image_t,
gil::pmr::rgb16_image_t,
gil::pmr::rgb32_image_t,
gil::pmr::rgba8_image_t,
gil::pmr::rgba16_image_t,
gil::pmr::rgba32_image_t
>;
#endif //defined(BOOST_NO_CXX17_HDR_MEMORY_RESOURCE)

using rgb_interleaved_image_types = std::tuple
<
gil::bgr8_image_t,
Expand Down

0 comments on commit 9a4d72c

Please sign in to comment.