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 
33 template<typename T, colorspace_t colorspace, int CHMIN, int CHMAX, bool has_omap>
34 class BlendColor: public BlendBase<T, colorspace, CHMIN, CHMAX, has_omap>
35 {
36   int pos, ch;
37 public:
set_icc_data(ICCProfile * d)38   void set_icc_data( ICCProfile* d ) { }
blend(const float &,T *,T * top,T * out,const int & x,int &)39   void blend(const float& , T* , T* top, T* out, const int& x, int& )
40   {
41     pos = x;
42     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
43       out[pos] = top[pos];
44     }
45   }
46 };
47 
48 
49 
50 /*
51   RGB colorspace
52  */
53 template<typename T, int CHMIN, int CHMAX>
54 class BlendColor<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false>:
55   public BlendBase<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false>
56 {
57   BlendLuminosity<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false> blend_lumi;
58   int pos, ch;
59   double temp_top;
60   double irgb[3], rgb[3];
61 public:
set_icc_data(ICCProfile * d)62   void set_icc_data( ICCProfile* d ) { blend_lumi.set_icc_data(d); }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)63   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
64   {
65     blend_lumi.blend( opacity, top, bottom, out, x, xomap );
66     return;
67 
68     // RGB values of the bottom layer
69     irgb[0] = (double(bottom[x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
70     irgb[1] = (double(bottom[x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
71     irgb[2] = (double(bottom[x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
72     // Luminance value of the bottom layer
73     double lumi = PF::luminance( irgb[0], irgb[1], irgb[2] );
74 
75     // RGB values of the top layer
76     double ored = (double(top[x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
77     double ogreen = (double(top[x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
78     double oblue = (double(top[x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
79 
80     // Color blend: the color of the top layer is mixed with
81     // the luminance of the bottom one
82     rgb[0] = ored; rgb[1] = ogreen; rgb[2] = oblue;
83     PF::lc_blend( rgb[0], rgb[1], rgb[2], lumi );
84 
85     pos = x;
86     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
87       out[pos] = (T)(( (rgb[ch]*opacity)+(irgb[ch]*(1.0f-opacity)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN);
88     }
89   }
90 };
91 
92 template<typename T, int CHMIN, int CHMAX>
93 class BlendColor<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, true>:
94   public BlendBase<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, true>
95 {
96   BlendColor<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false> blender;
97   float opacity_real;
98 public:
set_icc_data(ICCProfile * d)99   void set_icc_data( ICCProfile* d ) { blender.set_icc_data(d); }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)100   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
101   {
102     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
103     xomap += 1;
104     blender.blend( opacity_real, bottom, top, out, x, xomap );
105   }
106 };
107 
108 
109 
110 
111 /*
112   Lab colorspace
113  */
114 template<typename T, int CHMIN, int CHMAX>
115 class BlendColor<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false>:
116   public BlendBase<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false>
117 {
118   int pos, ch;
119   double temp_top;
120   double rgb[3];
121 public:
set_icc_data(ICCProfile * d)122   void set_icc_data( ICCProfile* d ) { }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)123   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
124   {
125     pos = x;
126     for( ch=CHMIN; ch<=0; ch++, pos++ )
127       out[pos] = bottom[pos];
128     for( ; ch<=CHMAX; ch++, pos++ )
129       out[pos] = static_cast<T>( opacity*top[pos]+(1.0f-opacity)*bottom[pos] );
130   }
131 };
132 
133 template<typename T, int CHMIN, int CHMAX>
134 class BlendColor<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, true>:
135   public BlendBase<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, true>
136 {
137   BlendColor<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false> blender;
138   float opacity_real;
139 public:
set_icc_data(ICCProfile * d)140   void set_icc_data( ICCProfile* d ) { }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)141   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
142   {
143     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
144     xomap += 1;
145     blender.blend( opacity_real, bottom, top, out, x, xomap );
146   }
147 };
148 
149 
150