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