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