1 /*
2  */
3 
4 /*
5 
6     Copyright (C) 2014 Ferrero Andrea
7 
8     This program is free software: you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation, either version 3 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License
19     along with this program. If not, see <http://www.gnu.org/licenses/>.
20 
21 
22  */
23 
24 /*
25 
26     These files are distributed with PhotoFlow - http://aferrero2707.github.io/PhotoFlow/
27 
28  */
29 
30 
31 
32 template<typename T, colorspace_t colorspace, int CHMIN, int CHMAX, bool has_omap>
33 class BlendOverlay: public BlendBase<T, colorspace, CHMIN, CHMAX, has_omap>
34 {
35 public:
blend(const float &,T *,T *,T *,const int &,int &)36   void blend(const float& /*opacity*/, T* /*bottom*/, T* /*top*/,
37       T* /*out*/, const int& /*x*/, int& /*xomap*/) {}
38 };
39 
40 
41 template<typename T, colorspace_t CS, int CHMIN, int CHMAX>
42 class BlendOverlay<T, CS, CHMIN, CHMAX, false>:
43 public BlendBase<T, CS, CHMIN, CHMAX, false>
44 {
45   int ch, pos;
46   T ibottom;
47   typename FormatInfo<T>::PROMOTED ptop, overlay;
48   typename FormatInfo<T>::PROMOTED psum;
49 public:
BlendOverlay()50   BlendOverlay(): BlendBase<T, CS, CHMIN, CHMAX, false>(), psum(FormatInfo<T>::MAX + FormatInfo<T>::MIN) {}
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)51   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
52   {
53     pos = x;
54     //psum = FormatInfo<T>::MAX + FormatInfo<T>::MIN;
55     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
56       if( bottom[pos] < FormatInfo<T>::HALF )
57         overlay = (((typename FormatInfo<T>::PROMOTED)top[pos])*bottom[pos]/FormatInfo<T>::MAX)*2;
58       else
59         overlay = psum - ((psum-top[pos])*(psum-bottom[pos])/FormatInfo<T>::RANGE)*2;
60 
61       clip( opacity*overlay + (1.0f-opacity)*bottom[pos], out[pos] );
62     }
63   }
64 };
65 
66 template<typename T, colorspace_t CS, int CHMIN, int CHMAX>
67 class BlendOverlay<T, CS, CHMIN, CHMAX, true>:
68 public BlendBase<T, CS, CHMIN, CHMAX, true>
69 {
70   int ch, pos;
71   T ibottom;
72   typename FormatInfo<T>::PROMOTED ptop, overlay;
73   typename FormatInfo<T>::PROMOTED psum;
74   float opacity_real;
75 public:
BlendOverlay()76   BlendOverlay(): BlendBase<T, CS, CHMIN, CHMAX, true>(), psum(FormatInfo<T>::MAX + FormatInfo<T>::MIN) {}
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)77   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
78   {
79     //int i = x;
80     opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
81     xomap += 1;
82 
83     pos = x;
84     //psum = FormatInfo<T>::MAX + FormatInfo<T>::MIN;
85     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
86       if( bottom[pos] < FormatInfo<T>::HALF )
87         overlay = (((typename FormatInfo<T>::PROMOTED)top[pos])*bottom[pos]/FormatInfo<T>::MAX)*2;
88       else
89         overlay = psum - ((psum-top[pos])*(psum-bottom[pos])/FormatInfo<T>::RANGE)*2;
90       clip( opacity_real*overlay + (1.0f-opacity_real)*bottom[pos], out[pos] );
91     }
92   }
93 };
94 
95 
96 
97 
98 
99 
100 /**
101  * Overlay blend implemented using GIMP definition:
102  *
103  * gimp_composite_overlay_any_any_any_generic:
104  * @ctx: The compositing context.
105  *
106  * Perform an RGB[A] overlay operation between the pixel sources
107  * ctx->A and ctx->B, using the generalised algorithm:
108  *
109  * D =  A * (A + (2 * B) * (255 - A))
110  *
111  **/
112 template<typename T, colorspace_t colorspace, int CHMIN, int CHMAX, bool has_omap>
113 class BlendOverlayGimp: public BlendBase<T, colorspace, CHMIN, CHMAX, has_omap>
114 {
115 public:
blend(const float &,T *,T *,T *,const int &,int &)116   void blend(const float& /*opacity*/, T* /*bottom*/, T* /*top*/,
117       T* /*out*/, const int& /*x*/, int& /*xomap*/) {}
118 };
119 
120 
121 template<typename T, colorspace_t CS, int CHMIN, int CHMAX>
122 class BlendOverlayGimp<T, CS, CHMIN, CHMAX, false>:
123 public BlendBase<T, CS, CHMIN, CHMAX, false>
124 {
125   int ch, pos;
126   T ibottom;
127   typename FormatInfo<T>::PROMOTED ptop, overlay;
128   typename FormatInfo<T>::PROMOTED psum;
129   float nbottom, ntop, noverlay;
130 public:
BlendOverlayGimp()131   BlendOverlayGimp(): BlendBase<T, CS, CHMIN, CHMAX, false>(), psum(FormatInfo<T>::MAX + FormatInfo<T>::MIN) {}
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)132   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
133   {
134     pos = x;
135     //psum = FormatInfo<T>::MAX + FormatInfo<T>::MIN;
136     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
137       ntop = ( ((float)top[pos])+FormatInfo<T>::MIN )/FormatInfo<T>::RANGE;
138       nbottom = ( ((float)bottom[pos])+FormatInfo<T>::MIN )/FormatInfo<T>::RANGE;
139       noverlay = nbottom * (nbottom + (ntop*2.0f)*(1.0f-nbottom));
140       overlay = (typename FormatInfo<T>::PROMOTED)(noverlay * FormatInfo<T>::RANGE - FormatInfo<T>::MIN);
141       clip( opacity*overlay + (1.0f-opacity)*bottom[pos], out[pos] );
142     }
143   }
144 };
145 
146 template<typename T, colorspace_t CS, int CHMIN, int CHMAX>
147 class BlendOverlayGimp<T, CS, CHMIN, CHMAX, true>:
148 public BlendBase<T, CS, CHMIN, CHMAX, true>
149 {
150   int ch, pos;
151   T ibottom;
152   typename FormatInfo<T>::PROMOTED ptop, overlay;
153   typename FormatInfo<T>::PROMOTED psum;
154   float nbottom, ntop, noverlay;
155   float opacity_real;
156 public:
BlendOverlayGimp()157   BlendOverlayGimp(): BlendBase<T, CS, CHMIN, CHMAX, true>(), psum(FormatInfo<T>::MAX + FormatInfo<T>::MIN) {}
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)158   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
159   {
160     //int i = x;
161     opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
162     xomap += 1;
163 
164     pos = x;
165     //psum = FormatInfo<T>::MAX + FormatInfo<T>::MIN;
166     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
167       ntop = ( ((float)top[pos])+FormatInfo<T>::MIN )/FormatInfo<T>::RANGE;
168       nbottom = ( ((float)bottom[pos])+FormatInfo<T>::MIN )/FormatInfo<T>::RANGE;
169       noverlay = nbottom * (nbottom + (ntop*2.0f)*(1.0f-nbottom));
170       overlay = (typename FormatInfo<T>::PROMOTED)(noverlay * FormatInfo<T>::RANGE - FormatInfo<T>::MIN);
171       clip( opacity_real*overlay + (1.0f-opacity_real)*bottom[pos], out[pos] );
172     }
173   }
174 };
175