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 <sys/types.h>
31 #include <sys/stat.h>
32 #include <fcntl.h>
33 
34 #include "convert_colorspace.hh"
35 #include "icc_transform.hh"
36 #include "gaussblur.hh"
37 #include "guided_filter.hh"
38 #include "shadows_highlights.hh"
39 
40 
ShadowsHighlightsPar()41 PF::ShadowsHighlightsPar::ShadowsHighlightsPar():
42 OpParBase(),
43 method("method",this,PF::SHAHI_GAUSSIAN,"SHAHI_GAUSSIAN","gaussian"),
44 shadows("shadows",this,50),
45 highlights("highlights",this,-50),
46 wp_adjustment("wp_adjustment",this,0),
47 radius("radius",this,100),
48 threshold("threshold",this,0.075),
49 compress("compress",this,50),
50 sh_color_adjustment("sh_color_adjustment",this,100),
51 hi_color_adjustment("hi_color_adjustment",this,50),
52 in_profile( NULL )
53 {
54   method.add_enum_value(PF::SHAHI_GUIDED,"SHAHI_GUIDED","guided");
55 
56   gauss = new_gaussblur();
57   guided = new_guided_filter();
58   convert2lab = PF::new_convert_colorspace();
59   PF::ConvertColorspacePar* csconvpar = dynamic_cast<PF::ConvertColorspacePar*>(convert2lab->get_par());
60   if(csconvpar) {
61     csconvpar->set_out_profile_mode( PF::PROF_MODE_DEFAULT );
62     csconvpar->set_out_profile_type( PF::PROF_TYPE_LAB );
63   }
64   convert2input = new_icc_transform();
65 
66   set_type("shadows_highlights" );
67 
68   set_default_name( _("shadows/highlights") );
69 }
70 
71 
needs_caching()72 bool PF::ShadowsHighlightsPar::needs_caching()
73 {
74   return true;
75 }
76 
77 
78 
propagate_settings()79 void PF::ShadowsHighlightsPar::propagate_settings()
80 {
81   GaussBlurPar* gausspar = dynamic_cast<GaussBlurPar*>( gauss->get_par() );
82   if( gausspar ) {
83     gausspar->set_radius( radius.get() );
84     gausspar->propagate_settings();
85   }
86 
87   PF::GuidedFilterPar* guidedpar = dynamic_cast<PF::GuidedFilterPar*>( guided->get_par() );
88   if( guidedpar ) {
89     //float ss = 0.01 * guided_radius.get() * MIN(full_res->Xsize, full_res->Ysize);
90     //guidedpar->set_radius(ss);
91     //guidedpar->set_threshold(guided_threshold.get());
92     guidedpar->propagate_settings();
93   }
94 }
95 
96 
compute_padding(VipsImage * full_res,unsigned int id,unsigned int level)97 void PF::ShadowsHighlightsPar::compute_padding( VipsImage* full_res, unsigned int id, unsigned int level )
98 {
99   std::cout<<"ShadowsHighlightsPar::compute_padding(): method.get_enum_value().first="<<method.get_enum_value().first<<std::endl;
100   switch( method.get_enum_value().first ) {
101   case PF::SHAHI_GAUSSIAN: {
102     GaussBlurPar* gausspar = dynamic_cast<GaussBlurPar*>( gauss->get_par() );
103     if( gausspar ) {
104       gausspar->set_radius( radius.get() );
105       gausspar->propagate_settings();
106       gausspar->compute_padding(full_res, id, level);
107       set_padding( gausspar->get_padding(id), id );
108     }
109     break;
110   }
111   case PF::SHAHI_GUIDED: {
112     PF::GuidedFilterPar* guidedpar = dynamic_cast<PF::GuidedFilterPar*>( guided->get_par() );
113     if( guidedpar ) {
114       guidedpar->set_radius( radius.get() );
115       //guidedpar->set_threshold(threshold.get());
116       guidedpar->propagate_settings();
117       guidedpar->compute_padding(full_res, id, level);
118       set_padding( guidedpar->get_padding(id), id );
119     }
120 
121   }
122   default: break;
123   }
124 }
125 
126 
127 
128 
build(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)129 VipsImage* PF::ShadowsHighlightsPar::build(std::vector<VipsImage*>& in, int first,
130     VipsImage* imap, VipsImage* omap,
131     unsigned int& level)
132 {
133   if( (in.size()<1) || (in[0]==NULL) )
134     return NULL;
135 
136   std::vector<VipsImage*> in2;
137 
138   in_profile = PF::get_icc_profile( in[0] );
139 
140   convert2lab->get_par()->set_image_hints( in[0] );
141   convert2lab->get_par()->set_format( get_format() );
142   in2.clear(); in2.push_back( in[0] );
143   VipsImage* labimg = convert2lab->get_par()->build( in2, 0, NULL, NULL, level );
144   if( !labimg ) {
145     std::cout<<"ShadowsHighlightsPar::build(): null Lab image"<<std::endl;
146     PF_REF( in[0], "ShadowsHighlightsPar::build(): null Lab image" );
147     return in[0];
148   }
149   //std::cout<<"srcimg->Xsize="<<srcimg->Xsize<<"  extended->Xsize="<<extended->Xsize<<std::endl;
150 
151 
152   VipsImage* out = NULL;
153   VipsImage* blurred = NULL;
154   switch( method.get_enum_value().first ) {
155   case PF::SHAHI_GAUSSIAN: {
156     GaussBlurPar* gausspar = dynamic_cast<GaussBlurPar*>( gauss->get_par() );
157     if( gausspar ) {
158       gausspar->set_radius( radius.get() );
159       gausspar->set_image_hints( labimg );
160       gausspar->set_format( get_format() );
161       in2.clear(); in2.push_back( labimg );
162       blurred = gausspar->build( in2, 0, NULL, NULL, level );
163       PF_UNREF( labimg, "ShadowsHighlightsPar::build(): extended unref after convert2lab" );
164     }
165     break;
166   }
167   case PF::SHAHI_GUIDED: {
168     PF::GuidedFilterPar* guidedpar = dynamic_cast<PF::GuidedFilterPar*>( guided->get_par() );
169     if( guidedpar ) {
170       guidedpar->set_radius( radius.get() );
171       //guidedpar->set_threshold(threshold.get());
172       guidedpar->set_image_hints( labimg );
173       guidedpar->set_format( get_format() );
174       in2.clear(); in2.push_back( labimg );
175       blurred = guidedpar->build( in2, 0, NULL, NULL, level );
176       PF_UNREF( labimg, "ShadowsHighlightsPar::build(): extended unref after convert2lab" );
177     }
178     break;
179   }
180   default:
181     break;
182   }
183 
184   if( !blurred ) {
185     std::cout<<"ShadowsHighlightsPar::build(): null Lab image"<<std::endl;
186     PF_REF( in[0], "ShadowsHighlightsPar::build(): null Lab image" );
187     return in[0];
188   }
189 
190   in2.clear();
191   in2.push_back(blurred);
192   in2.push_back(labimg);
193   VipsImage* shahi = OpParBase::build( in2, 0, imap, omap, level );
194   //PF_UNREF( labimg, "ShadowsHighlightsPar::update() labimg unref" );
195   PF_UNREF( blurred, "ShadowsHighlightsPar::build() blurred unref" );
196 
197   PF::ICCTransformPar* icc_par = dynamic_cast<PF::ICCTransformPar*>( convert2input->get_par() );
198   //std::cout<<"ImageArea::update(): icc_par="<<icc_par<<std::endl;
199   if( icc_par ) {
200     //std::cout<<"ImageArea::update(): setting display profile: "<<current_display_profile<<std::endl;
201     icc_par->set_out_profile( in_profile );
202   }
203   convert2input->get_par()->set_image_hints( in[0] );
204   convert2input->get_par()->set_format( get_format() );
205   in2.clear(); in2.push_back( shahi );
206 #ifndef NDEBUG
207   std::cout<<"ShadowsHighlightsPar::build(): calling convert2input->get_par()->build()"<<std::endl;
208 #endif
209   out = convert2input->get_par()->build(in2, 0, NULL, NULL, level );
210   PF_UNREF( shahi, "ShadowsHighlightsPar::build() cropped unref" );
211 
212 
213   set_image_hints( in[0] );
214 
215   return out;
216 }
217