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 #ifndef BLUR_BILATERAL_H 31 #define BLUR_BILATERAL_H 32 33 #include <assert.h> 34 #include <string> 35 36 #include "../base/processor.hh" 37 extern "C" { 38 #include "../external/darktable/src/common/bilateral.h" 39 } 40 41 42 namespace PF 43 { 44 45 #include "blur_bilateral_splat.hh" 46 #include "blur_bilateral_blur.hh" 47 #include "blur_bilateral_slice.hh" 48 49 50 class BlurBilateralAlgoPar: public OpParBase 51 { 52 Property<float> sigma_s; 53 Property<float> sigma_r; 54 float ss, sr; 55 56 int cur_padding; 57 58 public: 59 BlurBilateralAlgoPar(); 60 61 //void set_iterations( int i ) { iterations.set( i ); } set_sigma_s(float s)62 void set_sigma_s( float s ) { sigma_s.set( s ); } set_sigma_r(float s)63 void set_sigma_r( float s ) { sigma_r.set( s ); } 64 get_ss()65 float get_ss() { return ss; } get_sr()66 float get_sr() { return sr; } 67 get_sigma_s()68 float get_sigma_s() { return sigma_s.get(); } get_sigma_r()69 float get_sigma_r() { return sigma_r.get(); } 70 has_intensity()71 bool has_intensity() { return false; } has_opacity()72 bool has_opacity() { return true; } needs_caching()73 bool needs_caching() { return true; } 74 compute_padding(VipsImage * full_res,unsigned int id,unsigned int level)75 void compute_padding( VipsImage* full_res, unsigned int id, unsigned int level ) 76 { 77 float ss = sigma_s.get(); 78 for( int l = 1; l <= level; l++ ) { 79 ss /= 2; 80 } 81 int iss = static_cast<int>(ss*3); 82 //iss /= 16; 83 //iss = (iss+1)*16; 84 iss = 2; 85 set_padding( iss, id ); 86 std::cout<<"BlurBilateralAlgoPar()::compute_padding(): sigma_s="<<sigma_s.get() 87 <<" level="<<level<<" ss="<<ss<<" iss="<<iss<<" padding="<<get_padding(id)<<std::endl; 88 } 89 90 /* Function to derive the output area from the input area 91 */ transform(const VipsRect * rin,VipsRect * rout,int)92 virtual void transform(const VipsRect* rin, VipsRect* rout, int /*id*/) 93 { 94 int pad = get_padding(0); 95 rout->left = rin->left+pad; 96 rout->top = rin->top+pad; 97 rout->width = rin->width-pad*2; 98 rout->height = rin->height-pad*2; 99 } 100 101 /* Function to derive the area to be read from input images, 102 based on the requested output area 103 */ transform_inv(const VipsRect * rout,VipsRect * rin,int)104 virtual void transform_inv(const VipsRect* rout, VipsRect* rin, int /*id*/) 105 { 106 int pad = get_padding(0); 107 rin->left = rout->left-pad; 108 rin->top = rout->top-pad; 109 rin->width = rout->width+pad*2; 110 rin->height = rout->height+pad*2; 111 } 112 113 VipsImage* build(std::vector<VipsImage*>& in, int first, 114 VipsImage* imap, VipsImage* omap, 115 unsigned int& level); 116 }; 117 118 119 120 template < OP_TEMPLATE_DEF > 121 class BlurBilateralAlgoProc 122 { 123 public: render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)124 void render(VipsRegion** ireg, int n, int in_first, 125 VipsRegion* imap, VipsRegion* omap, 126 VipsRegion* oreg, OpParBase* par) 127 { 128 std::cout<<"BlurBilateralAlgoProc::render() called"<<std::endl; 129 } 130 }; 131 132 template < OP_TEMPLATE_DEF_CS_SPEC > 133 class BlurBilateralAlgoProc< OP_TEMPLATE_IMP_CS_SPEC(PF_COLORSPACE_GRAYSCALE) > 134 { 135 public: render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)136 void render(VipsRegion** ireg, int n, int in_first, 137 VipsRegion* imap, VipsRegion* omap, 138 VipsRegion* oreg, OpParBase* par) 139 { 140 if( ireg[0] == NULL ) return; 141 142 BlurBilateralAlgoPar* opar = dynamic_cast<BlurBilateralAlgoPar*>(par); 143 if( !opar ) return; 144 145 VipsRect *r = &oreg->valid; 146 int width = r->width; 147 int height = r->height; 148 int y; 149 VipsImage* srcimg = ireg[0]->im; 150 151 if( false && r->left<10000 && r->top<10000 ) { 152 std::cout<<"BlurBilateralAlgoProc::render(): ireg="<<ireg[0]->valid.width<<"x"<<ireg[0]->valid.height 153 <<"+"<<ireg[0]->valid.left<<","<<ireg[0]->valid.top<<std::endl; 154 std::cout<<" oreg="<<r->width<<"x"<<r->height<<"+"<<r->left<<","<<r->top<<std::endl; 155 } 156 157 T* obuf = (T*)malloc( ireg[0]->valid.width * ireg[0]->valid.height * sizeof(T) ); 158 if(!obuf) return; 159 160 T* pin = (T*)VIPS_REGION_ADDR( ireg[0], ireg[0]->valid.left, ireg[0]->valid.top ); 161 T* pout; 162 T* p; 163 164 int verb = 0; 165 //if(ireg[0]->valid.left==0 && ireg[0]->valid.top==0) verb = 1; 166 dt_bilateral_t* dt_b = dt_bilateral_init(ireg[0]->valid.width, ireg[0]->valid.height, 167 opar->get_ss(), opar->get_sr(), verb); 168 dt_b->buf = (float*)malloc(dt_b->size_x * dt_b->size_y * dt_b->size_z * sizeof(float)); 169 memset(dt_b->buf, 0, dt_b->size_x * dt_b->size_y * dt_b->size_z * sizeof(float)); 170 171 int ilskip = VIPS_REGION_LSKIP( ireg[0] ) / sizeof(T); 172 int lskip = dt_b->size_x * dt_b->size_z; 173 int olskip = VIPS_REGION_LSKIP( oreg ) / sizeof(T); 174 175 dt_bilateral_splat(dt_b, pin, ilskip, lskip, verb); 176 dt_bilateral_blur(dt_b); 177 dt_bilateral_slice(dt_b, pin, obuf, ilskip, lskip, olskip, -1); 178 dt_bilateral_free(dt_b); 179 int dx = r->left - ireg[0]->valid.left; 180 int dy = r->top - ireg[0]->valid.top; 181 182 for( y = 0; y < height; y++ ) { 183 p = obuf + (y+dy)*ireg[0]->valid.width + dx; 184 pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top + y ); 185 memcpy(pout, p, sizeof(T)*width ); 186 } 187 free(dt_b->buf); 188 free(obuf); 189 } 190 }; 191 192 193 194 195 196 class BlurBilateralPar: public OpParBase 197 { 198 Property<float> sigma_s; 199 Property<float> sigma_r; 200 ProcessorBase* bsplat; 201 ProcessorBase* blur; 202 ProcessorBase* slice; 203 ProcessorBase* balgo; 204 205 public: 206 BlurBilateralPar(); 207 has_intensity()208 bool has_intensity() { return false; } has_opacity()209 bool has_opacity() { return true; } needs_caching()210 bool needs_caching() { return false; } 211 212 void set_sigma_s( float s ); 213 void set_sigma_r( float s ); get_sigma_s()214 float get_sigma_s() { return sigma_s.get(); } get_sigma_r()215 float get_sigma_r() { return sigma_r.get(); } 216 compute_padding(VipsImage * full_res,unsigned int id,unsigned int level)217 void compute_padding( VipsImage* full_res, unsigned int id, unsigned int level ) 218 { 219 //g_assert(balgo->get_par() != NULL); 220 //balgo->get_par()->compute_padding(full_res, id, level); 221 //set_padding( balgo->get_par()->get_padding(id), id ); 222 float ss; 223 ss = sigma_s.get(); 224 for( int l = 1; l <= level; l++ ) { 225 ss /= 2; 226 } 227 ss = roundf(ss); //ss = 100; 228 int iss = ss; 229 if(iss < 1) iss = 1; 230 231 set_padding( 5*iss, id ); 232 //std::cout<<"BlurBilateralPar()::compute_padding(): padding="<<get_padding(id)<<std::endl; 233 } 234 235 VipsImage* build(std::vector<VipsImage*>& in, int first, 236 VipsImage* imap, VipsImage* omap, 237 unsigned int& level); 238 239 VipsImage* build_(std::vector<VipsImage*>& in, int first, 240 VipsImage* imap, VipsImage* omap, 241 unsigned int& level); 242 }; 243 244 245 246 template < OP_TEMPLATE_DEF > 247 class BlurBilateralProc 248 { 249 public: render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)250 void render(VipsRegion** ireg, int n, int in_first, 251 VipsRegion* imap, VipsRegion* omap, 252 VipsRegion* oreg, OpParBase* par) 253 { 254 } 255 }; 256 257 258 259 template < OP_TEMPLATE_DEF_CS_SPEC > 260 class BlurBilateralProc< OP_TEMPLATE_IMP_CS_SPEC(PF_COLORSPACE_GRAYSCALE) > 261 { 262 public: render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)263 void render(VipsRegion** ireg, int n, int in_first, 264 VipsRegion* imap, VipsRegion* omap, 265 VipsRegion* oreg, OpParBase* par) 266 { 267 if( ireg[0] == NULL ) return; 268 269 BlurBilateralPar* opar = dynamic_cast<BlurBilateralPar*>(par); 270 if( !opar ) return; 271 272 VipsRect *r = &oreg->valid; 273 int width = r->width; 274 int height = r->height; 275 int y; 276 VipsImage* srcimg = ireg[0]->im; 277 278 if( false && r->left<10000 && r->top<10000 ) { 279 std::cout<<"BlurBilateralProc::render(): ireg="<<ireg[0]->valid.width<<"x"<<ireg[0]->valid.height 280 <<"+"<<ireg[0]->valid.left<<","<<ireg[0]->valid.top<<std::endl; 281 std::cout<<" oreg="<<r->width<<"x"<<r->height<<"+"<<r->left<<","<<r->top<<std::endl; 282 } 283 284 T* pin; 285 T* pout; 286 for( y = 0; y < height; y++ ) { 287 pin = (T*)VIPS_REGION_ADDR( ireg[0], r->left, r->top + y ); 288 pout = (T*)VIPS_REGION_ADDR( oreg, r->left, r->top + y ); 289 memcpy(pout, pin, sizeof(T)*width ); 290 } 291 } 292 }; 293 294 295 ProcessorBase* new_blur_bilateral(); 296 } 297 298 #endif 299 300 301