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 class BlurBilateralBlurPar: public OpParBase
31 {
32   int padding;
33 public:
BlurBilateralBlurPar()34   BlurBilateralBlurPar():
35     OpParBase(), padding(2)
36   {
37     set_type( "blur_bilateral_blur" );
38     set_default_name( _("blilateral blur blur") );
39   }
40 
41 
has_intensity()42   bool has_intensity() { return false; }
has_opacity()43   bool has_opacity() { return false; }
needs_caching()44   bool needs_caching() { return false; }
45 
get_padding()46   int get_padding() { return padding; }
47 
48 
49 
50   /* Function to derive the output area from the input area
51    */
transform(const VipsRect * rin,VipsRect * rout,int)52   virtual void transform(const VipsRect* rin, VipsRect* rout, int /*id*/)
53   {
54     int pad = padding;
55     rout->left = rin->left+pad;
56     rout->top = rin->top+pad;
57     rout->width = rin->width-pad*2;
58     rout->height = rin->height-pad*2;
59   }
60 
61   /* Function to derive the area to be read from input images,
62      based on the requested output area
63   */
transform_inv(const VipsRect * rout,VipsRect * rin,int)64   virtual void transform_inv(const VipsRect* rout, VipsRect* rin, int /*id*/)
65   {
66     int pad = padding;
67     rin->left = rout->left-pad;
68     rin->top = rout->top-pad;
69     rin->width = rout->width+pad*2;
70     rin->height = rout->height+pad*2;
71     //std::cout<<"BlurBilateralBlurPar::transform_inv(): ireg="<<rin->width<<"x"<<rin->height
72     //      <<"+"<<rin->left<<","<<rin->top<<std::endl;
73     //std::cout<<"                                       oreg="<<rout->width<<"x"<<rout->height<<"+"<<rout->left<<","<<rout->top<<std::endl;
74   }
75 
build(std::vector<VipsImage * > & in,int first,VipsImage * imap,VipsImage * omap,unsigned int & level)76   VipsImage* build(std::vector<VipsImage*>& in, int first,
77       VipsImage* imap, VipsImage* omap,
78       unsigned int& level)
79   {
80     VipsImage* srcimg = NULL;
81     if( in.size() > 0 ) srcimg = in[0];
82     VipsImage* out = srcimg;
83     if( !out ) return NULL;
84     set_image_hints(srcimg);
85     VipsImage* blurred = OpParBase::build( in, first, NULL, NULL, level );
86 
87     return blurred;
88   }
89 };
90 
91 
92 
93 template < OP_TEMPLATE_DEF >
94 class BlurBilateralBlurProc
95 {
96 public:
render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)97   void render(VipsRegion** ireg, int n, int in_first,
98       VipsRegion* imap, VipsRegion* omap,
99       VipsRegion* oreg, OpParBase* par)
100   {
101     std::cout<<"BlurBilateralBlurProc::render() called"<<std::endl;
102   }
103 };
104 
105 template < OP_TEMPLATE_DEF_CS_SPEC >
106 class BlurBilateralBlurProc< OP_TEMPLATE_IMP_CS_SPEC(PF_COLORSPACE_MULTIBAND) >
107 {
108 public:
render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)109   void render(VipsRegion** ireg, int n, int in_first,
110       VipsRegion* imap, VipsRegion* omap,
111       VipsRegion* oreg, OpParBase* par)
112   {
113     if( ireg[0] == NULL ) return;
114 
115     BlurBilateralBlurPar* opar = dynamic_cast<BlurBilateralBlurPar*>(par);
116     if( !opar ) return;
117 
118     VipsRect *r = &oreg->valid;
119     int width = r->width;
120     int height = r->height;
121     int y;
122     VipsImage* srcimg = ireg[0]->im;
123 
124     if( false && r->left<10000 && r->top<10000 ) {
125       std::cout<<"BlurBilateralBlurProc::render(): ireg="<<ireg[0]->valid.width<<"x"<<ireg[0]->valid.height
126           <<"+"<<ireg[0]->valid.left<<","<<ireg[0]->valid.top<<std::endl;
127       std::cout<<"                                 oreg="<<r->width<<"x"<<r->height<<"+"<<r->left<<","<<r->top<<std::endl;
128     }
129 
130     int verb = 0;
131     //if(ireg[0]->valid.left==0 && ireg[0]->valid.top==0) verb = 1;
132     dt_bilateral_t* dt_b = (dt_bilateral_t *)malloc(sizeof(dt_bilateral_t));
133     dt_b->size_x = ireg[0]->valid.width;
134     dt_b->size_y = ireg[0]->valid.height;
135     dt_b->size_z = ireg[0]->im->Bands;
136     dt_b->buf = (float*)malloc(dt_b->size_x * dt_b->size_y * dt_b->size_z * sizeof(float));
137 
138     T* pin  = (T*)VIPS_REGION_ADDR( ireg[0], ireg[0]->valid.left, ireg[0]->valid.top );
139     T* pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top );
140     int ilskip = VIPS_REGION_LSKIP( ireg[0] ) / sizeof(T);
141     int olskip = VIPS_REGION_LSKIP( oreg ) / sizeof(T);
142     int ilsz = VIPS_REGION_SIZEOF_LINE(ireg[0]);
143     int olsz = VIPS_REGION_SIZEOF_LINE(oreg);
144     int lsz = dt_b->size_x * dt_b->size_z;
145 
146     T* p = dt_b->buf;
147     for( y = 0; y < ireg[0]->valid.height; y++ ) {
148       pin = (T*)VIPS_REGION_ADDR( ireg[0], ireg[0]->valid.left, ireg[0]->valid.top + y );
149       memcpy(p, pin, lsz * sizeof(float) );
150       p += lsz;
151     }
152 
153     dt_bilateral_blur(dt_b);
154 
155     p = dt_b->buf + 2*lsz + 2*dt_b->size_z;
156     for( y = 0; y < height; y++ ) {
157       pin = (T*)VIPS_REGION_ADDR( ireg[0], r->left, r->top + y );
158       pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top + y );
159       memcpy(pout, p, olsz );
160       p += lsz;
161     }
162 
163     free(dt_b->buf); free(dt_b);
164   }
165 };
166