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 BlendLuminance: public BlendBase<T, colorspace, CHMIN, CHMAX, has_omap>
35 {
36   int pos, ch;
37   ICCProfile* data;
38 public:
set_icc_data(ICCProfile * d)39   void set_icc_data( ICCProfile* d ) { data = d; }
blend(const float &,T *,T * top,T * out,const int & x,int &)40   void blend(const float& , T* , T* top, T* out, const int& x, int& )
41   {
42     pos = x;
43     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
44       out[pos] = top[pos];
45     }
46   }
47 };
48 
49 
50 
51 /*
52   RGB colorspace
53  */
54 template<typename T, int CHMIN, int CHMAX>
55 class BlendLuminance<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false>:
56   public BlendBase<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false>
57 {
58   int pos, ch;
59   float temp_top, temp_out;
60   float irgb[3];
61   float rgb[3];
62   ICCProfile* data;
63 public:
set_icc_data(ICCProfile * d)64   void set_icc_data( ICCProfile* d ) { data = d; }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)65   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
66   {
67     //std::cout<<"BlendLuminance: data="<<data<<std::endl;
68     if( !data ) {
69       pos = x;
70       for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
71         out[pos] = top[pos];
72       }
73       return;
74     }
75 
76     //std::cout<<"BlendLuminance: data->trc_type="<<data->trc_type<<std::endl;
77 
78     // RGB values of the bottom layer
79     irgb[0] = (float(bottom[x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
80     irgb[1] = (float(bottom[x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
81     irgb[2] = (float(bottom[x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
82 
83     // RGB values of the top layer
84     float ored = (float(top[x]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
85     float ogreen = (float(top[x+1]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
86     float oblue = (float(top[x+2]) + FormatInfo<T>::MIN)/FormatInfo<T>::RANGE;
87 
88     if( data->get_trc_type()!=PF_TRC_LINEAR ) {
89       //std::cout<<"BlendLuminance: perceptual -> linear: "<<irgb[0]<<" -> "<<data->perceptual_trc_vec[ (int)(irgb[0]*65535) ]<<std::endl;
90       // RGB values are encoded perceptually
91       irgb[0] = data->perceptual2linear( irgb[0] );
92       irgb[1] = data->perceptual2linear( irgb[1] );
93       irgb[2] = data->perceptual2linear( irgb[2] );
94       ored = data->perceptual2linear( ored );
95       ogreen = data->perceptual2linear( ogreen );
96       oblue = data->perceptual2linear( oblue );
97 
98       //irgb[0] = data->perceptual_trc_vec[ (int)(irgb[0]*65535) ];
99       //irgb[1] = data->perceptual_trc_vec[ (int)(irgb[1]*65535) ];
100       //irgb[2] = data->perceptual_trc_vec[ (int)(irgb[2]*65535) ];
101       //ored = data->perceptual_trc_vec[ (int)(ored*65535) ];
102       //ogreen = data->perceptual_trc_vec[ (int)(ogreen*65535) ];
103       //oblue = data->perceptual_trc_vec[ (int)(oblue*65535) ];
104 
105       //irgb[0] = cmsEvalToneCurveFloat( data->perceptual_trc, irgb[0] );
106       //irgb[1] = cmsEvalToneCurveFloat( data->perceptual_trc, irgb[0] );
107       //irgb[2] = cmsEvalToneCurveFloat( data->perceptual_trc, irgb[0] );
108     }
109 
110     float iL = data->get_luminance( irgb[0], irgb[1], irgb[2] );
111     float oL = data->get_luminance( ored, ogreen, oblue );
112     //float r = oL / MAX(iL, 0.0000000000000000001);
113     float r = oL / MAX(iL, FLT_MIN);
114 
115     rgb[0] = irgb[0] * r;
116     rgb[1] = irgb[1] * r;
117     rgb[2] = irgb[2] * r;
118 
119     //if(x==0) std::cout<<"ired="<<irgb[0]<<"  ored="<<ored<<"  data->Y_R="<<data->Y_R<<"  r="<<r<<"  rgb[0]="<<rgb[0]<<std::endl;
120 
121     pos = x;
122     for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
123       //temp_out = (T)(( (rgb[ch]*opacity)+(irgb[ch]*(1.0f-opacity)) )*FormatInfo<T>::RANGE - FormatInfo<T>::MIN);
124       temp_out = (rgb[ch]*opacity)+(irgb[ch]*(1.0f-opacity));
125       //if( temp_out<0 ) temp_out = 0;
126       //if( temp_out>1 ) temp_out = 1;
127       if( data->get_trc_type()!=PF_TRC_LINEAR ) {
128         temp_out = data->linear2perceptual( temp_out );
129         //temp_out = data->perceptual_trc_inv_vec[ (int)(temp_out*65535) ];
130       }
131       out[pos] = (T)(temp_out*FormatInfo<T>::RANGE - FormatInfo<T>::MIN);
132     }
133   }
134 };
135 
136 template<typename T, int CHMIN, int CHMAX>
137 class BlendLuminance<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, true>:
138   public BlendBase<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, true>
139 {
140   BlendLuminance<T, PF_COLORSPACE_RGB, CHMIN, CHMAX, false> blender;
141   float opacity_real;
142   ICCProfile* data;
143 public:
set_icc_data(ICCProfile * d)144   void set_icc_data( ICCProfile* d ) { data = d; blender.set_icc_data(data); }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)145   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
146   {
147     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
148     xomap += 1;
149     blender.blend( opacity_real, bottom, top, out, x, xomap );
150   }
151 };
152 
153 
154 
155 
156 /*
157   Lab colorspace
158  */
159 template<typename T, int CHMIN, int CHMAX>
160 class BlendLuminance<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false>:
161   public BlendBase<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false>
162 {
163   int pos, ch;
164   double temp_top;
165   double rgb[3];
166   ICCProfile* data;
167 public:
set_icc_data(ICCProfile * d)168   void set_icc_data( ICCProfile* d ) { data = d; }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)169   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
170   {
171     pos = x;
172     for( ch=CHMIN; ch<=0; ch++, pos++ )
173       out[pos] = static_cast<T>( opacity*top[pos]+(1.0f-opacity)*bottom[pos] );
174     for( ; ch<=CHMAX; ch++, pos++ )
175       out[pos] = bottom[pos];
176   }
177 };
178 
179 template<typename T, int CHMIN, int CHMAX>
180 class BlendLuminance<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, true>:
181   public BlendBase<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, true>
182 {
183   BlendLuminance<T, PF_COLORSPACE_LAB, CHMIN, CHMAX, false> blender;
184   float opacity_real;
185   ICCProfile* data;
186 public:
set_icc_data(ICCProfile * d)187   void set_icc_data( ICCProfile* d ) { data = d; blender.set_icc_data(data); }
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)188   void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
189   {
190     float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
191     xomap += 1;
192     blender.blend( opacity_real, bottom, top, out, x, xomap );
193   }
194 };
195 
196 
197