PageRenderTime 63ms CodeModel.GetById 33ms RepoModel.GetById 1ms app.codeStats 0ms

/Libraries/Boost1.40/libs/gil/test/pixel.cpp

https://github.com/metrixcreate/RepSnapper
C++ | 332 lines | 237 code | 62 blank | 33 comment | 23 complexity | 013831e5441419ced541131b1262e3f8 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-2.0, BSD-3-Clause, LGPL-2.0
  1. /*
  2. Copyright 2005-2007 Adobe Systems Incorporated
  3. Use, modification and distribution are subject to the Boost Software License,
  4. Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
  5. http://www.boost.org/LICENSE_1_0.txt).
  6. See http://opensource.adobe.com/gil for most recent version including documentation.
  7. */
  8. // pixel.cpp : Tests GIL pixels.
  9. //
  10. #include <iterator>
  11. #include <iostream>
  12. #include <boost/type_traits.hpp>
  13. #include <boost/mpl/vector.hpp>
  14. #include <boost/mpl/size.hpp>
  15. #include <boost/mpl/at.hpp>
  16. #include <boost/mpl/size.hpp>
  17. #include <boost/gil/planar_pixel_reference.hpp>
  18. #include <boost/gil/packed_pixel.hpp>
  19. #include <boost/gil/rgb.hpp>
  20. #include <boost/gil/gray.hpp>
  21. #include <boost/gil/rgba.hpp>
  22. #include <boost/gil/cmyk.hpp>
  23. #include <boost/gil/pixel.hpp>
  24. #include <boost/gil/typedefs.hpp>
  25. #include <boost/gil/channel_algorithm.hpp>
  26. #include <boost/gil/color_convert.hpp>
  27. #include <boost/gil/gil_concept.hpp>
  28. #include <boost/gil/metafunctions.hpp>
  29. #include <boost/gil/bit_aligned_pixel_reference.hpp>
  30. // Testing pixel references and values, pixel operations, color conversion
  31. using namespace boost::gil;
  32. using namespace std;
  33. using namespace boost;
  34. void error_if(bool condition);
  35. struct increment {
  36. template <typename Incrementable> void operator()(Incrementable& x) const { ++x; }
  37. };
  38. struct prev {
  39. template <typename Subtractable>
  40. typename channel_traits<Subtractable>::value_type operator()(const Subtractable& x) const { return x-1; }
  41. };
  42. struct set_to_one{ int operator()() const { return 1; } };
  43. // Construct with two pixel types. They must be compatible and the second must be mutable
  44. template <typename C1, typename C2>
  45. struct do_basic_test : public C1, public C2 {
  46. typedef typename C1::type pixel1_t;
  47. typedef typename C2::type pixel2_t;
  48. typedef typename C1::pixel_t::value_type pixel1_value_t;
  49. typedef typename C2::pixel_t::value_type pixel2_value_t;
  50. typedef pixel1_value_t pixel_value_t;
  51. do_basic_test(const pixel_value_t& v) : C1(v), C2(v) {}
  52. void test_all() {
  53. test_heterogeneous();
  54. // test homogeneous algorithms - fill, max, min
  55. static const int num_chan = num_channels<typename C2::pixel_t>::value;
  56. static_fill(C2::_pixel, at_c<0>(C1::_pixel)+1);
  57. error_if(at_c<0>(C2::_pixel) != at_c<num_chan-1>(C2::_pixel));
  58. C2::_pixel = C1::_pixel;
  59. error_if(static_max(C2::_pixel) != static_max(C1::_pixel));
  60. error_if(static_min(C2::_pixel) != static_min(C1::_pixel));
  61. error_if(static_max(C2::_pixel) < static_min(C2::_pixel));
  62. // test operator[]
  63. C2::_pixel[0] = C1::_pixel[0]+1;
  64. error_if(C2::_pixel[0] != C1::_pixel[0]+1);
  65. }
  66. void test_heterogeneous() {
  67. // Both must be pixel types (not necessarily pixel values). The second must be mutable. They must be compatible
  68. boost::function_requires<PixelConcept<typename C1::pixel_t> >();
  69. boost::function_requires<MutablePixelConcept<typename C2::pixel_t> >();
  70. boost::function_requires<PixelsCompatibleConcept<typename C1::pixel_t,typename C2::pixel_t> >();
  71. C2::_pixel = C1::_pixel; // test operator=
  72. error_if(C1::_pixel != C2::_pixel); // test operator==
  73. // construct a pixel value from it
  74. pixel1_value_t v1(C1::_pixel);
  75. pixel2_value_t v2(C2::_pixel);
  76. error_if(v1 != v2);
  77. // construct from a pixel value
  78. pixel1_t c1(v1);
  79. pixel2_t c2(v2);
  80. error_if(c1 != c2);
  81. // Invert the first semantic channel.
  82. C2::_pixel = C1::_pixel;
  83. semantic_at_c<0>(C2::_pixel) = channel_invert(semantic_at_c<0>(C2::_pixel));
  84. error_if(C1::_pixel == C2::_pixel); // now they must not be equal
  85. // test pixel algorithms
  86. C2::_pixel = C1::_pixel;
  87. static_for_each(C2::_pixel, increment());
  88. static_transform(C2::_pixel, C2::_pixel, prev());
  89. error_if(C1::_pixel!=C2::_pixel);
  90. static_generate(C2::_pixel, set_to_one());
  91. error_if(at_c<0>(C2::_pixel) != 1);
  92. // Test swap if both are mutable and if their value type is the same
  93. // (We know the second one is mutable)
  94. typedef typename boost::add_reference<typename C1::type>::type p1_ref;
  95. test_swap(
  96. boost::mpl::bool_<
  97. pixel_reference_is_mutable<p1_ref>::value &&
  98. boost::is_same<pixel1_value_t,pixel2_value_t>::value> ());
  99. }
  100. void test_swap(boost::mpl::false_) {}
  101. void test_swap(boost::mpl::true_) {
  102. // test swap
  103. static_fill(C1::_pixel, 0);
  104. static_fill(C2::_pixel, 1);
  105. pixel_value_t pv1(C1::_pixel);
  106. pixel_value_t pv2(C2::_pixel);
  107. error_if(C2::_pixel == C1::_pixel);
  108. swap(C1::_pixel, C2::_pixel);
  109. error_if(C1::_pixel != pv2 || C2::_pixel != pv1);
  110. }
  111. };
  112. template <typename PixelValue, int Tag=0>
  113. class value_core {
  114. public:
  115. typedef PixelValue type;
  116. typedef type pixel_t;
  117. type _pixel;
  118. value_core() : _pixel(0) {}
  119. value_core(const type& val) : _pixel(val) { // test copy constructor
  120. boost::function_requires<PixelValueConcept<pixel_t> >();
  121. type p2; // test default constructor
  122. }
  123. };
  124. template <typename PixelRef, int Tag=0>
  125. class reference_core : public value_core<typename boost::remove_reference<PixelRef>::type::value_type, Tag> {
  126. public:
  127. typedef PixelRef type;
  128. typedef typename boost::remove_reference<PixelRef>::type pixel_t;
  129. typedef value_core<typename pixel_t::value_type, Tag> parent_t;
  130. type _pixel;
  131. reference_core() : parent_t(), _pixel(parent_t::_pixel) {}
  132. reference_core(const typename pixel_t::value_type& val) : parent_t(val), _pixel(parent_t::_pixel) {
  133. boost::function_requires<PixelConcept<pixel_t> >();
  134. }
  135. };
  136. // Use a subset of pixel models that covers all color spaces, channel depths, reference/value, planar/interleaved, const/mutable
  137. // color conversion will be invoked on pairs of them. Having an exhaustive binary check would be too big/expensive.
  138. typedef mpl::vector<
  139. value_core<gray8_pixel_t>,
  140. reference_core<gray16_pixel_t&>,
  141. value_core<bgr8_pixel_t>,
  142. reference_core<rgb8_planar_ref_t>,
  143. value_core<argb32_pixel_t>,
  144. reference_core<cmyk32f_pixel_t&>,
  145. reference_core<abgr16c_ref_t>, // immutable reference
  146. reference_core<rgb32fc_planar_ref_t>
  147. > representative_pixels_t;
  148. template <typename Vector, typename Fun, int K>
  149. struct for_each_impl {
  150. static void apply(Fun fun) {
  151. for_each_impl<Vector,Fun,K-1>::apply(fun);
  152. fun(typename mpl::at_c<Vector,K>::type());
  153. }
  154. };
  155. template <typename Vector, typename Fun>
  156. struct for_each_impl<Vector,Fun,-1> {
  157. static void apply(Fun fun) {}
  158. };
  159. template <typename Vector, typename Fun>
  160. void for_each(Fun fun) {
  161. for_each_impl<Vector,Fun, mpl::size<Vector>::value-1>::apply(fun);
  162. }
  163. template <typename Pixel1>
  164. struct ccv2 {
  165. template <typename P1, typename P2>
  166. void color_convert_compatible(const P1& p1, P2& p2, mpl::true_) {
  167. typedef typename P1::value_type value_t;
  168. p2 = p1;
  169. value_t converted;
  170. color_convert(p1, converted);
  171. error_if(converted != p2);
  172. }
  173. template <typename P1, typename P2>
  174. void color_convert_compatible(const P1& p1, P2& p2, mpl::false_) {
  175. color_convert(p1,p2);
  176. }
  177. template <typename P1, typename P2>
  178. void color_convert_impl(const P1& p1, P2& p2) {
  179. color_convert_compatible(p1, p2, mpl::bool_<pixels_are_compatible<P1,P2>::value>());
  180. }
  181. template <typename Pixel2>
  182. void operator()(Pixel2) {
  183. // convert from Pixel1 to Pixel2 (or, if Pixel2 is immutable, to its value type)
  184. static const int p2_is_mutable = pixel_reference_is_mutable<typename Pixel2::type>::type::value;
  185. typedef typename boost::remove_reference<typename Pixel2::type>::type pixel_model_t;
  186. typedef typename pixel_model_t::value_type p2_value_t;
  187. typedef typename mpl::if_c<p2_is_mutable, Pixel2, value_core<p2_value_t> >::type pixel2_mutable;
  188. Pixel1 p1;
  189. pixel2_mutable p2;
  190. color_convert_impl(p1._pixel, p2._pixel);
  191. }
  192. };
  193. struct ccv1 {
  194. template <typename Pixel>
  195. void operator()(Pixel) {
  196. for_each<representative_pixels_t>(ccv2<Pixel>());
  197. }
  198. };
  199. void test_color_convert() {
  200. for_each<representative_pixels_t>(ccv1());
  201. }
  202. void test_packed_pixel() {
  203. typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, rgb_layout_t>::type rgb565_pixel_t;
  204. boost::function_requires<PixelValueConcept<rgb565_pixel_t> >();
  205. BOOST_STATIC_ASSERT((sizeof(rgb565_pixel_t)==2));
  206. // define a bgr556 pixel
  207. typedef packed_pixel_type<uint16_t, mpl::vector3_c<unsigned,5,6,5>, bgr_layout_t>::type bgr556_pixel_t;
  208. boost::function_requires<PixelValueConcept<bgr556_pixel_t> >();
  209. // Create a zero packed pixel and a full regular unpacked pixel.
  210. rgb565_pixel_t r565;//((uint16_t)0);
  211. rgb8_pixel_t rgb_full(255,255,255);
  212. // Convert all channels of the unpacked pixel to the packed one & assert the packed one is full
  213. get_color(r565,red_t()) = channel_convert<kth_element_type<rgb565_pixel_t, 0>::type>(get_color(rgb_full,red_t()));
  214. get_color(r565,green_t()) = channel_convert<kth_element_type<rgb565_pixel_t, 1>::type>(get_color(rgb_full,green_t()));
  215. get_color(r565,blue_t()) = channel_convert<kth_element_type<rgb565_pixel_t, 2>::type>(get_color(rgb_full,blue_t()));
  216. error_if(r565 != rgb565_pixel_t((uint16_t)65535));
  217. // rgb565 is compatible with bgr556. Test interoperability
  218. boost::function_requires<PixelsCompatibleConcept<rgb565_pixel_t,bgr556_pixel_t> >();
  219. do_basic_test<value_core<rgb565_pixel_t,0>, value_core<bgr556_pixel_t,1> >(r565).test_heterogeneous();
  220. color_convert(r565,rgb_full);
  221. color_convert(rgb_full,r565);
  222. // Test bit-aligned pixel reference
  223. typedef const bit_aligned_pixel_reference<boost::uint8_t, boost::mpl::vector3_c<int,1,2,1>, bgr_layout_t, true> bgr121_ref_t;
  224. typedef const bit_aligned_pixel_reference<boost::uint8_t, boost::mpl::vector3_c<int,1,2,1>, rgb_layout_t, true> rgb121_ref_t;
  225. typedef rgb121_ref_t::value_type rgb121_pixel_t;
  226. rgb121_pixel_t p121;
  227. do_basic_test<reference_core<bgr121_ref_t,0>, reference_core<rgb121_ref_t,1> >(p121).test_heterogeneous();
  228. do_basic_test<value_core<rgb121_pixel_t,0>, reference_core<rgb121_ref_t,1> >(p121).test_heterogeneous();
  229. BOOST_STATIC_ASSERT((pixel_reference_is_proxy<rgb8_planar_ref_t>::value));
  230. BOOST_STATIC_ASSERT((pixel_reference_is_proxy<bgr121_ref_t>::value));
  231. BOOST_STATIC_ASSERT(!(pixel_reference_is_proxy<rgb8_pixel_t>::value));
  232. BOOST_STATIC_ASSERT(!(pixel_reference_is_proxy<rgb8_pixel_t&>::value));
  233. BOOST_STATIC_ASSERT(!(pixel_reference_is_proxy<const rgb8_pixel_t&>::value));
  234. BOOST_STATIC_ASSERT( (pixel_reference_is_mutable< rgb8_pixel_t&>::value));
  235. BOOST_STATIC_ASSERT(!(pixel_reference_is_mutable<const rgb8_pixel_t&>::value));
  236. BOOST_STATIC_ASSERT((pixel_reference_is_mutable<const rgb8_planar_ref_t&>::value));
  237. BOOST_STATIC_ASSERT((pixel_reference_is_mutable< rgb8_planar_ref_t >::value));
  238. BOOST_STATIC_ASSERT(!(pixel_reference_is_mutable<const rgb8c_planar_ref_t&>::value));
  239. BOOST_STATIC_ASSERT(!(pixel_reference_is_mutable< rgb8c_planar_ref_t >::value));
  240. BOOST_STATIC_ASSERT( (pixel_reference_is_mutable<bgr121_ref_t>::value));
  241. BOOST_STATIC_ASSERT(!(pixel_reference_is_mutable<bgr121_ref_t::const_reference>::value));
  242. }
  243. void test_pixel() {
  244. test_packed_pixel();
  245. rgb8_pixel_t rgb8(1,2,3);
  246. do_basic_test<value_core<rgb8_pixel_t,0>, reference_core<rgb8_pixel_t&,1> >(rgb8).test_all();
  247. do_basic_test<value_core<bgr8_pixel_t,0>, reference_core<rgb8_planar_ref_t,1> >(rgb8).test_all();
  248. do_basic_test<reference_core<rgb8_planar_ref_t,0>, reference_core<bgr8_pixel_t&,1> >(rgb8).test_all();
  249. do_basic_test<reference_core<const rgb8_pixel_t&,0>, reference_core<rgb8_pixel_t&,1> >(rgb8).test_all();
  250. test_color_convert();
  251. // Semantic vs physical channel accessors. Named channel accessors
  252. bgr8_pixel_t bgr8(rgb8);
  253. error_if(bgr8[0] == rgb8[0]);
  254. error_if(dynamic_at_c(bgr8,0) == dynamic_at_c(rgb8,0));
  255. error_if(at_c<0>(bgr8) == at_c<0>(rgb8));
  256. error_if(semantic_at_c<0>(bgr8) != semantic_at_c<0>(rgb8));
  257. error_if(get_color(bgr8,blue_t()) != get_color(rgb8,blue_t()));
  258. // Assigning a grayscale channel to a pixel
  259. gray16_pixel_t g16(34);
  260. g16 = 8;
  261. bits16 g = get_color(g16,gray_color_t());
  262. error_if(g != 8);
  263. error_if(g16 != 8);
  264. }
  265. int main(int argc, char* argv[]) {
  266. test_pixel();
  267. return 0;
  268. }