pixel_iterator.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  1. //
  2. // Copyright 2005-2007 Adobe Systems Incorporated
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. #ifdef _MSC_VER
  9. #pragma warning(disable : 4244) // 'argument': conversion from 'int' to 'unsigned char', possible loss of data
  10. #endif
  11. #include <boost/gil.hpp>
  12. #include <boost/assert.hpp>
  13. #include <boost/mp11.hpp>
  14. #include <exception>
  15. #include <iostream>
  16. #include <type_traits>
  17. #include <vector>
  18. using namespace boost::gil;
  19. using namespace std;
  20. void test_pixel_iterator()
  21. {
  22. boost::function_requires<Point2DConcept<point<int>>>();
  23. boost::function_requires<MutablePixelIteratorConcept<bgr8_ptr_t> >();
  24. boost::function_requires<MutablePixelIteratorConcept<cmyk8_planar_ptr_t> >();
  25. boost::function_requires<PixelIteratorConcept<rgb8c_planar_step_ptr_t> >();
  26. boost::function_requires<MutableStepIteratorConcept<rgb8_step_ptr_t> >();
  27. boost::function_requires<MutablePixelLocatorConcept<rgb8_step_loc_t> >();
  28. boost::function_requires<PixelLocatorConcept<rgb8c_planar_step_loc_t> >();
  29. boost::function_requires<MutableStepIteratorConcept<cmyk8_planar_step_ptr_t> >();
  30. boost::function_requires<StepIteratorConcept<gray8c_step_ptr_t> >();
  31. boost::function_requires<MutablePixelLocatorConcept<memory_based_2d_locator<rgb8_step_ptr_t> > >();
  32. using bgr121_ref_t = bit_aligned_pixel_reference
  33. <
  34. std::uint8_t,
  35. boost::mp11::mp_list_c<int,1,2,1>,
  36. bgr_layout_t,
  37. true
  38. > const;
  39. using bgr121_ptr_t = bit_aligned_pixel_iterator<bgr121_ref_t>;
  40. boost::function_requires<MutablePixelIteratorConcept<bgr121_ptr_t> >();
  41. boost::function_requires<PixelBasedConcept<bgr121_ptr_t> >();
  42. boost::function_requires<MemoryBasedIteratorConcept<bgr121_ptr_t> >();
  43. boost::function_requires<HasDynamicXStepTypeConcept<bgr121_ptr_t> >();
  44. // TEST dynamic_step_t
  45. static_assert(std::is_same<cmyk16_step_ptr_t, dynamic_x_step_type<cmyk16_step_ptr_t>::type>::value, "");
  46. static_assert(std::is_same<cmyk16_planar_step_ptr_t, dynamic_x_step_type<cmyk16_planar_ptr_t>::type>::value, "");
  47. static_assert(std::is_same<iterator_type<uint8_t,gray_layout_t,false,false,false>::type,gray8c_ptr_t>::value, "");
  48. // TEST iterator_is_step
  49. static_assert(iterator_is_step<cmyk16_step_ptr_t>::value, "");
  50. static_assert(iterator_is_step<cmyk16_planar_step_ptr_t>::value, "");
  51. static_assert(!iterator_is_step<cmyk16_planar_ptr_t>::value, "");
  52. using ccv_rgb_g_fn = color_convert_deref_fn<rgb8c_ref_t, gray8_pixel_t>;
  53. using ccv_g_rgb_fn = color_convert_deref_fn<gray8c_ref_t, rgb8_pixel_t>;
  54. gil_function_requires<PixelDereferenceAdaptorConcept<ccv_rgb_g_fn> >();
  55. gil_function_requires<PixelDereferenceAdaptorConcept<deref_compose<ccv_rgb_g_fn,ccv_g_rgb_fn> > >();
  56. using rgb2gray_ptr = dereference_iterator_adaptor<rgb8_ptr_t, ccv_rgb_g_fn>;
  57. static_assert(!iterator_is_step<rgb2gray_ptr>::value, "");
  58. using rgb2gray_step_ptr = dynamic_x_step_type<rgb2gray_ptr>::type;
  59. static_assert(std::is_same<rgb2gray_step_ptr, dereference_iterator_adaptor<rgb8_step_ptr_t, ccv_rgb_g_fn>>::value, "");
  60. make_step_iterator(rgb2gray_ptr(),2);
  61. using rgb2gray_step_ptr1 = dereference_iterator_adaptor<rgb8_step_ptr_t, ccv_rgb_g_fn>;
  62. static_assert(iterator_is_step<rgb2gray_step_ptr1>::value, "");
  63. static_assert(std::is_same<rgb2gray_step_ptr1, dynamic_x_step_type<rgb2gray_step_ptr1>::type>::value, "");
  64. using rgb2gray_step_ptr2 = memory_based_step_iterator<dereference_iterator_adaptor<rgb8_ptr_t, ccv_rgb_g_fn>>;
  65. static_assert(iterator_is_step<rgb2gray_step_ptr2 >::value, "");
  66. static_assert(std::is_same<rgb2gray_step_ptr2, dynamic_x_step_type<rgb2gray_step_ptr2>::type>::value, "");
  67. make_step_iterator(rgb2gray_step_ptr2(),2);
  68. // bit_aligned iterators test
  69. // Mutable reference to a BGR232 pixel
  70. using bgr232_ref_t = bit_aligned_pixel_reference
  71. <
  72. std::uint8_t,
  73. boost::mp11::mp_list_c<unsigned, 2, 3, 2>,
  74. bgr_layout_t,
  75. true
  76. > const;
  77. // A mutable iterator over BGR232 pixels
  78. using bgr232_ptr_t = bit_aligned_pixel_iterator<bgr232_ref_t>;
  79. // BGR232 pixel value. It is a packed_pixel of size 1 byte. (The last bit is unused)
  80. using bgr232_pixel_t = std::iterator_traits<bgr232_ptr_t>::value_type;
  81. static_assert(sizeof(bgr232_pixel_t) == 1, "");
  82. bgr232_pixel_t red(0,0,3); // = 0RRGGGBB, = 01100000
  83. // a buffer of 7 bytes fits exactly 8 BGR232 pixels.
  84. unsigned char pix_buffer[7];
  85. std::fill(pix_buffer,pix_buffer+7,0);
  86. bgr232_ptr_t pix_it(&pix_buffer[0],0); // start at bit 0 of the first pixel
  87. for (int i=0; i<8; ++i) {
  88. *pix_it++ = red;
  89. }
  90. // test cross byte pixel values - meaning when a pixel value is stretched over two bytes
  91. using gray3_image_t = bit_aligned_image1_type<3, gray_layout_t>::type;
  92. using image_t = gray3_image_t;
  93. using view_t = image_t::view_t;
  94. using ref_t = view_t::reference;
  95. using iterator_t = bit_aligned_pixel_iterator<ref_t>;
  96. std::vector< unsigned char > buf( 4 );
  97. // bit pattern is: 1011 0110 0110 1101 1101 1011
  98. // each byte is read right to left
  99. buf[0] = 182;
  100. buf[1] = 109;
  101. buf[2] = 219;
  102. iterator_t it( &buf[0], 0 );
  103. ref_t p1 = *it; it++;
  104. ref_t p2 = *it; it++;
  105. ref_t p3 = *it; it++;
  106. ref_t p4 = *it; it++;
  107. ref_t p5 = *it; it++;
  108. ref_t p6 = *it; it++;
  109. ref_t p7 = *it; it++;
  110. ref_t p8 = *it; it++;
  111. unsigned char v1 = get_color( p1, gray_color_t() );
  112. unsigned char v2 = get_color( p2, gray_color_t() );
  113. unsigned char v3 = get_color( p3, gray_color_t() );
  114. unsigned char v4 = get_color( p4, gray_color_t() );
  115. unsigned char v5 = get_color( p5, gray_color_t() );
  116. unsigned char v6 = get_color( p6, gray_color_t() );
  117. unsigned char v7 = get_color( p7, gray_color_t() );
  118. unsigned char v8 = get_color( p8, gray_color_t() );
  119. // all values should be 110b ( 6 );
  120. BOOST_ASSERT(v1 == 6);
  121. BOOST_ASSERT(v2 == 6);
  122. BOOST_ASSERT(v3 == 6);
  123. BOOST_ASSERT(v4 == 6);
  124. BOOST_ASSERT(v5 == 6);
  125. BOOST_ASSERT(v6 == 6);
  126. BOOST_ASSERT(v7 == 6);
  127. BOOST_ASSERT(v8 == 6);
  128. }
  129. // TODO: Make better tests. Use some code from below.
  130. /*
  131. template <typename Pixel>
  132. void invert_pixel1(Pixel& pix) {
  133. at_c<0>(pix)=0;
  134. }
  135. template <typename T> inline void ignore_unused_variable_warning(const T&){}
  136. void test_pixel_iterator() {
  137. rgb8_pixel_t rgb8(1,2,3);
  138. rgba8_pixel_t rgba8;
  139. rgb8_ptr_t ptr1=&rgb8;
  140. memunit_advance(ptr1, 3);
  141. const rgb8_ptr_t ptr2=memunit_advanced(ptr1,10);
  142. memunit_distance(ptr1,ptr2);
  143. const rgb8_pixel_t& ref=memunit_advanced_ref(ptr1,10); ignore_unused_variable_warning(ref);
  144. rgb8_planar_ptr_t planarPtr1(&rgb8);
  145. rgb8_planar_ptr_t planarPtr2(&rgb8);
  146. memunit_advance(planarPtr1,10);
  147. memunit_distance(planarPtr1,planarPtr2);
  148. rgb8_planar_ptr_t planarPtr3=memunit_advanced(planarPtr1,10);
  149. // planarPtr2=&rgba8;
  150. planar_pixel_reference<uint8_t&,rgb_t> pxl=*(planarPtr1+5);
  151. rgb8_pixel_t pv2=pxl;
  152. rgb8_pixel_t pv3=*(planarPtr1+5);
  153. rgb8_pixel_t pv=planarPtr1[5];
  154. assert(*(planarPtr1+5)==planarPtr1[5]);
  155. rgb8_planar_ref_t planarRef=memunit_advanced_ref(planarPtr1,10);
  156. rgb8_step_ptr_t stepIt(&rgb8,5);
  157. stepIt++;
  158. rgb8_step_ptr_t stepIt2=stepIt+10;
  159. stepIt2=stepIt;
  160. rgb8_step_ptr_t stepIt3(&rgb8,5);
  161. rgb8_pixel_t& ref1=stepIt3[5];
  162. // bool v=std::is_pod<iterator_traits<memory_based_step_iterator<rgb8_ptr_t> >::value_type>::value;
  163. // v=std::is_pod<rgb8_pixel_t>::value;
  164. // v=std::is_pod<int>::value;
  165. rgb8_step_ptr_t rgb8StepIt(ptr1, 10);
  166. rgb8_step_ptr_t rgb8StepIt2=rgb8StepIt;
  167. rgb8StepIt=rgb8StepIt2;
  168. ++rgb8StepIt;
  169. rgb8_ref_t reff=*rgb8StepIt; ignore_unused_variable_warning(reff);
  170. rgb8StepIt+=10;
  171. std::ptrdiff_t dst=rgb8StepIt2-rgb8StepIt; ignore_unused_variable_warning(dst);
  172. rgb8_pixel_t val1=ref1;
  173. rgb8_ptr_t ptr=&ref1;
  174. invert_pixel1(*planarPtr1);
  175. // invert_pixel1(*ptr);
  176. rgb8c_planar_ptr_t r8cpp;
  177. // invert_pixel1(*r8cpp);
  178. rgb8_pixel_t& val21=stepIt3[5];
  179. rgb8_pixel_t val22=val21;
  180. rgb8_pixel_t val2=stepIt3[5];
  181. rgb8_ptr_t ptr11=&(stepIt3[5]); ignore_unused_variable_warning(ptr11);
  182. rgb8_ptr_t ptr3=&*(stepIt3+5); ignore_unused_variable_warning(ptr3);
  183. rgb8_step_ptr_t stepIt4(ptr,5);
  184. ++stepIt4;
  185. rgb8_step_ptr_t stepIt5;
  186. if (stepIt4==stepIt5) {
  187. int st=0;ignore_unused_variable_warning(st);
  188. }
  189. iterator_from_2d<rgb8_loc_t> pix_img_it(rgb8_loc_t(ptr, 20), 5);
  190. ++pix_img_it;
  191. pix_img_it+=10;
  192. rgb8_pixel_t& refr=*pix_img_it;
  193. refr=rgb8_pixel_t(1,2,3);
  194. *pix_img_it=rgb8_pixel_t(1,2,3);
  195. pix_img_it[3]=rgb8_pixel_t(1,2,3);
  196. *(pix_img_it+3)=rgb8_pixel_t(1,2,3);
  197. iterator_from_2d<rgb8c_loc_t> pix_img_it_c(rgb8c_loc_t(rgb8c_ptr_t(ptr),20), 5);
  198. ++pix_img_it_c;
  199. pix_img_it_c+=10;
  200. // *pix_img_it_c=rgb8_pixel_t(1,2,3); // error: assigning though const iterator
  201. using dif_t = iterator_from_2d<rgb8_loc_t>::difference_type;
  202. dif_t dt=0;
  203. std::ptrdiff_t tdt=dt; ignore_unused_variable_warning(tdt);
  204. // memory_based_step_iterator<rgb8_pixel_t> stepIt3Err=stepIt+10; // error: non-const from const iterator
  205. memory_based_2d_locator<rgb8_step_ptr_t> xy_locator(ptr,27);
  206. xy_locator.x()++;
  207. // memory_based_step_iterator<rgb8_pixel_t>& yit=xy_locator.y();
  208. xy_locator.y()++;
  209. xy_locator+=point<std::ptrdiff_t>(3,4);
  210. // *xy_locator=(xy_locator(-1,0)+xy_locator(0,1))/2;
  211. rgb8_pixel_t& rf=*xy_locator; ignore_unused_variable_warning(rf);
  212. make_step_iterator(rgb8_ptr_t(),3);
  213. make_step_iterator(rgb8_planar_ptr_t(),3);
  214. make_step_iterator(rgb8_planar_step_ptr_t(),3);
  215. // Test operator-> on planar ptrs
  216. {
  217. rgb8c_planar_ptr_t cp(&rgb8);
  218. rgb8_planar_ptr_t p(&rgb8);
  219. // 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.
  220. }
  221. // xy_locator.y()++;
  222. // dimensions to explore
  223. //
  224. // values, references, pointers
  225. // color spaces (rgb,cmyk,gray)
  226. // channel ordering (bgr vs rgb)
  227. // planar vs interleaved
  228. // Pixel POINTERS
  229. // using RGB8ConstPtr = iterator_traits<rgb8_ptr_t>::pointer const;
  230. using RGB8ConstPtr = rgb8_ptr_t const;
  231. using RGB8ConstPlanarPtr = rgb8_planar_ptr_t const;
  232. // using RGB8ConstPlanarPtr = iterator_traits<rgb8_planar_ptr_t>::pointer const;
  233. // constructing from values, references and other pointers
  234. RGB8ConstPtr rgb8_const_ptr=NULL; ignore_unused_variable_warning(rgb8_const_ptr);
  235. rgb8_ptr_t rgb8ptr=&rgb8;
  236. rgb8=bgr8_pixel_t(30,20,10);
  237. rgb8_planar_ptr_t rgb8_pptr=&rgb8;
  238. ++rgb8_pptr;
  239. rgb8_pptr--;
  240. rgb8_pptr[0]=rgb8;
  241. RGB8ConstPlanarPtr rgb8_const_planar_ptr=&rgb8;
  242. rgb8c_planar_ptr_t r8c=&rgb8;
  243. r8c=&rgb8;
  244. rgb8_pptr=&rgb8;
  245. // rgb8_const_planar_ptr=&rgb16p; // error: incompatible bit depth
  246. // iterator_traits<CMYK8>::pointer cmyk8_ptr_t=&rgb8; // error: incompatible pointer type
  247. RGB8ConstPtr rgb8_const_ptr_err=rgb8ptr; // const pointer from non-regular pointer
  248. ignore_unused_variable_warning(rgb8_const_ptr_err);
  249. // dereferencing pointers to obtain references
  250. rgb8_ref_t rgb8ref_2=*rgb8ptr; ignore_unused_variable_warning(rgb8ref_2);
  251. assert(rgb8ref_2==rgb8);
  252. // RGB8Ref rgb8ref_2_err=*rgb8_const_planar_ptr; // error: non-const reference from const pointer
  253. rgb8_planar_ref_t rgb8planarref_3=*rgb8_pptr; // planar reference from planar pointer
  254. assert(rgb8planarref_3==rgb8);
  255. // RGB8Ref rgb8ref_3=*rgb8_planar_ptr_t; // error: non-planar reference from planar pointer
  256. const rgb8_pixel_t crgb8=rgb8;
  257. *rgb8_pptr=rgb8;
  258. *rgb8_pptr=crgb8;
  259. memunit_advance(rgb8_pptr,3);
  260. memunit_advance(rgb8_pptr,-3);
  261. }
  262. */
  263. int main()
  264. {
  265. try
  266. {
  267. test_pixel_iterator();
  268. return EXIT_SUCCESS;
  269. }
  270. catch (std::exception const& e)
  271. {
  272. std::cerr << e.what() << std::endl;
  273. return EXIT_FAILURE;
  274. }
  275. catch (...)
  276. {
  277. return EXIT_FAILURE;
  278. }
  279. }