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