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 <vips/cimg_funcs.h>
31 
32 #include "../base/new_operation.hh"
33 #include "convert_colorspace.hh"
34 #include "icc_transform.hh"
35 #include "../operations/impulse_nr.hh"
36 #include "../operations/nlmeans.hh"
37 #include "denoise.hh"
38 
39 
DenoisePar()40 PF::DenoisePar::DenoisePar():
41   OpParBase(),
42   impulse_nr_enable("impulse_nr_enable",this,false),
43   impulse_nr_threshold("impulse_nr_threshold",this,50),
44   nlmeans_enable("nlmeans_enable",this,false),
45   nlmeans_radius("nlmeans_radius",this,2),
46   nlmeans_strength("nlmeans_strength",this,50),
47   nlmeans_luma_frac("nlmeans_luma_frac",this,0.5),
48   nlmeans_chroma_frac("nlmeans_chroma_frac",this,1),
49   iterations("iterations",this,1),
50   amplitude("amplitude",this,100),
51   sharpness("sharpness",this,0.9),
52   anisotropy("anisotropy",this,0.15),
53   alpha("alpha",this,0.6),
54   sigma("sigma",this,1.1),
55 	nr_mode("nr_mode",this,PF_NR_ANIBLUR,"ANIBLUR","Anisotropic Blur (G'Mic)")
56 {
57   convert2lab = PF::new_convert_colorspace();
58   PF::ConvertColorspacePar* csconvpar = dynamic_cast<PF::ConvertColorspacePar*>(convert2lab->get_par());
59   if(csconvpar) {
60     csconvpar->set_out_profile_mode( PF::PROF_MODE_DEFAULT );
61     csconvpar->set_out_profile_type( PF::PROF_TYPE_LAB );
62   }
63   convert2input = new_icc_transform();
64   impulse_nr = PF::new_impulse_nr();
65   nlmeans = PF::new_nlmeans();
66   set_type( "denoise" );
67 
68   set_default_name( _("noise reduction") );
69 }
70 
71 
72 
build(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)73 VipsImage* PF::DenoisePar::build(std::vector<VipsImage*>& in, int first,
74     VipsImage* imap, VipsImage* omap,
75     unsigned int& level)
76 {
77   VipsImage* srcimg = NULL;
78   if( in.size() > 0 ) srcimg = in[0];
79   VipsImage* mask;
80   VipsImage* out = srcimg;
81 
82   if( !out ) return NULL;
83 
84   PF_REF( out, "PF::DenoisePar::build(): out ref" );
85   if( (get_render_mode() == PF_RENDER_PREVIEW && level>0) ) {
86     return out;
87   }
88 
89   if( !impulse_nr_enable.get() && !nlmeans_enable.get() ) {
90     return out;
91   }
92 
93   ICCProfile* in_profile = PF::get_icc_profile( srcimg );
94 
95   std::vector<VipsImage*> in2;
96 
97   convert2lab->get_par()->set_image_hints( out );
98   convert2lab->get_par()->set_format( get_format() );
99   in2.clear(); in2.push_back( out );
100   VipsImage* labimg = convert2lab->get_par()->build( in2, 0, NULL, NULL, level );
101   if( !labimg ) {
102     std::cout<<"DenoisePar::build(): null Lab image"<<std::endl;
103     return out;
104   }
105   PF_UNREF( out, "DenoisePar::build(): out unref after Lab conversion" );
106   out = labimg;
107 
108   if( impulse_nr_enable.get() && impulse_nr && impulse_nr->get_par() ) {
109     PF::ImpulseNRPar* imnrpar = dynamic_cast<PF::ImpulseNRPar*>(impulse_nr->get_par());
110     if( !imnrpar ) {
111       std::cout<<"DenoisePar::build(): failed to cast to ImpulseNRPar*"<<std::endl;
112       //PF_REF( out, "PF::DenoisePar::build(): out ref" );
113       return out;
114     }
115     imnrpar->set_threshold( impulse_nr_threshold.get() );
116     imnrpar->set_image_hints( out );
117     imnrpar->set_format( get_format() );
118     in2.clear(); in2.push_back( out );
119     VipsImage* imnrimg = imnrpar->build( in2, 0, NULL, NULL, level );
120     PF_UNREF( out, "DenoisePar::build(): out unref after imnrpar->build()" );
121     out = imnrimg;
122   }
123 
124   //std::cout<<"DenoisePar::build(): nlmeans_enable.get()="<<nlmeans_enable.get()<<std::endl;
125   if( nlmeans_enable.get() && nlmeans && nlmeans->get_par() ) {
126     PF::NonLocalMeansPar* nrpar = dynamic_cast<PF::NonLocalMeansPar*>(nlmeans->get_par());
127     if( !nrpar ) {
128       std::cout<<"DenoisePar::build(): failed to cast to NonLocalMeansPar*"<<std::endl;
129       //PF_REF( out, "PF::DenoisePar::build(): out ref" );
130       return out;
131     }
132     nrpar->set_radius( nlmeans_radius.get() );
133     nrpar->set_strength( nlmeans_strength.get() );
134     nrpar->set_luma_frac( nlmeans_luma_frac.get() );
135     nrpar->set_chroma_frac( nlmeans_chroma_frac.get() );
136     nrpar->set_image_hints( out );
137     nrpar->set_format( get_format() );
138     in2.clear(); in2.push_back( out );
139     VipsImage* nrimg = nrpar->build( in2, 0, NULL, NULL, level );
140     PF_UNREF( out, "DenoisePar::build(): out unref after nrpar->build()" );
141     out = nrimg;
142   }
143 
144 
145   PF::ICCTransformPar* icc_par = dynamic_cast<PF::ICCTransformPar*>( convert2input->get_par() );
146   //std::cout<<"ImageArea::update(): icc_par="<<icc_par<<std::endl;
147   if( icc_par ) {
148     //std::cout<<"ImageArea::update(): setting display profile: "<<current_display_profile<<std::endl;
149     icc_par->set_out_profile( in_profile );
150   }
151   convert2input->get_par()->set_image_hints( out );
152   convert2input->get_par()->set_format( get_format() );
153   in2.clear(); in2.push_back( out );
154   //std::cout<<"DenoisePar::build(): calling convert2input->get_par()->build()"<<std::endl;
155   VipsImage* out2 = convert2input->get_par()->build(in2, 0, NULL, NULL, level );
156   PF_UNREF( out, "DenoisePar::update() out unref" );
157 
158 
159 	/*
160   int fast_approx = 0;
161 	if( (get_render_mode() == PF_RENDER_PREVIEW && level>0) )
162     fast_approx = 1;
163   out = vips_image_new();
164   if( im_greyc_mask( srcimg, out, NULL,
165                      iterations.get(), amplitude.get(),
166                      sharpness.get(), anisotropy.get(),
167                      alpha.get(), sigma.get(), 0.8, 30, 2, 1, fast_approx ) )
168     return NULL;
169   */
170 
171 	return out2;
172 }
173