xref: /haiku/headers/libs/agg/agg_gamma_lut.h (revision 1acbe440b8dd798953bec31d18ee589aa3f71b73)
1 //----------------------------------------------------------------------------
2 // Anti-Grain Geometry - Version 2.4
3 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
4 //
5 // Permission to copy, use, modify, sell and distribute this software
6 // is granted provided this copyright notice appears in all copies.
7 // This software is provided "as is" without express or implied
8 // warranty, and with no claim as to its suitability for any purpose.
9 //
10 //----------------------------------------------------------------------------
11 // Contact: mcseem@antigrain.com
12 //          mcseemagg@yahoo.com
13 //          http://www.antigrain.com
14 //----------------------------------------------------------------------------
15 
16 #ifndef AGG_GAMMA_LUT_INCLUDED
17 #define AGG_GAMMA_LUT_INCLUDED
18 
19 #include <math.h>
20 #include "agg_basics.h"
21 
22 namespace agg
23 {
24     template<class LoResT=int8u,
25              class HiResT=int8u,
26              unsigned GammaShift=8,
27              unsigned HiResShift=8> class gamma_lut
28     {
29     public:
30         typedef gamma_lut<LoResT, HiResT, GammaShift, HiResShift> self_type;
31 
32         enum gamma_scale_e
33         {
34             gamma_shift = GammaShift,
35             gamma_size  = 1 << gamma_shift,
36             gamma_mask  = gamma_size - 1
37         };
38 
39         enum hi_res_scale_e
40         {
41             hi_res_shift = HiResShift,
42             hi_res_size  = 1 << hi_res_shift,
43             hi_res_mask  = hi_res_size - 1
44         };
45 
46         ~gamma_lut()
47         {
48             pod_allocator<LoResT>::deallocate(m_inv_gamma, hi_res_size);
49             pod_allocator<HiResT>::deallocate(m_dir_gamma, gamma_size);
50         }
51 
52         gamma_lut() :
53             m_gamma(1.0),
54             m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
55             m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
56         {
57             unsigned i;
58             for(i = 0; i < gamma_size; i++)
59             {
60                 m_dir_gamma[i] = HiResT(i << (hi_res_shift - gamma_shift));
61             }
62 
63             for(i = 0; i < hi_res_size; i++)
64             {
65                 m_inv_gamma[i] = LoResT(i >> (hi_res_shift - gamma_shift));
66             }
67         }
68 
69         gamma_lut(double g) :
70             m_gamma(1.0),
71             m_dir_gamma(pod_allocator<HiResT>::allocate(gamma_size)),
72             m_inv_gamma(pod_allocator<LoResT>::allocate(hi_res_size))
73         {
74             gamma(g);
75         }
76 
77         void gamma(double g)
78         {
79             m_gamma = g;
80 
81             unsigned i;
82             for(i = 0; i < gamma_size; i++)
83             {
84                 m_dir_gamma[i] = (HiResT)
85                     uround(pow(i / double(gamma_mask), m_gamma) * double(hi_res_mask));
86             }
87 
88             double inv_g = 1.0 / g;
89             for(i = 0; i < hi_res_size; i++)
90             {
91                 m_inv_gamma[i] = (LoResT)
92                     uround(pow(i / double(hi_res_mask), inv_g) * double(gamma_mask));
93             }
94         }
95 
96         double gamma() const
97         {
98             return m_gamma;
99         }
100 
101         HiResT dir(LoResT v) const
102         {
103             return m_dir_gamma[unsigned(v)];
104         }
105 
106         LoResT inv(HiResT v) const
107         {
108             return m_inv_gamma[unsigned(v)];
109         }
110 
111     private:
112         gamma_lut(const self_type&);
113         const self_type& operator = (const self_type&);
114 
115         double m_gamma;
116         HiResT* m_dir_gamma;
117         LoResT* m_inv_gamma;
118     };
119 }
120 
121 #endif
122