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