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 BlendNormal: 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 /*
42   Greyscale colorspace
43  */
44 template<typename T, int CHMIN, int CHMAX>
45 class BlendNormal<T, PF_COLORSPACE_GRAYSCALE, CHMIN, CHMAX, false>:
46   public BlendBase<T, PF_COLORSPACE_GRAYSCALE, CHMIN, CHMAX, false>
47 {
48 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)49   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
50   {
51     out[x] = (T)(opacity*top[x] + (1.0f-opacity)*bottom[x]);
52   }
53 };
54 
55 template<typename T, int CHMIN, int CHMAX>
56 class BlendNormal<T, PF_COLORSPACE_GRAYSCALE, CHMIN, CHMAX, true>:
57   public BlendBase<T, PF_COLORSPACE_GRAYSCALE, CHMIN, CHMAX, true>
58 {
59 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)60   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
61   {
62     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
63     xomap += 1;
64     out[x] = (T)(opacity_real*top[x] + (1.0f-opacity_real)*bottom[x]);
65   }
66 };
67 
68 
69 /*
70   RGB colorspace
71  */
72 template<typename T, int CHMIN, int CHMAX>
73 class BlendNormal<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false>:
74   public BlendBase<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false>
75 {
76   int ch, pos;
77 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)78   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
79   {
80     pos = x;
81     // The target channel(s) get blended
82     //std::cout<<"x: "<<x<<"  opacity: "<<opacity<<std::endl;
83     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
84       //std::cout<<"pos: "<<pos<<"  bottom: "<<(int)bottom[pos]<<"  top: "<<(int)top[pos];
85       out[pos] = (T)(opacity*top[pos] + (1.0f-opacity)*bottom[pos]);
86       //std::cout<<"  out: "<<(int)out[pos]<<std::endl;
87     }
88 
89     /*
90     int i = x;
91     //std::cout<<"  in: "<<(int)in[i]<<"  out: "<<(int)out[i]<<std::endl;
92     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
93     //std::cout<<"  in: "<<(int)in[i]<<"  out: "<<(int)out[i]<<std::endl;
94     i++;
95     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
96     i++;
97     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
98     */
99   }
100 };
101 
102 template<typename T, int CHMIN, int CHMAX>
103 class BlendNormal<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, true>:
104   public BlendBase<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, true>
105 {
106   int ch, pos;
107 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)108   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
109   {
110     //int i = x;
111     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
112     xomap += 1;
113 
114     pos = x;
115     // The target channel(s) get blended
116     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ )
117       out[pos] = (T)(opacity_real*top[pos] + (1.0f-opacity_real)*bottom[pos]);
118 
119     /*
120     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
121     i += 1;
122     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
123     i += 1;
124     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
125     */
126   }
127 };
128 
129 
130 /*
131   LAB colorspace
132  */
133 template<typename T, int CHMIN, int CHMAX>
134 class BlendNormal<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false>:
135   public BlendBase<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false>
136 {
137   int ch, pos;
138 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)139   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
140   {
141     pos = x;
142     // The target channel(s) get blended
143     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ )
144       out[pos] = (T)(opacity*top[pos] + (1.0f-opacity)*bottom[pos]);
145 
146     /*
147     int i = x;
148     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
149     i++;
150     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
151     i++;
152     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
153     */
154   }
155 };
156 
157 template<typename T, int CHMIN, int CHMAX>
158 class BlendNormal<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, true>:
159   public BlendBase<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, true>
160 {
161   int ch, pos;
162 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)163   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
164   {
165     //int i = x;
166     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
167     xomap += 1;
168 
169     pos = x;
170     // The target channel(s) get blended
171     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ )
172       out[pos] = (T)(opacity_real*top[pos] + (1.0f-opacity_real)*bottom[pos]);
173 
174     /*
175     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
176     i += 1;
177     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
178     i += 1;
179     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
180     */
181   }
182 };
183 
184 
185 /*
186   CMYK colorspace
187  */
188 template<typename T, int CHMIN, int CHMAX>
189 class BlendNormal<T, PF_COLORSPACE_CMYK, CHMIN, CHMAX, false>:
190   public BlendBase<T, PF_COLORSPACE_CMYK, CHMIN, CHMAX, false>
191 {
192   int ch, pos;
193 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)194   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
195   {
196     pos = x;
197     // The target channel(s) get blended
198     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ )
199       out[pos] = (T)(opacity*top[pos] + (1.0f-opacity)*bottom[pos]);
200 
201     /*
202     int i = x;
203     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
204     i++;
205     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
206     i++;
207     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
208     i++;
209     out[i] = (T)(opacity*out[i] + (1.0f-opacity)*in[i]);
210     */
211   }
212 };
213 
214 template<typename T, int CHMIN, int CHMAX>
215 class BlendNormal<T, PF_COLORSPACE_CMYK, CHMIN, CHMAX, true>:
216   public BlendBase<T, PF_COLORSPACE_CMYK, CHMIN, CHMAX, true>
217 {
218   int ch, pos;
219 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)220   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
221   {
222     //int i = x;
223     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
224     xomap += 1;
225 
226     pos = x;
227     // The target channel(s) get blended
228     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ )
229       out[pos] = (T)(opacity_real*top[pos] + (1.0f-opacity_real)*bottom[pos]);
230 
231     /*
232     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
233     i += 1;
234     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
235     i += 1;
236     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
237     i += 1;
238     out[i] = (T)(opacity_real*out[i] + (1.0f-opacity_real)*in[i]);
239     */
240   }
241 };
242