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 //#include "vivid_light.hh"
32
33
color_burn(float bottom,float top)34 static float color_burn(float bottom, float top)
35 {
36 if( top == 0 ) return 0;
37 float result = 1.0f - ((1.0f - bottom) / top);
38 //float result = 1;
39 return( (result<0) ? 0 : result );
40 }
41
42
color_dodge(float bottom,float top)43 static float color_dodge(float bottom, float top)
44 {
45 if( top == 1 ) return 0;
46 float result = bottom / (1.0f-top);
47 return( (result>1) ? 1 : result );
48 }
49
50
51
52 template<typename T, colorspace_t colorspace, int CHMIN, int CHMAX, bool has_omap>
53 class BlendVividLight: public BlendBase<T, colorspace, CHMIN, CHMAX, has_omap>
54 {
55 public:
blend(const float &,T *,T *,T *,const int &,int &)56 void blend(const float& /*opacity*/, T* /*bottom*/, T* /*top*/,
57 T* /*out*/, const int& /*x*/, int& /*xomap*/) {}
58 };
59
60
61 float vivid_light_f(float nbottom, float ntop);
62
63
64
65 /*
66 Default
67 */
68 template<typename T, colorspace_t CS, int CHMIN, int CHMAX>
69 class BlendVividLight<T, CS, CHMIN, CHMAX, false>:
70 public BlendBase<T, CS, CHMIN, CHMAX, false>
71 {
72 int ch, pos;
73 T ibottom;
74 typename FormatInfo<T>::PROMOTED ptop, pbottom, vivid;
75 float ntop, nbottom, nvivid;
76 typename FormatInfo<T>::PROMOTED psum;
77 public:
BlendVividLight()78 BlendVividLight(): BlendBase<T, CS, CHMIN, CHMAX, false>(), psum(FormatInfo<T>::MAX + FormatInfo<T>::MIN) {}
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int &)79 void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& /*xomap*/)
80 {
81 #ifdef DO_WARNINGS
82 #warning "TODO: optimize vivid light blend"
83 #warning "TODO: handle vivid light blend for Lab and CMYK"
84 #endif
85 pos = x;
86 psum = FormatInfo<T>::MAX + FormatInfo<T>::MIN;
87 for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
88 ptop = top[pos]; pbottom = bottom[pos];
89 ntop = ( ((float)top[pos])+FormatInfo<T>::MIN )/FormatInfo<T>::RANGE;
90 nbottom = ( ((float)bottom[pos])+FormatInfo<T>::MIN )/FormatInfo<T>::RANGE;
91 if( ntop <= 0.5 )
92 //vivid = (ptop*FormatInfo<T>::RANGE / (FormatInfo<T>::RANGE-pbottom*2));
93 //result = ((top==0) ? 0 : 1.0f – (1.0f – bottom) / (top*2.0f));
94 //result = ((top==0) ? 0 : 1.0f – (1.0f – bottom) / (top*2.0f));
95 //nvivid = ((ntop==0) ? 0 : 1.0f - (1.0f - nbottom) / (ntop*2.0f));
96 nvivid = color_burn( nbottom, ntop*2.0f );
97 else
98 //vivid = (FormatInfo<T>::RANGE - (FormatInfo<T>::RANGE-ptop) / (2*(pbottom-FormatInfo<T>::HALF)));
99 //nvivid = ((ntop==1) ? 1 : nbottom / (2.0f*(1.0f-ntop))); // b/(1-(2t-1)) = b/(1-2t+1) = b/(2-2t) = b/(2*(1-t))
100 nvivid = color_dodge( nbottom, ntop*2.0f-1.0f );
101 //nvivid = PF::vivid_light( ntop, nbottom );
102 vivid_light_f(nbottom,ntop);
103 if( nvivid < 0 ) nvivid = 0;
104 if( nvivid > 1 ) nvivid = 1;
105 vivid = (typename FormatInfo<T>::PROMOTED)(nvivid * FormatInfo<T>::RANGE - FormatInfo<T>::MIN);
106 clip( opacity*vivid + (1.0f-opacity)*bottom[pos], out[pos] );
107 }
108 }
109 };
110
111 template<typename T, colorspace_t CS, int CHMIN, int CHMAX>
112 class BlendVividLight<T, CS, CHMIN, CHMAX, true>:
113 public BlendBase<T, CS, CHMIN, CHMAX, true>
114 {
115 int ch, pos;
116 T ibottom;
117 typename FormatInfo<T>::PROMOTED ptop, pbottom, vivid;
118 typename FormatInfo<T>::PROMOTED psum;
119 public:
blend(const float & opacity,T * bottom,T * top,T * out,const int & x,int & xomap)120 void blend(const float& opacity, T* bottom, T* top, T* out, const int& x, int& xomap)
121 {
122 //int i = x;
123 float opacity_real = opacity*(this->pmap[xomap]+FormatInfo<T>::MIN)/(FormatInfo<T>::RANGE);
124 xomap += 1;
125
126 pos = x;
127 psum = FormatInfo<T>::MAX + FormatInfo<T>::MIN;
128 for( ch=CHMIN; ch<=CHMAX; ch++, pos++ ) {
129 ptop = top[pos]; pbottom = bottom[pos];
130 if( bottom[pos] <= FormatInfo<T>::HALF )
131 vivid = (ptop*FormatInfo<T>::RANGE / (FormatInfo<T>::RANGE-pbottom*2));
132 else
133 vivid = (FormatInfo<T>::RANGE - (FormatInfo<T>::RANGE-ptop) / (2*(pbottom-FormatInfo<T>::HALF)));
134 clip( opacity_real*vivid + (1.0f-opacity_real)*bottom[pos], out[pos] );
135 }
136 }
137 };
138