/* * 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 #include #include #ifdef _OPENMP #include #endif // 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]+0x10000]) #define SULY(a,b) (ec[src[i - a][j - b]-src[i][j]+0x10000]) #define BL_BEGIN(a,b) double scale = (a); \ int* ec = new int [0x20000]; \ for (int i=0; i<0x20000; i++) \ ec[i] = (int)(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_END(b) buffer[i][j] = v; }} delete [] ec; \ 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 parallel for if (multiThread) BL_OPER3(1,7,7,55) 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 parallel for if (multiThread) BL_OPER3(1,4,4,16) 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 parallel for if (multiThread) BL_OPER5(0,0,1,0,8,21,1,21,59) 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 parallel for if (multiThread) BL_OPER5(0,0,1,0,5,10,1,10,23) 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 parallel for if (multiThread) BL_OPER5(0,1,2,1,6,12,2,12,22) 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 parallel for if (multiThread) BL_OPER5(0,1,2,1,4,7,2,7,12) 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 parallel for if (multiThread) BL_OPER7(0,0,1,1,0,2,5,8,1,5,18,27,1,8,27,41) 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 parallel for if (multiThread) BL_OPER7(0,0,1,1,0,1,4,6,1,4,11,16,1,6,16,23) 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 parallel for if (multiThread) BL_OPER7(0,0,1,1,0,2,4,6,1,4,11,14,1,6,14,19) 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 parallel for if (multiThread) BL_OPER7(0,1,2,3,1,4,8,10,2,8,17,21,3,10,21,28) 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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 parallel for if (multiThread) 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_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 MAXVAL 0xffff #define CLIP(a) ((a)>0?((a) void bilateral (T** src, T** dst, int W, int H, int sigmar, double sigmas, int row_from, int row_to) { // range weights double* ec = new double [0x20000]; for (int i=0; i<0x20000; i++) ec[i] = exp(-(double)(i-0x10000)*(double)(i-0x10000) / (2.0*sigmar*sigmar)); // histogram unsigned short* hist = new unsigned short[1<>TRANSBIT]++; sigmar*=2; for (int i=row_from; ir) for (int x = 0; x>TRANSBIT]--; if (i>TRANSBIT]++; memcpy (hist, rhist, (1<r) for (int x=MAX(0,i-r); x<=MIN(i+r,H-1); x++) hist[src[x][j-r-1]>>TRANSBIT]--; if (j>TRANSBIT]++; // calculate pixel value float weight = 0.0; for (int k=0; k<=(sigmar>>TRANSBIT); k++) { float w = 1.0 - (double)k/(sigmar>>TRANSBIT); int v = src[i][j]>>TRANSBIT; if (v-k >= 0) { weight += hist [v-k] * w; buff_final[i][j] += hist [v-k] * w * (src[i][j]-(k<