• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2013 Christian Henning
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 #ifndef BOOST_GIL_TEST_EXTENSION_IO_MANDEL_VIEW_HPP
9 #define BOOST_GIL_TEST_EXTENSION_IO_MANDEL_VIEW_HPP
10 
11 #include <boost/gil.hpp>
12 
13 #include <cmath>
14 #include <cstdint>
15 
16 namespace gil = boost::gil;
17 
18 // Models a Unary Function
19 template <typename P>  // Models PixelValueConcept
20 struct mandelbrot_fn
21 {
22     using point_t                    = gil::point_t;
23     using const_t                    = mandelbrot_fn;
24     using value_type                 = P;
25     using reference                  = value_type;
26     using const_reference            = value_type;
27     using argument_type              = point_t;
28     using result_type                = reference;
29     static constexpr bool is_mutable = false;
30 
31     value_type in_color_;
32     value_type out_color_;
33     point_t img_size_;
34     static const int MAX_ITER = 100;  // max number of iterations
35 
36     mandelbrot_fn() = default;
mandelbrot_fnmandelbrot_fn37     mandelbrot_fn(gil::point_t const& sz, value_type const& in_color, value_type const& out_color)
38         : in_color_(in_color), out_color_(out_color), img_size_(sz)
39     {
40     }
41 
widthmandelbrot_fn42     std::ptrdiff_t width()
43     {
44         return img_size_.x;
45     }
heightmandelbrot_fn46     std::ptrdiff_t height()
47     {
48         return img_size_.y;
49     }
50 
operator ()mandelbrot_fn51     result_type operator()(gil::point_t const& p) const
52     {
53         // normalize the coords to (-2..1, -1.5..1.5)
54         // (actually make y -1.0..2 so it is asymmetric, so we can verify some view factory methods)
55         gil::point<double> const n{
56             static_cast<double>(p.x) / static_cast<double>(img_size_.x) * 3 - 2,
57             static_cast<double>(p.y) / static_cast<double>(img_size_.y) * 3 - 1.0f};  //1.5f}
58         double t = get_num_iter(n);
59         t        = std::pow(t, 0.2);
60 
61         value_type ret;
62         for (std::size_t k = 0; k < gil::num_channels<P>::value; ++k)
63             ret[k] =
64                 (typename gil::channel_type<P>::type)(in_color_[k] * t + out_color_[k] * (1 - t));
65         return ret;
66     }
67 
68     private:
get_num_itermandelbrot_fn69     double get_num_iter(boost::gil::point<double> const& p) const
70     {
71         gil::point<double> z(0, 0);
72         for (int i = 0; i < MAX_ITER; ++i)
73         {
74             z = gil::point<double>(z.x * z.x - z.y * z.y + p.x, 2 * z.x * z.y + p.y);
75             if (z.x * z.x + z.y * z.y > 4)
76                 return i / (double)MAX_ITER;
77         }
78         return 0;
79     }
80 };
81 
82 template <typename Pixel>
83 struct mandel_view
84 {
85     using deref_t        = mandelbrot_fn<Pixel>;
86     using locator_t      = gil::virtual_2d_locator<deref_t, false>;
87     using my_virt_view_t = gil::image_view<locator_t>;
88     using type           = my_virt_view_t;
89 };
90 
91 template <typename Pixel>
create_mandel_view(unsigned int width,unsigned int height,Pixel const & in,Pixel const & out)92 auto create_mandel_view(unsigned int width, unsigned int height, Pixel const& in, Pixel const& out)
93     -> typename mandel_view<Pixel>::type
94 {
95     using view_t    = typename mandel_view<Pixel>::type;
96     using deref_t   = typename mandel_view<Pixel>::deref_t;
97     using locator_t = typename mandel_view<Pixel>::locator_t;
98 
99     gil::point_t dims(width, height);
100     return view_t(dims, locator_t(gil::point_t(0, 0), gil::point_t(1, 1), deref_t(dims, in, out)));
101 }
102 
103 #endif // BOOST_GIL_TEST_EXTENSION_IO_MANDEL_VIEW_HPP
104