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 //#include <arpa/inet.h>
31 
32 #include "../../operations/gaussblur.hh"
33 #include "../../operations/hsl_mask.hh"
34 
35 #include "hue_saturation.hh"
36 
37 
38 
HueSaturationPar()39 PF::HueSaturationPar::HueSaturationPar():
40   OpParBase(),
41   hue("hue",this,0),
42   hue_eq("hue_eq",this,0),
43   saturation("saturation",this,0),
44   saturation_eq("saturation_eq",this,0),
45   contrast("contrast",this,0),
46   contrast_eq("contrast_eq",this,0),
47   brightness("brightness",this,0),
48   brightness_eq("brightness_eq",this,0),
49   gamma("gamma",this,0),
50   brightness_is_gamma("brightness_is_gamma",this,false),
51   hue_H_equalizer( "hue_H_equalizer", this ),
52   hue_S_equalizer( "hue_S_equalizer", this ),
53   hue_L_equalizer( "hue_L_equalizer", this ),
54   hue_H_equalizer_enabled( "hue_H_equalizer_enabled", this, false ),
55   hue_S_equalizer_enabled( "hue_S_equalizer_enabled", this, false ),
56   hue_L_equalizer_enabled( "hue_L_equalizer_enabled", this, false ),
57   saturation_H_equalizer( "saturation_H_equalizer", this ),
58   saturation_S_equalizer( "saturation_S_equalizer", this ),
59   saturation_L_equalizer( "saturation_L_equalizer", this ),
60   contrast_H_equalizer( "contrast_H_equalizer", this ),
61   contrast_S_equalizer( "contrast_S_equalizer", this ),
62   contrast_L_equalizer( "contrast_L_equalizer", this ),
63   brightness_H_equalizer( "brightness_H_equalizer", this ),
64   brightness_S_equalizer( "brightness_S_equalizer", this ),
65   brightness_L_equalizer( "brightness_L_equalizer", this ),
66   show_mask("show_mask",this,false),
67   invert_mask("invert_mask",this,false),
68   feather_mask("feather_mask",this,false),
69   feather_radius("feather_radius",this,5.0f)
70 {
71   set_type("hue_saturation" );
72 
73   set_default_name( _("basic adjustments") );
74 
75   mask = new_hsl_mask();
76   blur = new_gaussblur();
77 
78   int id = 0;
79   eq_vec[id++] = &hue_H_equalizer;
80   eq_vec[id++] = &hue_S_equalizer;
81   eq_vec[id++] = &hue_L_equalizer;
82 /*
83   eq_vec[id++] = &saturation_H_equalizer;
84   eq_vec[id++] = &saturation_S_equalizer;
85   eq_vec[id++] = &saturation_L_equalizer;
86   eq_vec[id++] = &contrast_H_equalizer;
87   eq_vec[id++] = &contrast_S_equalizer;
88   eq_vec[id++] = &contrast_L_equalizer;
89   eq_vec[id++] = &brightness_H_equalizer;
90   eq_vec[id++] = &brightness_S_equalizer;
91   eq_vec[id++] = &brightness_L_equalizer;
92 */
93 
94   hue_H_equalizer.get().set_circular( true );
95 
96   float x1 = 0, y1 = 1., x2 = 1, y2 = 1.;
97   for( id = 0; id < 3; id++ ) {
98     eq_vec[id]->get().set_point( 0, x1, y1 );
99     eq_vec[id]->get().set_point( 1, x2, y2 );
100     eq_vec[id]->store_default();
101   }
102   /*
103   for( id = 0; id < 3; id+=3 ) {
104     float x = 40;
105     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
106     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
107     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
108     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
109     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
110     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
111     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
112     eq_vec[id]->get().add_point( x/360, 0. ); x += 40;
113   }
114 */
115   x1 = 0; y1 = 0.5;
116   //eq_vec[0]->get().set_point( 0, x1, y1 );
117 }
118 
119 
120 
update_curve(PF::Property<PF::SplineCurve> * curve,float * vec)121 void PF::HueSaturationPar::update_curve( PF::Property<PF::SplineCurve>* curve, float* vec )
122 {
123   curve->get().lock();
124   //std::cout<<"CurvesPar::update_curve() called. # of points="<<curve.get().get_npoints()<<std::endl;std::cout.flush();
125   for(int i = 0; i <= 65535; i++) {
126     float x = ((float)i)/65535;
127     float y = curve->get().get_value( x );
128     if( y>1 ) y=1;
129     if( y<0 ) y=0;
130     vec[i] = y;
131     //std::cout<<"i="<<i<<"  x="<<x<<"  y="<<y<<"  vec8[i]="<<vec8[i]<<std::endl;
132   }
133   curve->get().unlock();
134 }
135 
136 
137 
build(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)138 VipsImage* PF::HueSaturationPar::build(std::vector<VipsImage*>& in, int first,
139         VipsImage* imap, VipsImage* omap,
140         unsigned int& level)
141 {
142   for( int id = 0; id < 3; id++ ) {
143     if( eq_vec[id]->is_modified() )
144       update_curve( eq_vec[id], vec[id] );
145     eq_enabled[id] = false;
146     //std::cout<<"eq_vec["<<id<<"]->get().get_npoints()="<<eq_vec[id]->get().get_npoints()<<std::endl;
147     //for( size_t pi = 0; pi < eq_vec[id]->get().get_npoints(); pi++ ) {
148       //std::cout<<"  get_point("<<pi<<").second="<<eq_vec[id]->get().get_point(pi).second<<std::endl;
149       //if( fabs(eq_vec[id]->get().get_point(pi).second) > 0.001 ) {
150         //eq_enabled[id] = true;
151         //break;
152       //}
153     //}
154   }
155   eq_enabled[0] = hue_H_equalizer_enabled.get();
156   eq_enabled[1] = hue_S_equalizer_enabled.get();
157   eq_enabled[2] = hue_L_equalizer_enabled.get();
158 
159   exponent = (gamma.get() >= 0.0f) ? 1.0f / (1.0f + gamma.get()*2.f) : (1.0f - gamma.get()*2.);
160 
161   std::vector<VipsImage*> in2;
162   if( in.size() < 1 )
163     return NULL;
164 
165   in2.push_back( in[0] );
166   PF::HSLMaskPar* mask_par = dynamic_cast<PF::HSLMaskPar*>( mask->get_par() );
167   PF::GaussBlurPar* blur_par = dynamic_cast<PF::GaussBlurPar*>( blur->get_par() );
168   if( mask_par ) {
169     std::vector<VipsImage*> in3; in3.push_back( in[0] );
170     mask_par->get_H_curve() = hue_H_equalizer;
171     mask_par->get_S_curve() = hue_S_equalizer;
172     mask_par->get_L_curve() = hue_L_equalizer;
173     mask_par->set_H_curve_enabled( hue_H_equalizer_enabled.get() );
174     mask_par->set_S_curve_enabled( hue_S_equalizer_enabled.get() );
175     mask_par->set_L_curve_enabled( hue_L_equalizer_enabled.get() );
176     mask_par->set_invert( get_invert_mask() );
177     mask_par->set_image_hints( in[0] );
178     mask_par->set_format( get_format() );
179     VipsImage* imask = mask_par->build( in3, 0, NULL, NULL, level );
180 
181     if( feather_mask.get() == true ) {
182       blur_par->set_radius( feather_radius.get() );
183       blur_par->set_image_hints( in[0] );
184       blur_par->set_format( get_format() );
185       in3.clear();
186       in3.push_back( imask );
187       VipsImage* blurred = blur_par->build( in3, 0, NULL, NULL, level );
188       std::cout<<"blurred = "<<blurred<<std::endl;
189       PF_UNREF( imask, "HueSaturationPar::build(): imask unref");
190       imask = blurred;
191     }
192 
193     in2.push_back( imask );
194   }
195 
196   VipsImage* out = PF::OpParBase::build( in2, 0, imap, omap, level );
197 
198   if( in2.size()>1 ) PF_UNREF( in2[1], "HueSaturationPar::build(): in[2] unref");
199 
200   return out;
201 }
202