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 PF_GUIDED_FILTER_H 31 #define PF_GUIDED_FILTER_H 32 33 #include "../base/operation.hh" 34 35 #include "padded_op.hh" 36 37 namespace PF 38 { 39 40 class GuidedFilterPar: public PaddedOpPar 41 { 42 Property<float> radius; 43 float radius_real; 44 Property<float> threshold; 45 Property<int> subsampling; 46 int subsampling_real; 47 48 ICCProfile* icc_data; 49 Property<bool> convert_to_perceptual; 50 public: 51 GuidedFilterPar(); 52 get_icc_data()53 ICCProfile* get_icc_data() { return icc_data; } 54 has_intensity()55 bool has_intensity() { return false; } 56 bool needs_caching(); set_convert_to_perceptual(bool val)57 void set_convert_to_perceptual(bool val) { convert_to_perceptual.set(val); } get_convert_to_perceptual()58 bool get_convert_to_perceptual() { return convert_to_perceptual.get(); } 59 set_radius(float r)60 void set_radius(float r) { radius.set(r); } get_radius()61 float get_radius() { return radius_real; } set_threshold(float t)62 void set_threshold(float t) { threshold.set(t); } get_threshold()63 float get_threshold() { return threshold.get(); } 64 set_subsampling(int s)65 void set_subsampling(int s) { subsampling.set(s); } get_subsampling()66 int get_subsampling() { return subsampling_real; } 67 68 void compute_padding( VipsImage* full_res, unsigned int id, unsigned int level ); 69 70 VipsImage* build(std::vector<VipsImage*>& in, int first, 71 VipsImage* imap, VipsImage* omap, 72 unsigned int& level); 73 }; 74 75 76 77 template < OP_TEMPLATE_DEF > 78 class GuidedFilterProc 79 { 80 public: render(VipsRegion ** in,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * out,OpParBase * par)81 void render(VipsRegion** in, int n, int in_first, 82 VipsRegion* imap, VipsRegion* omap, 83 VipsRegion* out, OpParBase* par) 84 { 85 } 86 }; 87 88 89 void guidedFilter(const PixelMatrix<float> &guide, const PixelMatrix<float> &src, 90 PixelMatrix<float> &dst, int r, float epsilon, int subsampling); 91 92 93 void guidedFilter(const PixelMatrix<float> &src, PixelMatrix<float> &dst, 94 int r, float epsilon, int subsampling); 95 96 97 template < OP_TEMPLATE_DEF_TYPE_SPEC > 98 class GuidedFilterProc< OP_TEMPLATE_IMP_TYPE_SPEC(float) > 99 { 100 ICCProfile* profile; 101 GuidedFilterPar* opar; 102 fill_L_matrices(int rw,int rh,PixelMatrix<float> & rgbin,PixelMatrix<float> & guidein,PixelMatrix<float> & Lin,PixelMatrix<float> & Lguide)103 void fill_L_matrices(int rw, int rh, PixelMatrix<float>& rgbin, PixelMatrix<float>& guidein, 104 PixelMatrix<float>& Lin, PixelMatrix<float>& Lguide) 105 { 106 int x, y, z; 107 108 for(y = 0; y < rh; y++) { 109 float* row = rgbin[y]; 110 float* rowg = guidein[y]; 111 float* L = Lin[y]; 112 float* Lg = Lguide[y]; 113 for( x = 0; x < rw; x++ ) { 114 //std::cout<<" y="<<y<<" x="<<x<<" row="<<row<<" rr="<<rr<<" gr="<<gr<<" br="<<br<<std::endl; 115 //if(x==0 && y==0) std::cout<<" row="<<row[0]<<" "<<row[1]<<" "<<row[2]<<std::endl; 116 if( opar->get_convert_to_perceptual() && 117 profile && profile->is_linear() ) { 118 //*L = (row[0]>0) ? powf( row[0], 1./2.4 ) : row[0]; 119 *L = (row[0]>1.0e-16) ? log10( row[0] ) : -16; 120 *Lg = (rowg[0]>1.0e-16) ? log10( rowg[0] ) : -16; 121 } else { 122 *L = row[0]; 123 *Lg = rowg[0]; 124 } 125 //*Lg = *L; 126 127 row += 1; 128 rowg += 1; 129 L += 1; 130 Lg += 1; 131 } 132 } 133 } 134 fill_L_matrices(int rw,int rh,PixelMatrix<float> & rgbin,PixelMatrix<float> & Lin)135 void fill_L_matrices(int rw, int rh, PixelMatrix<float>& rgbin, PixelMatrix<float>& Lin) 136 { 137 int x, y, z; 138 139 for(y = 0; y < rh; y++) { 140 float* row = rgbin[y]; 141 float* L = Lin[y]; 142 for( x = 0; x < rw; x++ ) { 143 //std::cout<<" y="<<y<<" x="<<x<<" row="<<row<<" rr="<<rr<<" gr="<<gr<<" br="<<br<<std::endl; 144 //if(x==0 && y==0) std::cout<<" row="<<row[0]<<" "<<row[1]<<" "<<row[2]<<std::endl; 145 if( opar->get_convert_to_perceptual() && 146 profile && profile->is_linear() ) { 147 //*L = (row[0]>0) ? powf( row[0], 1./2.4 ) : row[0]; 148 *L = (row[0]>1.0e-16) ? log10( row[0] ) : -16; 149 } else { 150 *L = row[0]; 151 } 152 //*Lg = *L; 153 154 row += 1; 155 L += 1; 156 } 157 } 158 } 159 fill_RGB_matrices(int rw,int rh,PixelMatrix<float> & rgbin,PixelMatrix<float> & rin,PixelMatrix<float> & gin,PixelMatrix<float> & bin,PixelMatrix<float> & rguide,PixelMatrix<float> & gguide,PixelMatrix<float> & bguide)160 void fill_RGB_matrices(int rw, int rh, PixelMatrix<float>& rgbin, 161 PixelMatrix<float>& rin, PixelMatrix<float>& gin, PixelMatrix<float>& bin, 162 PixelMatrix<float>& rguide, PixelMatrix<float>& gguide, PixelMatrix<float>& bguide) 163 { 164 int x, y, z; 165 166 for(y = 0; y < rh; y++) { 167 float* row = rgbin[y]; 168 float* rr = rin[y]; 169 float* gr = gin[y]; 170 float* br = bin[y]; 171 float* rrg = rguide[y]; 172 float* grg = gguide[y]; 173 float* brg = bguide[y]; 174 for( x = 0; x < rw; x++ ) { 175 //std::cout<<" y="<<y<<" x="<<x<<" row="<<row<<" rr="<<rr<<" gr="<<gr<<" br="<<br<<std::endl; 176 //if(x==0 && y==0) std::cout<<" row="<<row[0]<<" "<<row[1]<<" "<<row[2]<<std::endl; 177 if( opar->get_convert_to_perceptual() && 178 profile && profile->is_linear() ) { 179 //*rr = (row[0]>0) ? powf( row[0], 1./2.4 ) : row[0]; 180 //*gr = (row[1]>0) ? powf( row[1], 1./2.4 ) : row[1]; 181 //*br = (row[2]>0) ? powf( row[2], 1./2.4 ) : row[2]; 182 *rr = (row[0]>1.0e-16) ? log10( row[0] ) : -16; 183 *gr = (row[1]>1.0e-16) ? log10( row[1] ) : -16; 184 *br = (row[2]>1.0e-16) ? log10( row[2] ) : -16; 185 } else { 186 *rr = row[0]; 187 *gr = row[1]; 188 *br = row[2]; 189 } 190 *rrg = *rr; 191 *grg = *gr; 192 *brg = *br; 193 194 row += 3; 195 rr += 1; 196 gr += 1; 197 br += 1; 198 rrg += 1; 199 grg += 1; 200 brg += 1; 201 } 202 } 203 } 204 fill_RGBL_matrices(int rw,int rh,PixelMatrix<float> & rgbin,PixelMatrix<float> & rin,PixelMatrix<float> & gin,PixelMatrix<float> & bin,PixelMatrix<float> & Lin,PixelMatrix<float> & rguide,PixelMatrix<float> & gguide,PixelMatrix<float> & bguide,PixelMatrix<float> & Lguide)205 void fill_RGBL_matrices(int rw, int rh, PixelMatrix<float>& rgbin, 206 PixelMatrix<float>& rin, PixelMatrix<float>& gin, PixelMatrix<float>& bin, PixelMatrix<float>& Lin, 207 PixelMatrix<float>& rguide, PixelMatrix<float>& gguide, PixelMatrix<float>& bguide, PixelMatrix<float>& Lguide) 208 { 209 int x, y, z; 210 211 for(y = 0; y < rh; y++) { 212 float* row = rgbin[y]; 213 float* rr = rin[y]; 214 float* gr = gin[y]; 215 float* br = bin[y]; 216 float* Lr = Lin[y]; 217 float* rrg = rguide[y]; 218 float* grg = gguide[y]; 219 float* brg = bguide[y]; 220 float* Lrg = Lguide[y]; 221 for( x = 0; x < rw; x++ ) { 222 //std::cout<<" y="<<y<<" x="<<x<<" row="<<row<<" rr="<<rr<<" gr="<<gr<<" br="<<br<<std::endl; 223 //if(x==0 && y==0) std::cout<<" row="<<row[0]<<" "<<row[1]<<" "<<row[2]<<std::endl; 224 if( opar->get_convert_to_perceptual() && profile && profile->is_linear() ) { 225 //*rr = (row[0]>0) ? powf( row[0], 1./2.4 ) : row[0]; 226 //*gr = (row[1]>0) ? powf( row[1], 1./2.4 ) : row[1]; 227 //*br = (row[2]>0) ? powf( row[2], 1./2.4 ) : row[2]; 228 //*Lr = (row[3]>0) ? powf( row[3], 1./2.4 ) : row[3]; 229 *rr = (row[0]>1.0e-16) ? log10( row[0] ) : -16; 230 *gr = (row[1]>1.0e-16) ? log10( row[1] ) : -16; 231 *br = (row[2]>1.0e-16) ? log10( row[2] ) : -16; 232 *Lr = (row[3]>1.0e-16) ? log10( row[3] ) : -16; 233 } else { 234 *rr = row[0]; 235 *gr = row[1]; 236 *br = row[2]; 237 *Lr = row[3]; 238 } 239 *rrg = *rr; 240 *grg = *gr; 241 *brg = *br; 242 *Lrg = *Lr; 243 244 row += 4; 245 rr += 1; gr += 1; br += 1; Lr += 1; 246 rrg += 1; grg += 1; brg += 1; Lrg += 1; 247 } 248 } 249 } 250 fill_RGB_out(int rw,int rh,int dx,int dy,PixelMatrix<float> & rgbout,PixelMatrix<float> & rout,PixelMatrix<float> & gout,PixelMatrix<float> & bout)251 void fill_RGB_out(int rw, int rh, int dx, int dy, PixelMatrix<float>& rgbout, 252 PixelMatrix<float>& rout, PixelMatrix<float>& gout, PixelMatrix<float>& bout) 253 { 254 int x, y, z; 255 256 for(y = 0; y < rh; y++) { 257 float* rr = rout[y+dy]; 258 float* gr = gout[y+dy]; 259 float* br = bout[y+dy]; 260 float* row = rgbout[y]; 261 rr += dx; gr += dx; br += dx; 262 for( x = 0; x < rw; x++ ) { 263 if( opar->get_convert_to_perceptual() && 264 profile && profile->is_linear() ) { 265 //row[0] = (*rr>0) ? powf( *rr, 2.4 ) : *rr; 266 //row[1] = (*gr>0) ? powf( *gr, 2.4 ) : *gr; 267 //row[2] = (*br>0) ? powf( *br, 2.4 ) : *br; 268 row[0] = pow( 10, *rr ); 269 row[1] = pow( 10, *gr ); 270 row[2] = pow( 10, *br ); 271 } else { 272 row[0] = *rr; 273 row[1] = *gr; 274 row[2] = *br; 275 } 276 row += 3; 277 rr += 1; 278 gr += 1; 279 br += 1; 280 } 281 } 282 } 283 fill_RGBL_out(int rw,int rh,int dx,int dy,PixelMatrix<float> & rgbout,PixelMatrix<float> & rout,PixelMatrix<float> & gout,PixelMatrix<float> & bout,PixelMatrix<float> & Lout)284 void fill_RGBL_out(int rw, int rh, int dx, int dy, PixelMatrix<float>& rgbout, 285 PixelMatrix<float>& rout, PixelMatrix<float>& gout, PixelMatrix<float>& bout, PixelMatrix<float>& Lout) 286 { 287 int x, y, z; 288 289 for(y = 0; y < rh; y++) { 290 float* rr = rout[y+dy]; 291 float* gr = gout[y+dy]; 292 float* br = bout[y+dy]; 293 float* Lr = Lout[y+dy]; 294 float* row = rgbout[y]; 295 rr += dx; gr += dx; br += dx; Lr += dx; 296 for( x = 0; x < rw; x++ ) { 297 if( opar->get_convert_to_perceptual() && 298 profile && profile->is_linear() ) { 299 //row[0] = (*rr>0) ? powf( *rr, 2.4 ) : *rr; 300 //row[1] = (*gr>0) ? powf( *gr, 2.4 ) : *gr; 301 //row[2] = (*br>0) ? powf( *br, 2.4 ) : *br; 302 //row[3] = (*Lr>0) ? powf( *Lr, 2.4 ) : *Lr; 303 row[0] = pow( 10, *rr ); 304 row[1] = pow( 10, *gr ); 305 row[2] = pow( 10, *br ); 306 row[3] = pow( 10, *Lr ); 307 } else { 308 row[0] = *rr; 309 row[1] = *gr; 310 row[2] = *br; 311 row[3] = *Lr; 312 } 313 row += 4; 314 rr += 1; 315 gr += 1; 316 br += 1; 317 Lr += 1; 318 } 319 } 320 } 321 fill_L_out(int rw,int rh,int dx,int dy,PixelMatrix<float> & rgbout,PixelMatrix<float> & Lout)322 void fill_L_out(int rw, int rh, int dx, int dy, 323 PixelMatrix<float>& rgbout, PixelMatrix<float>& Lout) 324 { 325 int x, y, z; 326 327 for(y = 0; y < rh; y++) { 328 float* L = Lout[y+dy]; 329 float* row = rgbout[y]; 330 L += dx; 331 for( x = 0; x < rw; x++ ) { 332 if( opar->get_convert_to_perceptual() && 333 profile && profile->is_linear() ) { 334 //row[0] = (*L>0) ? powf( *L, 2.4 ) : *L; 335 row[0] = pow( 10, *L ); 336 } else { 337 row[0] = *L; 338 } 339 row += 1; 340 L += 1; 341 } 342 } 343 } 344 345 public: render(VipsRegion ** ireg,int n,int in_first,VipsRegion * imap,VipsRegion * omap,VipsRegion * oreg,OpParBase * par)346 void render(VipsRegion** ireg, int n, int in_first, 347 VipsRegion* imap, VipsRegion* omap, 348 VipsRegion* oreg, OpParBase* par) 349 { 350 if( n < 1 ) return; 351 if( ireg[0] == NULL ) return; 352 353 opar = dynamic_cast<GuidedFilterPar*>(par); 354 if( !opar ) return; 355 356 int es = VIPS_IMAGE_SIZEOF_ELEMENT( ireg[0]->im ); 357 int ips = VIPS_IMAGE_SIZEOF_PEL( ireg[0]->im ); 358 const int ops = VIPS_IMAGE_SIZEOF_PEL( oreg->im ); 359 360 //const int order = 1; // 0,1,2 361 //const float radius = opar->get_radius(); 362 //const float thresfold = opar->get_threshold(); 363 364 int r = opar->get_radius(); 365 float epsilon = opar->get_threshold(); 366 int subsampling = opar->get_subsampling(); 367 368 #ifdef GF_DEBUG 369 std::cout<<"[GuidedFilter]: padding = "<<opar->get_padding(0)<<" subsampling = "<<subsampling<<" epsilon = "<<epsilon<<std::endl;; 370 std::cout<<" ireg[0] = "<<ireg[0]<<" -> ("<<ireg[0]->valid.left<<","<<ireg[0]->valid.top<<") x ("<<ireg[0]->valid.width<<","<<ireg[0]->valid.height<<")\n"; 371 std::cout<<" oreg = "<<oreg<<" -> ("<<oreg->valid.left<<","<<oreg->valid.top<<") x ("<<oreg->valid.width<<","<<oreg->valid.height<<")\n"; 372 std::cout<<" pin[0] = "<<(void*)VIPS_REGION_ADDR(ireg[0], ireg[0]->valid.left, ireg[0]->valid.top) 373 <<" -> "<<*((float*)VIPS_REGION_ADDR(ireg[0], ireg[0]->valid.left, ireg[0]->valid.top))<<std::endl; 374 #endif 375 376 profile = opar->get_icc_data(); 377 if( opar->get_convert_to_perceptual() && profile && profile->is_linear() ) epsilon *= 10; 378 379 //std::cout<<"GuidedFilterProc::render: n="<<n<<" radius="<<r<<" epsilon="<<epsilon<<std::endl; 380 381 int offsx = 0; 382 int offsy = 0; 383 int shiftx = (ireg[0]->valid.left/subsampling+1) * subsampling - ireg[0]->valid.left; 384 int shifty = (ireg[0]->valid.top/subsampling+1) * subsampling - ireg[0]->valid.top; 385 int rw = ireg[0]->valid.width - shiftx - subsampling; 386 rw = (rw/subsampling+1) * subsampling; 387 int rh = ireg[0]->valid.height - shifty - subsampling; 388 rh = (rh/subsampling+1) * subsampling; 389 int ileft = ireg[0]->valid.left + shiftx; 390 int itop = ireg[0]->valid.top + shifty; 391 float* p = (float*)VIPS_REGION_ADDR( ireg[0], ileft, itop ); 392 float* pguide = (n==2 && ireg[1]) ? (float*)VIPS_REGION_ADDR( ireg[1], ileft, itop ) : p; 393 float* pout; 394 int rowstride = VIPS_REGION_LSKIP(ireg[0]) / sizeof(float); 395 PixelMatrix<float> rgbin(p, rw, rh, rowstride, offsy, offsx); 396 PixelMatrix<float> guidein(pguide, rw, rh, rowstride, offsy, offsx); 397 398 /* 399 std::cout<<"GuidedFilterProc::render: Bands="<<ireg[0]->im->Bands<<std::endl; 400 std::cout<<"GuidedFilterProc::render: radius="<<r<<" subsampling="<<subsampling<<std::endl; 401 std::cout<<"GuidedFilterProc::render: ireg.left="<<ireg[0]->valid.left 402 <<" shiftx="<<shiftx<<std::endl; 403 std::cout<<"GuidedFilterProc::render: ireg.top="<<ireg[0]->valid.top 404 <<" shifty="<<shifty<<std::endl; 405 std::cout<<"GuidedFilterProc::render: ireg.width="<<ireg[0]->valid.width 406 <<" rw="<<rw<<std::endl; 407 std::cout<<"GuidedFilterProc::render: ireg.height="<<ireg[0]->valid.height 408 <<" rh="<<rh<<std::endl; 409 */ 410 if( ireg[0]->im->Bands == 1 ) { 411 //if(true && r->top<150 && r->left<700 && x==0 && y==0) 412 //std::cout<<"[x,y]="<<x0+r->left<<","<<y+r->top<<" l1: "<<l2<<" l2: "<<l2<<std::endl; 413 414 PixelMatrix<float> Lin(rw, rh, offsy, offsx); 415 PixelMatrix<float> Lguide(rw, rh, offsy, offsx); 416 PixelMatrix<float> Lout(rw, rh, offsy, offsx); 417 418 //std::cout<<"GuidedFilterProc::render: splitting RGB channels"<<std::endl; 419 420 //fill_L_matrices( rw, rh, rgbin, guidein, Lin, Lguide ); 421 fill_L_matrices( rw, rh, rgbin, Lin ); 422 423 //std::cout<<"GuidedFilterProc::render: processing L channel"<<std::endl; 424 //guidedFilter(Lguide, Lin, Lout, r, epsilon, subsampling); 425 guidedFilter(Lin, Lout, r, epsilon, subsampling); 426 427 int dx = oreg->valid.left - ireg[0]->valid.left - shiftx; 428 int dy = oreg->valid.top - ireg[0]->valid.top - shifty; 429 offsx = oreg->valid.left; 430 offsy = oreg->valid.top; 431 rw = oreg->valid.width; 432 rh = oreg->valid.height; 433 pout = (float*)VIPS_REGION_ADDR( oreg, offsx, offsy ); 434 rowstride = VIPS_REGION_LSKIP(oreg) / sizeof(float); 435 PF::PixelMatrix<float> rgbout(pout, rw, rh, rowstride, 0, 0); 436 437 //std::cout<<"GuidedFilterProc::render: r="<<r<<" epsilon="<<epsilon<<" subsampling="<<subsampling 438 // <<" left="<<oreg->valid.left<<" top="<<oreg->valid.top 439 // <<" dx="<<dx<<" dy="<<dy<<" rw="<<rw<<" rh="<<rh<<std::endl; 440 441 fill_L_out(rw, rh, dx, dy, rgbout, Lout); 442 #ifdef GF_DEBUG 443 std::cout<<" pout[0] = "<<(void*)VIPS_REGION_ADDR(oreg, oreg->valid.left, oreg->valid.top) 444 <<" -> "<<*((float*)VIPS_REGION_ADDR(oreg, oreg->valid.left, oreg->valid.top))<<std::endl; 445 #endif 446 } 447 448 if( ireg[0]->im->Bands == 3 ) { 449 PixelMatrix<float> rin(rw, rh, offsy, offsx); 450 PixelMatrix<float> gin(rw, rh, offsy, offsx); 451 PixelMatrix<float> bin(rw, rh, offsy, offsx); 452 PixelMatrix<float> rguide(rw, rh, offsy, offsx); 453 PixelMatrix<float> gguide(rw, rh, offsy, offsx); 454 PixelMatrix<float> bguide(rw, rh, offsy, offsx); 455 PixelMatrix<float> rout(rw, rh, offsy, offsx); 456 PixelMatrix<float> gout(rw, rh, offsy, offsx); 457 PixelMatrix<float> bout(rw, rh, offsy, offsx); 458 459 //std::cout<<"GuidedFilterProc::render: splitting RGB channels"<<std::endl; 460 461 fill_RGB_matrices( rw, rh, rgbin, rin, gin, bin, rguide, gguide, bguide ); 462 463 //std::cout<<"GuidedFilterProc::render: processing RGB channels"<<std::endl; 464 //std::cout<<" processing R:"<<std::endl; 465 guidedFilter(rguide, rin, rout, r, epsilon, subsampling); 466 //std::cout<<" processing G:"<<std::endl; 467 guidedFilter(gguide, gin, gout, r, epsilon, subsampling); 468 //std::cout<<" processing B:"<<std::endl; 469 guidedFilter(bguide, bin, bout, r, epsilon, subsampling); 470 471 int dx = oreg->valid.left - ireg[0]->valid.left - shiftx; 472 int dy = oreg->valid.top - ireg[0]->valid.top - shifty; 473 offsx = oreg->valid.left; 474 offsy = oreg->valid.top; 475 rw = oreg->valid.width; 476 rh = oreg->valid.height; 477 p = (float*)VIPS_REGION_ADDR( oreg, offsx, offsy ); 478 rowstride = VIPS_REGION_LSKIP(oreg) / sizeof(float); 479 PF::PixelMatrix<float> rgbout(p, rw, rh, rowstride, 0, 0); 480 481 //std::cout<<"GuidedFilterProc::render: r="<<r<<" epsilon="<<epsilon<<" subsampling="<<subsampling 482 // <<" dx="<<dx<<" dy="<<dy<<" rw="<<rw<<" rh="<<rh<<std::endl; 483 484 fill_RGB_out(rw, rh, dx, dy, rgbout, rout, gout, bout); 485 } 486 487 488 if( ireg[0]->im->Bands == 4 ) { 489 PixelMatrix<float> rin(rw, rh, offsy, offsx); 490 PixelMatrix<float> gin(rw, rh, offsy, offsx); 491 PixelMatrix<float> bin(rw, rh, offsy, offsx); 492 PixelMatrix<float> Lin(rw, rh, offsy, offsx); 493 PixelMatrix<float> rguide(rw, rh, offsy, offsx); 494 PixelMatrix<float> gguide(rw, rh, offsy, offsx); 495 PixelMatrix<float> bguide(rw, rh, offsy, offsx); 496 PixelMatrix<float> Lguide(rw, rh, offsy, offsx); 497 PixelMatrix<float> rout(rw, rh, offsy, offsx); 498 PixelMatrix<float> gout(rw, rh, offsy, offsx); 499 PixelMatrix<float> bout(rw, rh, offsy, offsx); 500 PixelMatrix<float> Lout(rw, rh, offsy, offsx); 501 502 //std::cout<<"GuidedFilterProc::render: splitting RGB channels"<<std::endl; 503 504 fill_RGBL_matrices( rw, rh, rgbin, rin, gin, bin, Lin, rguide, gguide, bguide, Lguide ); 505 506 //std::cout<<"GuidedFilterProc::render: processing RGB channels"<<std::endl; 507 //std::cout<<" processing R:"<<std::endl; 508 guidedFilter(rguide, rin, rout, r, epsilon, subsampling); 509 //std::cout<<" processing G:"<<std::endl; 510 guidedFilter(gguide, gin, gout, r, epsilon, subsampling); 511 //std::cout<<" processing B:"<<std::endl; 512 guidedFilter(bguide, bin, bout, r, epsilon, subsampling); 513 //std::cout<<" processing L:"<<std::endl; 514 guidedFilter(Lguide, Lin, Lout, r, epsilon, subsampling); 515 516 int dx = oreg->valid.left - ireg[0]->valid.left; 517 int dy = oreg->valid.top - ireg[0]->valid.top; 518 offsx = oreg->valid.left; 519 offsy = oreg->valid.top; 520 rw = oreg->valid.width; 521 rh = oreg->valid.height; 522 p = (float*)VIPS_REGION_ADDR( oreg, offsx, offsy ); 523 rowstride = VIPS_REGION_LSKIP(oreg) / sizeof(float); 524 PF::PixelMatrix<float> rgbout(p, rw, rh, rowstride, 0, 0); 525 526 //std::cout<<"GuidedFilterProc::render: r="<<r<<" epsilon="<<epsilon<<" subsampling="<<subsampling 527 // <<" dx="<<dx<<" dy="<<dy<<" rw="<<rw<<" rh="<<rh<<std::endl; 528 529 fill_RGBL_out(rw, rh, dx, dy, rgbout, rout, gout, bout, Lout); 530 } 531 532 /* 533 int x, y, z; 534 535 for(y = 0; y < rh; y++) { 536 float* row = rgbin[y]; 537 float* rr = rin[y]; 538 float* gr = gin[y]; 539 float* br = bin[y]; 540 float* rrg = rguide[y]; 541 float* grg = gguide[y]; 542 float* brg = bguide[y]; 543 for( x = 0; x < rw; x++ ) { 544 //std::cout<<" y="<<y<<" x="<<x<<" row="<<row<<" rr="<<rr<<" gr="<<gr<<" br="<<br<<std::endl; 545 //if(x==0 && y==0) std::cout<<" row="<<row[0]<<" "<<row[1]<<" "<<row[2]<<std::endl; 546 if( opar->get_convert_to_perceptual() && 547 profile && profile->is_linear() ) { 548 *rr = (row[0]>0) ? powf( row[0], 1./2.4 ) : row[0]; 549 *gr = (row[1]>0) ? powf( row[1], 1./2.4 ) : row[1]; 550 *br = (row[2]>0) ? powf( row[2], 1./2.4 ) : row[2]; 551 } else { 552 *rr = row[0]; 553 *gr = row[1]; 554 *br = row[2]; 555 } 556 if(false && profile && profile->is_linear()) { 557 *rrg = (*rr>0) ? powf( *rr, 1./2.4 ) : *rr; 558 *grg = (*gr>0) ? powf( *gr, 1./2.4 ) : *gr; 559 *brg = (*br>0) ? powf( *br, 1./2.4 ) : *br; 560 } else { 561 *rrg = *rr; 562 *grg = *gr; 563 *brg = *br; 564 } 565 row += 3; 566 rr += 1; 567 gr += 1; 568 br += 1; 569 rrg += 1; 570 grg += 1; 571 brg += 1; 572 } 573 } 574 575 //return; 576 577 int dx = oreg->valid.left - ireg[0]->valid.left; 578 int dy = oreg->valid.top - ireg[0]->valid.top; 579 offsx = oreg->valid.left; 580 offsy = oreg->valid.top; 581 rw = oreg->valid.width; 582 rh = oreg->valid.height; 583 p = (float*)VIPS_REGION_ADDR( oreg, offsx, offsy ); 584 rowstride = VIPS_REGION_LSKIP(oreg) / sizeof(float); 585 PF::PixelMatrix<float> rgbout(p, rw, rh, rowstride, 0, 0); 586 587 if( ireg[0]->im.Bands == 3 ) { 588 fill_RGB_out(rw, rh, dx, dy, rout, gout, bout, rgbout); 589 } 590 591 for(y = 0; y < rh; y++) { 592 float* irow = rgbin[y+dy]; 593 float* rr = rout[y+dy]; 594 float* gr = gout[y+dy]; 595 float* br = bout[y+dy]; 596 float* row = rgbout[y]; 597 //float* rr = rin[y+dy]; 598 //float* gr = gin[y+dy]; 599 //float* br = bin[y+dy]; 600 rr += dx; gr += dx; br += dx; irow += dx*3; 601 for( x = 0; x < rw; x++ ) { 602 if( opar->get_convert_to_perceptual() && 603 profile && profile->is_linear() ) { 604 row[0] = (*rr>0) ? powf( *rr, 2.4 ) : *rr; 605 row[1] = (*gr>0) ? powf( *gr, 2.4 ) : *gr; 606 row[2] = (*br>0) ? powf( *br, 2.4 ) : *br; 607 } else { 608 row[0] = *rr; 609 row[1] = *gr; 610 row[2] = *br; 611 } 612 //row[0] = irow[0]; 613 //row[1] = irow[1]; 614 //row[2] = irow[2]; 615 row += 3; 616 irow += 3; 617 rr += 1; 618 gr += 1; 619 br += 1; 620 } 621 } 622 */ 623 } 624 }; 625 626 627 ProcessorBase* new_guided_filter(); 628 629 } 630 631 #endif 632 633 634