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 class BlurBilateralSlicePar: public OpParBase
32 {
33   float sigma_s;
34   float sigma_r;
35   float ss, sr;
36 
37   float scale_x, scale_y;
38   int full_width, full_height;
39 
40 public:
BlurBilateralSlicePar()41   BlurBilateralSlicePar():
42     OpParBase(), sigma_s(0), sigma_r(0)
43   {
44     set_type( "blur_bilateral_slice" );
45     set_default_name( _("blilateral blur slice") );
46   }
47 
48   //void set_iterations( int i ) { iterations.set( i ); }
set_full_width(int w)49   void set_full_width( int w )  { full_width  = w; }
set_full_height(int h)50   void set_full_height( int h ) { full_height = h; }
51 
set_sigma_s(float s)52   void set_sigma_s( float s ) { sigma_s = s; }
set_sigma_r(float s)53   void set_sigma_r( float s ) { sigma_r = s; }
54 
get_ss()55   float get_ss() { return ss; }
get_sr()56   float get_sr() { return sr; }
57 
get_sigma_s()58   float get_sigma_s() { return sigma_s; }
get_sigma_r()59   float get_sigma_r() { return sigma_r; }
60 
has_intensity()61   bool has_intensity() { return false; }
has_opacity()62   bool has_opacity() { return true; }
needs_caching()63   bool needs_caching() { return true; }
64 
65 
66   /* Function to derive the output area from the input area
67    */
transform(const VipsRect * rin,VipsRect * rout,int)68   virtual void transform(const VipsRect* rin, VipsRect* rout, int /*id*/)
69   {
70     rout->left = rin->left*scale_x;
71     rout->top = rin->top*scale_y;
72     rout->width = rin->width*scale_x;
73     rout->height = rin->height*scale_y;
74   }
75 
76   /* Function to derive the area to be read from input images,
77        based on the requested output area
78    */
transform_inv(const VipsRect * rout,VipsRect * rin,int id)79   virtual void transform_inv(const VipsRect* rout, VipsRect* rin, int id)
80   {
81     if( id == 0 ) {
82     float _w = roundf(rout->width  / ss);
83     float _h = roundf(rout->height / ss);
84     float _l = roundf(rout->left   / ss);
85     float _t = roundf(rout->top    / ss);
86     rin->left   = _l - 2; //CLAMPS((int)_l, 0, 6000) - 1;
87     rin->top    = _t - 2; //CLAMPS((int)_t, 0, 6000) - 1;
88     rin->width  = _w + 5; //CLAMPS((int)_w, 4, 6000) + 3;
89     rin->height = _h + 5; //CLAMPS((int)_h, 4, 6000) + 3;
90     //rin->left = rout->left/scale_x;
91     //rin->top = rout->top/scale_y;
92     //rin->width = rout->width/scale_x;
93     //rin->height = rout->height/scale_y;
94     } else {
95       rin->left = rout->left;
96       rin->top = rout->top;
97       rin->width = rout->width;
98       rin->height = rout->height;
99     }
100     if( false ) {
101     std::cout<<"BlurBilateralSlicePar::transform_inv(): id="<<id<<"  ss="<<ss<<", ireg="<<rin->width<<"x"<<rin->height
102           <<"+"<<rin->left<<","<<rin->top<<std::endl;
103     std::cout<<"                                       oreg="<<rout->width<<"x"<<rout->height<<"+"<<rout->left<<","<<rout->top<<std::endl;
104     }
105   }
106 
build(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)107   VipsImage* build(std::vector<VipsImage*>& in, int first,
108       VipsImage* imap, VipsImage* omap,
109       unsigned int& level)
110   {
111     VipsImage* srcimg = NULL;
112     if( in.size() > 0 ) srcimg = in[0];
113     VipsImage* out = srcimg;
114     if( !out ) return NULL;
115 
116     ss = sigma_s;
117     sr = sigma_r;
118 
119     out = OpParBase::build( in, first, imap, omap, level );
120 
121     return out;
122   }
123 };
124 
125 
126 
127 template < OP_TEMPLATE_DEF >
128 class BlurBilateralSliceProc
129 {
130 public:
render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)131   void render(VipsRegion** ireg, int n, int in_first,
132       VipsRegion* imap, VipsRegion* omap,
133       VipsRegion* oreg, OpParBase* par)
134   {
135     std::cout<<"BlurBilateralSliceProc::render() called"<<std::endl;
136   }
137 };
138 
139 template < OP_TEMPLATE_DEF_CS_SPEC >
140 class BlurBilateralSliceProc< OP_TEMPLATE_IMP_CS_SPEC(PF_COLORSPACE_GRAYSCALE) >
141 {
142 public:
render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)143   void render(VipsRegion** ireg, int n, int in_first,
144       VipsRegion* imap, VipsRegion* omap,
145       VipsRegion* oreg, OpParBase* par)
146   {
147     if( ireg[0] == NULL ) return;
148 
149     BlurBilateralSlicePar* opar = dynamic_cast<BlurBilateralSlicePar*>(par);
150     if( !opar ) return;
151 
152     VipsRect *r = &oreg->valid;
153     int width = r->width;
154     int height = r->height;
155     int x, y;
156     VipsImage* srcimg = ireg[0]->im;
157 
158     if( false && r->left<10000 && r->top<10000 ) {
159       std::cout<<"BlurBilateralSliceProc::render(): ireg[0]="<<ireg[0]->valid.width<<"x"<<ireg[0]->valid.height
160           <<"+"<<ireg[0]->valid.left<<","<<ireg[0]->valid.top
161           //<<"  ireg[1]="<<ireg[1]->valid.width<<"x"<<ireg[1]->valid.height
162           //<<"+"<<ireg[1]->valid.left<<","<<ireg[1]->valid.top
163           <<std::endl;
164       std::cout<<"                                  oreg="<<r->width<<"x"<<r->height<<"+"<<r->left<<","<<r->top<<std::endl;
165     }
166 
167     T* pin  = (T*)VIPS_REGION_ADDR( ireg[0], ireg[0]->valid.left+2, ireg[0]->valid.top+2 );
168     T* pin2  = (T*)VIPS_REGION_ADDR( ireg[1], r->left, r->top );
169     T* pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top );
170     int ilskip = VIPS_REGION_LSKIP( ireg[1] ) / sizeof(T);
171     int lskip  = VIPS_REGION_LSKIP( ireg[0] ) / sizeof(T);
172     int olskip = VIPS_REGION_LSKIP( oreg ) / sizeof(T);
173 
174     int verb = 0;
175     //if(ireg[0]->valid.left<1000 && ireg[0]->valid.top<1000) verb = 1;
176     dt_bilateral_t* dt_b = dt_bilateral_init(width, height,
177         opar->get_ss(), opar->get_sr(), verb);
178     dt_b->buf = pin;
179     dt_bilateral_slice(dt_b, pin2, pout, ilskip, lskip, olskip, -1);
180     //std::cout<<"pout[0]="<<*pout<<std::endl;
181 
182     /*
183     for( y = 0; y < height; y++ ) {
184       pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top + y );
185       for( x = 0; x < width; x++ ) {
186         pout[x] = 60;
187       }
188     }
189     */
190 
191     dt_bilateral_free(dt_b);
192   }
193 };
194