/* * This file is part of RawTherapee. * * Copyright (c) 2004-2010 Gabor Horvath * * RawTherapee is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * RawTherapee is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ #ifndef _BILATERAL2_ #define _BILATERAL2_ #include #include #include #include #include "rtengine.h" #include "rt_math.h" #include "alignedbuffer.h" #include "mytime.h" #include "gauss.h" #include "array2D.h" #ifdef _OPENMP #include #endif using namespace rtengine; // This seems ugly, but way faster than any other solutions I tried #define ELEM(a,b) (src[i - a][j - b] * ec[src[i - a][j - b]-src[i][j]+65536.0f]) #define SULY(a,b) (ec[src[i - a][j - b]-src[i][j]+65536.0f]) //#define SULY(a,b) (ec[((int)(src[i - a][j - b]-src[i][j]+0x10000))]) #define BL_BEGIN(a,b) double scale = (a); \ LUTf ec (0x20000); \ for (int i=0; i<0x20000; i++) \ ec[i] = (exp(-(double)(i-0x10000)*(double)(i-0x10000) / (2.0*sens*sens))*scale); \ int rstart = b; \ int rend = H-b; \ int cstart = b; \ int cend = W-b; #define BL_FREE buffer[i][j] = v; }}; #define BL_END(b) for (int i=0; i=rend || j>=cend) \ dst[i][j] = src[i][j]; \ else \ dst[i][j] = buffer[i][j]; #define BL_OPER3(a11,a12,a21,a22) for (int i=rstart; i void bilateral05 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(318,1) #pragma omp for BL_OPER3(1,7,7,55) BL_FREE #pragma omp for BL_END(1) } // sigma = 0.6 template void bilateral06 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(768,1) #pragma omp for BL_OPER3(1,4,4,16) BL_FREE #pragma omp for BL_END(1) } // sigma = 0.7 template void bilateral07 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(366,2) #pragma omp for BL_OPER5(0,0,1,0,8,21,1,21,59) BL_FREE #pragma omp for BL_END(2) } // sigma = 0.8 template void bilateral08 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(753,2) #pragma omp for BL_OPER5(0,0,1,0,5,10,1,10,23) BL_FREE #pragma omp for BL_END(2) } // sigma = 0.9 template void bilateral09 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(595,2) #pragma omp for BL_OPER5(0,1,2,1,6,12,2,12,22) BL_FREE #pragma omp for BL_END(2) } // sigma = 1.0 template void bilateral10 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(910,2) #pragma omp for BL_OPER5(0,1,2,1,4,7,2,7,12) BL_FREE #pragma omp for BL_END(2) } // sigma = 1.1 template void bilateral11 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(209,3) #pragma omp for BL_OPER7(0,0,1,1,0,2,5,8,1,5,18,27,1,8,27,41) BL_FREE #pragma omp for BL_END(3) } // sigma = 1.2 template void bilateral12 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(322,3) #pragma omp for BL_OPER7(0,0,1,1,0,1,4,6,1,4,11,16,1,6,16,23) BL_FREE #pragma omp for BL_END(3) } // sigma = 1.3 template void bilateral13 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(336,3) #pragma omp for BL_OPER7(0,0,1,1,0,2,4,6,1,4,11,14,1,6,14,19) BL_FREE #pragma omp for BL_END(3) } // sigma = 1.4 template void bilateral14 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(195,3) #pragma omp for BL_OPER7(0,1,2,3,1,4,8,10,2,8,17,21,3,10,21,28) BL_FREE #pragma omp for BL_END(3) } // sigma = 1.5 template void bilateral15 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(132,4) #pragma omp for BL_OPER9(0,0,0,1,1,0,1,2,4,5,0,2,6,12,14,1,4,12,22,28,1,5,14,28,35) BL_FREE #pragma omp for BL_END(4) } // sigma = 1.6 template void bilateral16 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(180,4) #pragma omp for BL_OPER9(0,0,0,1,1,0,1,2,3,4,0,2,5,9,10,1,3,9,15,19,1,4,10,19,23) BL_FREE #pragma omp for BL_END(4) } // sigma = 1.7 template void bilateral17 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(195,4) #pragma omp for BL_OPER9(0,0,1,1,1,0,1,2,3,4,1,2,5,8,9,1,3,8,13,16,1,4,9,16,19) BL_FREE #pragma omp for BL_END(4) } // sigma = 1.8 template void bilateral18 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(151,4) #pragma omp for BL_OPER9(0,0,1,2,2,0,1,3,5,5,1,3,6,10,12,2,5,10,16,19,2,5,12,19,22) BL_FREE #pragma omp for BL_END(4) } // sigma = 1.9 template void bilateral19 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(151,4) #pragma omp for BL_OPER9(0,0,1,2,2,0,1,3,4,5,1,3,5,8,9,2,4,8,12,14,2,5,9,14,16) BL_FREE #pragma omp for BL_END(4) } // sigma = 2 template void bilateral20 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(116,5) #pragma omp for BL_OPER11(0,0,0,1,1,1,0,0,1,2,3,3,0,1,2,4,7,7,1,2,4,8,12,14,1,3,7,12,18,20,1,3,7,14,20,23) BL_FREE #pragma omp for BL_END(5) } // sigma = 2.1 template void bilateral21 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(127,5) #pragma omp for BL_OPER11(0,0,0,1,1,1,0,0,1,2,3,3,0,1,2,4,6,7,1,2,4,8,11,12,1,3,6,11,15,17,1,3,7,12,17,19) BL_FREE #pragma omp for BL_END(5) } // sigma = 2.2 template void bilateral22 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(109,5) #pragma omp for BL_OPER11(0,0,0,1,1,2,0,1,2,3,3,4,1,2,3,5,7,8,1,3,5,9,12,13,1,3,7,12,16,18,2,4,8,13,18,20) BL_FREE #pragma omp for BL_END(5) } // sigma = 2.3 template void bilateral23 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(132,5) #pragma omp for BL_OPER11(0,0,1,1,1,1,0,1,1,2,3,3,1,1,3,5,6,7,1,2,5,7,10,11,1,3,6,10,13,14,1,3,7,11,14,16) BL_FREE #pragma omp for BL_END(5) } // sigma = 2.4 template void bilateral24 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(156,5) #pragma omp for BL_OPER11(0,0,1,1,1,1,0,1,1,2,3,3,1,1,3,4,5,6,1,2,4,6,8,9,1,3,5,8,10,11,1,3,6,9,11,12) BL_FREE #pragma omp for BL_END(5) } // sigma = 2.5 template void bilateral25 (T** src, T** dst, T** buffer, int W, int H, double sens, bool multiThread) { BL_BEGIN(173,5) #pragma omp for BL_OPER11(0,0,1,1,1,1,0,1,1,2,3,3,1,1,2,4,5,5,1,2,4,5,7,7,1,3,5,7,9,9,1,3,5,7,9,10) BL_FREE #pragma omp for BL_END(5) } // main bilateral filter template void bilateral (T** src, T** dst, T** buffer, int W, int H, double sigma, double sens, bool multiThread) { //parallel if (multiThread) if (sigma<0.45) #ifdef _OPENMP #pragma omp for #endif for (int i=0; i (src, dst, buffer, W, H, sens, multiThread); else if (sigma<0.65) bilateral06 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<0.75) bilateral07 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<0.85) bilateral08 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<0.95) bilateral09 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.05) bilateral10 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.15) bilateral11 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.25) bilateral12 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.35) bilateral13 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.45) bilateral14 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.55) bilateral15 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.65) bilateral16 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.75) bilateral17 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.85) bilateral18 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<1.95) bilateral19 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<2.05) bilateral20 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<2.15) bilateral21 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<2.25) bilateral22 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<2.35) bilateral23 (src, dst, buffer, W, H, sens, multiThread); else if (sigma<2.45) bilateral24 (src, dst, buffer, W, H, sens, multiThread); else bilateral25 (src, dst, buffer, W, H, sens, multiThread); } // START OF EXPERIMENTAL CODE: O(1) bilateral box filter // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define BINBIT 7 //bit depth of histogram -- there are 2^BINBIT discrete levels #define TRANSBIT 9 //bit shift = 16-BINBIT taking short ints to bit depth BINBIT template void bilateral (T** src, T** dst, int W, int H, int sigmar, double sigmas, int row_from, int row_to) { // range weights /*LUTf ec(0x20000); for (int i=0; i<0x20000; i++) ec[i] = exp(-(double)(i-0x10000)*(double)(i-0x10000) / (2.0*sigmar*sigmar)); */ // histogram LUTu hist (1< buff_final(W,H,ARRAY2D_CLEAR_DATA); int r = sigmas; // calculate histogram at the beginning of the row rhist.clear(); for (int x = MAX(0,row_from-r); x<=MIN(H,row_from+r); x++) for (int y = 0; y>TRANSBIT]++; sigmar*=2; for (int i=row_from; ir) for (int x = 0; x<=MIN(H,r); x++) rhist[((int)src[i-r-1][x])>>TRANSBIT]--; if (i>TRANSBIT]++; hist=rhist; for (int j=0; jr) for (int x=MAX(0,i-r); x<=MIN(i+r,H-1); x++) hist[(int)(src[x][j-r-1])>>TRANSBIT]--; if (j>TRANSBIT]++; // calculate pixel value float totwt = 0.0, weight; for (int k=0; k<=(sigmar>>TRANSBIT); k++) { float w = 1.0 - (double)k/(sigmar>>TRANSBIT); int v = (int)(src[i][j])>>TRANSBIT; //float frac = ((float)(src[i][j]-(v<= 0) { weight = hist [v-k/*+frac*/] * w; totwt += weight; buff_final[i][j] += weight * (src[i][j]-(k<