5611bd5807
Use type traits and features of C++11, then use Boost.MP11. Remove unused and unnecessary metafunctions in `detail` namespace. Remove explicit access to ::type as no longer necessary with MP11. Clean up and reformat code according to the current guidelines. Legacy tests have been updated where necessary to accommodate switch to MP11. Replace std::is_integral with gil::detail::is_channel_integral Replacing boost::is_integral with std::is_integral is C++ UB: C++11 / 20.11.2 Header <type_traits> synopsis 1 The behavior of a program that adds specializations for any of the class templates defined in this subclause is undefined unless otherwise specified. Implements also proposal in #93 Closes #229
356 lines
12 KiB
C++
356 lines
12 KiB
C++
//
|
|
// Copyright 2005-2007 Adobe Systems Incorporated
|
|
//
|
|
// 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
|
|
//
|
|
#ifdef _MSC_VER
|
|
#pragma warning(disable : 4244) // 'argument': conversion from 'int' to 'unsigned char', possible loss of data
|
|
#endif
|
|
|
|
#include <boost/gil.hpp>
|
|
|
|
#include <boost/assert.hpp>
|
|
#include <boost/mp11.hpp>
|
|
|
|
#include <exception>
|
|
#include <iostream>
|
|
#include <type_traits>
|
|
#include <vector>
|
|
|
|
using namespace boost::gil;
|
|
using namespace std;
|
|
|
|
void test_pixel_iterator()
|
|
{
|
|
boost::function_requires<Point2DConcept<point<int>>>();
|
|
|
|
boost::function_requires<MutablePixelIteratorConcept<bgr8_ptr_t> >();
|
|
boost::function_requires<MutablePixelIteratorConcept<cmyk8_planar_ptr_t> >();
|
|
boost::function_requires<PixelIteratorConcept<rgb8c_planar_step_ptr_t> >();
|
|
boost::function_requires<MutableStepIteratorConcept<rgb8_step_ptr_t> >();
|
|
|
|
boost::function_requires<MutablePixelLocatorConcept<rgb8_step_loc_t> >();
|
|
boost::function_requires<PixelLocatorConcept<rgb8c_planar_step_loc_t> >();
|
|
|
|
boost::function_requires<MutableStepIteratorConcept<cmyk8_planar_step_ptr_t> >();
|
|
boost::function_requires<StepIteratorConcept<gray8c_step_ptr_t> >();
|
|
|
|
boost::function_requires<MutablePixelLocatorConcept<memory_based_2d_locator<rgb8_step_ptr_t> > >();
|
|
|
|
using bgr121_ref_t = bit_aligned_pixel_reference
|
|
<
|
|
std::uint8_t,
|
|
boost::mp11::mp_list_c<int,1,2,1>,
|
|
bgr_layout_t,
|
|
true
|
|
> const;
|
|
using bgr121_ptr_t = bit_aligned_pixel_iterator<bgr121_ref_t>;
|
|
|
|
boost::function_requires<MutablePixelIteratorConcept<bgr121_ptr_t> >();
|
|
boost::function_requires<PixelBasedConcept<bgr121_ptr_t> >();
|
|
boost::function_requires<MemoryBasedIteratorConcept<bgr121_ptr_t> >();
|
|
boost::function_requires<HasDynamicXStepTypeConcept<bgr121_ptr_t> >();
|
|
|
|
// TEST dynamic_step_t
|
|
static_assert(std::is_same<cmyk16_step_ptr_t, dynamic_x_step_type<cmyk16_step_ptr_t>::type>::value, "");
|
|
static_assert(std::is_same<cmyk16_planar_step_ptr_t, dynamic_x_step_type<cmyk16_planar_ptr_t>::type>::value, "");
|
|
|
|
static_assert(std::is_same<iterator_type<uint8_t,gray_layout_t,false,false,false>::type,gray8c_ptr_t>::value, "");
|
|
|
|
// TEST iterator_is_step
|
|
static_assert(iterator_is_step<cmyk16_step_ptr_t>::value, "");
|
|
static_assert(iterator_is_step<cmyk16_planar_step_ptr_t>::value, "");
|
|
static_assert(!iterator_is_step<cmyk16_planar_ptr_t>::value, "");
|
|
|
|
using ccv_rgb_g_fn = color_convert_deref_fn<rgb8c_ref_t, gray8_pixel_t>;
|
|
using ccv_g_rgb_fn = color_convert_deref_fn<gray8c_ref_t, rgb8_pixel_t>;
|
|
gil_function_requires<PixelDereferenceAdaptorConcept<ccv_rgb_g_fn> >();
|
|
gil_function_requires<PixelDereferenceAdaptorConcept<deref_compose<ccv_rgb_g_fn,ccv_g_rgb_fn> > >();
|
|
|
|
using rgb2gray_ptr = dereference_iterator_adaptor<rgb8_ptr_t, ccv_rgb_g_fn>;
|
|
static_assert(!iterator_is_step<rgb2gray_ptr>::value, "");
|
|
|
|
using rgb2gray_step_ptr = dynamic_x_step_type<rgb2gray_ptr>::type;
|
|
static_assert(std::is_same<rgb2gray_step_ptr, dereference_iterator_adaptor<rgb8_step_ptr_t, ccv_rgb_g_fn>>::value, "");
|
|
|
|
make_step_iterator(rgb2gray_ptr(),2);
|
|
|
|
using rgb2gray_step_ptr1 = dereference_iterator_adaptor<rgb8_step_ptr_t, ccv_rgb_g_fn>;
|
|
static_assert(iterator_is_step<rgb2gray_step_ptr1>::value, "");
|
|
static_assert(std::is_same<rgb2gray_step_ptr1, dynamic_x_step_type<rgb2gray_step_ptr1>::type>::value, "");
|
|
|
|
using rgb2gray_step_ptr2 = memory_based_step_iterator<dereference_iterator_adaptor<rgb8_ptr_t, ccv_rgb_g_fn>>;
|
|
static_assert(iterator_is_step<rgb2gray_step_ptr2 >::value, "");
|
|
static_assert(std::is_same<rgb2gray_step_ptr2, dynamic_x_step_type<rgb2gray_step_ptr2>::type>::value, "");
|
|
make_step_iterator(rgb2gray_step_ptr2(),2);
|
|
|
|
// bit_aligned iterators test
|
|
|
|
// Mutable reference to a BGR232 pixel
|
|
using bgr232_ref_t = bit_aligned_pixel_reference
|
|
<
|
|
std::uint8_t,
|
|
boost::mp11::mp_list_c<unsigned, 2, 3, 2>,
|
|
bgr_layout_t,
|
|
true
|
|
> const;
|
|
|
|
// A mutable iterator over BGR232 pixels
|
|
using bgr232_ptr_t = bit_aligned_pixel_iterator<bgr232_ref_t>;
|
|
|
|
// BGR232 pixel value. It is a packed_pixel of size 1 byte. (The last bit is unused)
|
|
using bgr232_pixel_t = std::iterator_traits<bgr232_ptr_t>::value_type;
|
|
static_assert(sizeof(bgr232_pixel_t) == 1, "");
|
|
|
|
bgr232_pixel_t red(0,0,3); // = 0RRGGGBB, = 01100000
|
|
|
|
// a buffer of 7 bytes fits exactly 8 BGR232 pixels.
|
|
unsigned char pix_buffer[7];
|
|
std::fill(pix_buffer,pix_buffer+7,0);
|
|
bgr232_ptr_t pix_it(&pix_buffer[0],0); // start at bit 0 of the first pixel
|
|
for (int i=0; i<8; ++i) {
|
|
*pix_it++ = red;
|
|
}
|
|
|
|
// test cross byte pixel values - meaning when a pixel value is stretched over two bytes
|
|
using gray3_image_t = bit_aligned_image1_type<3, gray_layout_t>::type;
|
|
using image_t = gray3_image_t;
|
|
|
|
using view_t = image_t::view_t;
|
|
using ref_t = view_t::reference;
|
|
|
|
using iterator_t = bit_aligned_pixel_iterator<ref_t>;
|
|
|
|
std::vector< unsigned char > buf( 4 );
|
|
// bit pattern is: 1011 0110 0110 1101 1101 1011
|
|
// each byte is read right to left
|
|
buf[0] = 182;
|
|
buf[1] = 109;
|
|
buf[2] = 219;
|
|
|
|
iterator_t it( &buf[0], 0 );
|
|
|
|
ref_t p1 = *it; it++;
|
|
ref_t p2 = *it; it++;
|
|
ref_t p3 = *it; it++;
|
|
ref_t p4 = *it; it++;
|
|
ref_t p5 = *it; it++;
|
|
ref_t p6 = *it; it++;
|
|
ref_t p7 = *it; it++;
|
|
ref_t p8 = *it; it++;
|
|
|
|
unsigned char v1 = get_color( p1, gray_color_t() );
|
|
unsigned char v2 = get_color( p2, gray_color_t() );
|
|
unsigned char v3 = get_color( p3, gray_color_t() );
|
|
unsigned char v4 = get_color( p4, gray_color_t() );
|
|
unsigned char v5 = get_color( p5, gray_color_t() );
|
|
unsigned char v6 = get_color( p6, gray_color_t() );
|
|
unsigned char v7 = get_color( p7, gray_color_t() );
|
|
unsigned char v8 = get_color( p8, gray_color_t() );
|
|
|
|
// all values should be 110b ( 6 );
|
|
BOOST_ASSERT(v1 == 6);
|
|
BOOST_ASSERT(v2 == 6);
|
|
BOOST_ASSERT(v3 == 6);
|
|
BOOST_ASSERT(v4 == 6);
|
|
BOOST_ASSERT(v5 == 6);
|
|
BOOST_ASSERT(v6 == 6);
|
|
BOOST_ASSERT(v7 == 6);
|
|
BOOST_ASSERT(v8 == 6);
|
|
}
|
|
|
|
// TODO: Make better tests. Use some code from below.
|
|
|
|
/*
|
|
template <typename Pixel>
|
|
void invert_pixel1(Pixel& pix) {
|
|
at_c<0>(pix)=0;
|
|
}
|
|
|
|
template <typename T> inline void ignore_unused_variable_warning(const T&){}
|
|
|
|
void test_pixel_iterator() {
|
|
rgb8_pixel_t rgb8(1,2,3);
|
|
rgba8_pixel_t rgba8;
|
|
|
|
rgb8_ptr_t ptr1=&rgb8;
|
|
memunit_advance(ptr1, 3);
|
|
const rgb8_ptr_t ptr2=memunit_advanced(ptr1,10);
|
|
|
|
memunit_distance(ptr1,ptr2);
|
|
const rgb8_pixel_t& ref=memunit_advanced_ref(ptr1,10); ignore_unused_variable_warning(ref);
|
|
|
|
rgb8_planar_ptr_t planarPtr1(&rgb8);
|
|
rgb8_planar_ptr_t planarPtr2(&rgb8);
|
|
memunit_advance(planarPtr1,10);
|
|
memunit_distance(planarPtr1,planarPtr2);
|
|
rgb8_planar_ptr_t planarPtr3=memunit_advanced(planarPtr1,10);
|
|
|
|
// planarPtr2=&rgba8;
|
|
|
|
planar_pixel_reference<uint8_t&,rgb_t> pxl=*(planarPtr1+5);
|
|
rgb8_pixel_t pv2=pxl;
|
|
rgb8_pixel_t pv3=*(planarPtr1+5);
|
|
rgb8_pixel_t pv=planarPtr1[5];
|
|
|
|
assert(*(planarPtr1+5)==planarPtr1[5]);
|
|
|
|
rgb8_planar_ref_t planarRef=memunit_advanced_ref(planarPtr1,10);
|
|
|
|
rgb8_step_ptr_t stepIt(&rgb8,5);
|
|
stepIt++;
|
|
rgb8_step_ptr_t stepIt2=stepIt+10;
|
|
stepIt2=stepIt;
|
|
|
|
rgb8_step_ptr_t stepIt3(&rgb8,5);
|
|
|
|
rgb8_pixel_t& ref1=stepIt3[5];
|
|
// bool v=std::is_pod<iterator_traits<memory_based_step_iterator<rgb8_ptr_t> >::value_type>::value;
|
|
// v=std::is_pod<rgb8_pixel_t>::value;
|
|
// v=std::is_pod<int>::value;
|
|
|
|
rgb8_step_ptr_t rgb8StepIt(ptr1, 10);
|
|
rgb8_step_ptr_t rgb8StepIt2=rgb8StepIt;
|
|
rgb8StepIt=rgb8StepIt2;
|
|
++rgb8StepIt;
|
|
rgb8_ref_t reff=*rgb8StepIt; ignore_unused_variable_warning(reff);
|
|
rgb8StepIt+=10;
|
|
std::ptrdiff_t dst=rgb8StepIt2-rgb8StepIt; ignore_unused_variable_warning(dst);
|
|
|
|
rgb8_pixel_t val1=ref1;
|
|
rgb8_ptr_t ptr=&ref1;
|
|
|
|
invert_pixel1(*planarPtr1);
|
|
// invert_pixel1(*ptr);
|
|
rgb8c_planar_ptr_t r8cpp;
|
|
// invert_pixel1(*r8cpp);
|
|
|
|
rgb8_pixel_t& val21=stepIt3[5];
|
|
rgb8_pixel_t val22=val21;
|
|
|
|
rgb8_pixel_t val2=stepIt3[5];
|
|
rgb8_ptr_t ptr11=&(stepIt3[5]); ignore_unused_variable_warning(ptr11);
|
|
rgb8_ptr_t ptr3=&*(stepIt3+5); ignore_unused_variable_warning(ptr3);
|
|
|
|
rgb8_step_ptr_t stepIt4(ptr,5);
|
|
++stepIt4;
|
|
|
|
rgb8_step_ptr_t stepIt5;
|
|
if (stepIt4==stepIt5) {
|
|
int st=0;ignore_unused_variable_warning(st);
|
|
}
|
|
|
|
iterator_from_2d<rgb8_loc_t> pix_img_it(rgb8_loc_t(ptr, 20), 5);
|
|
++pix_img_it;
|
|
pix_img_it+=10;
|
|
rgb8_pixel_t& refr=*pix_img_it;
|
|
refr=rgb8_pixel_t(1,2,3);
|
|
*pix_img_it=rgb8_pixel_t(1,2,3);
|
|
pix_img_it[3]=rgb8_pixel_t(1,2,3);
|
|
*(pix_img_it+3)=rgb8_pixel_t(1,2,3);
|
|
|
|
iterator_from_2d<rgb8c_loc_t> pix_img_it_c(rgb8c_loc_t(rgb8c_ptr_t(ptr),20), 5);
|
|
++pix_img_it_c;
|
|
pix_img_it_c+=10;
|
|
// *pix_img_it_c=rgb8_pixel_t(1,2,3); // error: assigning though const iterator
|
|
using dif_t = iterator_from_2d<rgb8_loc_t>::difference_type;
|
|
dif_t dt=0;
|
|
std::ptrdiff_t tdt=dt; ignore_unused_variable_warning(tdt);
|
|
|
|
// memory_based_step_iterator<rgb8_pixel_t> stepIt3Err=stepIt+10; // error: non-const from const iterator
|
|
|
|
memory_based_2d_locator<rgb8_step_ptr_t> xy_locator(ptr,27);
|
|
|
|
xy_locator.x()++;
|
|
// memory_based_step_iterator<rgb8_pixel_t>& yit=xy_locator.y();
|
|
xy_locator.y()++;
|
|
xy_locator+=point<std::ptrdiff_t>(3,4);
|
|
// *xy_locator=(xy_locator(-1,0)+xy_locator(0,1))/2;
|
|
rgb8_pixel_t& rf=*xy_locator; ignore_unused_variable_warning(rf);
|
|
|
|
make_step_iterator(rgb8_ptr_t(),3);
|
|
make_step_iterator(rgb8_planar_ptr_t(),3);
|
|
make_step_iterator(rgb8_planar_step_ptr_t(),3);
|
|
|
|
// Test operator-> on planar ptrs
|
|
{
|
|
rgb8c_planar_ptr_t cp(&rgb8);
|
|
rgb8_planar_ptr_t p(&rgb8);
|
|
// get_color(p,red_t()) = get_color(cp,green_t()); // does not compile - cannot assign a non-const pointer to a const pointer. Otherwise you will be able to modify the value through it.
|
|
}
|
|
// xy_locator.y()++;
|
|
|
|
// dimensions to explore
|
|
//
|
|
// values, references, pointers
|
|
// color spaces (rgb,cmyk,gray)
|
|
// channel ordering (bgr vs rgb)
|
|
// planar vs interleaved
|
|
|
|
// Pixel POINTERS
|
|
// using RGB8ConstPtr = iterator_traits<rgb8_ptr_t>::pointer const;
|
|
using RGB8ConstPtr = rgb8_ptr_t const;
|
|
using RGB8ConstPlanarPtr = rgb8_planar_ptr_t const;
|
|
// using RGB8ConstPlanarPtr = iterator_traits<rgb8_planar_ptr_t>::pointer const;
|
|
|
|
// constructing from values, references and other pointers
|
|
RGB8ConstPtr rgb8_const_ptr=NULL; ignore_unused_variable_warning(rgb8_const_ptr);
|
|
rgb8_ptr_t rgb8ptr=&rgb8;
|
|
|
|
rgb8=bgr8_pixel_t(30,20,10);
|
|
rgb8_planar_ptr_t rgb8_pptr=&rgb8;
|
|
++rgb8_pptr;
|
|
rgb8_pptr--;
|
|
rgb8_pptr[0]=rgb8;
|
|
RGB8ConstPlanarPtr rgb8_const_planar_ptr=&rgb8;
|
|
|
|
rgb8c_planar_ptr_t r8c=&rgb8;
|
|
r8c=&rgb8;
|
|
|
|
rgb8_pptr=&rgb8;
|
|
|
|
// rgb8_const_planar_ptr=&rgb16p; // error: incompatible bit depth
|
|
|
|
// iterator_traits<CMYK8>::pointer cmyk8_ptr_t=&rgb8; // error: incompatible pointer type
|
|
|
|
RGB8ConstPtr rgb8_const_ptr_err=rgb8ptr; // const pointer from non-regular pointer
|
|
ignore_unused_variable_warning(rgb8_const_ptr_err);
|
|
// dereferencing pointers to obtain references
|
|
rgb8_ref_t rgb8ref_2=*rgb8ptr; ignore_unused_variable_warning(rgb8ref_2);
|
|
assert(rgb8ref_2==rgb8);
|
|
// RGB8Ref rgb8ref_2_err=*rgb8_const_planar_ptr; // error: non-const reference from const pointer
|
|
|
|
rgb8_planar_ref_t rgb8planarref_3=*rgb8_pptr; // planar reference from planar pointer
|
|
assert(rgb8planarref_3==rgb8);
|
|
// RGB8Ref rgb8ref_3=*rgb8_planar_ptr_t; // error: non-planar reference from planar pointer
|
|
|
|
const rgb8_pixel_t crgb8=rgb8;
|
|
*rgb8_pptr=rgb8;
|
|
*rgb8_pptr=crgb8;
|
|
|
|
memunit_advance(rgb8_pptr,3);
|
|
memunit_advance(rgb8_pptr,-3);
|
|
}
|
|
*/
|
|
|
|
int main()
|
|
{
|
|
try
|
|
{
|
|
test_pixel_iterator();
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|
|
catch (std::exception const& e)
|
|
{
|
|
std::cerr << e.what() << std::endl;
|
|
return EXIT_FAILURE;
|
|
}
|
|
catch (...)
|
|
{
|
|
return EXIT_FAILURE;
|
|
}
|
|
}
|