PageRenderTime 72ms CodeModel.GetById 18ms app.highlight 50ms RepoModel.GetById 1ms app.codeStats 0ms

/Src/Dependencies/Boost/libs/gil/test/pixel.cpp

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