/* * 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 "mytime.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) #ifdef _OPENMP #pragma omp for #endif BL_OPER3(1, 7, 7, 55) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER3(1, 4, 4, 16) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER5(0, 0, 1, 0, 8, 21, 1, 21, 59) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER5(0, 0, 1, 0, 5, 10, 1, 10, 23) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER5(0, 1, 2, 1, 6, 12, 2, 12, 22) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER5(0, 1, 2, 1, 4, 7, 2, 7, 12) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER7(0, 0, 1, 1, 0, 2, 5, 8, 1, 5, 18, 27, 1, 8, 27, 41) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER7(0, 0, 1, 1, 0, 1, 4, 6, 1, 4, 11, 16, 1, 6, 16, 23) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER7(0, 0, 1, 1, 0, 2, 4, 6, 1, 4, 11, 14, 1, 6, 14, 19) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif BL_OPER7(0, 1, 2, 3, 1, 4, 8, 10, 2, 8, 17, 21, 3, 10, 21, 28) BL_FREE #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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) #ifdef _OPENMP #pragma omp for #endif 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 #ifdef _OPENMP #pragma omp for #endif 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 < H; i++) { memcpy (buffer[i], src[i], W * sizeof(T)); memcpy (dst[i], buffer[i], W * sizeof(T)); } else if (sigma < 0.55) { bilateral05 (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 << BINBIT); LUTu rhist(1 << BINBIT); // buffer for the final image /*float** buff_final = new float*[H]; float * real_buff_final = new float[W*H]; for (int i=0; i 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 < r + 1; y++) { rhist[((int)src[x][y]) >> TRANSBIT]++; } sigmar *= 2; for (int i = row_from; i < row_to; i++) { // calculate histogram at the beginning of the row if (i > r) for (int x = 0; x <= MIN(H, r); x++) { rhist[((int)src[i - r - 1][x]) >> TRANSBIT]--; } if (i < H - r) for (int x = 0; x <= MIN(H, r); x++) { rhist[((int)src[i + r][x]) >> TRANSBIT]++; } hist = rhist; for (int j = 0; j < W; j++) { // subtract pixels at the left and add pixels at the right if (j > r) for (int x = MAX(0, i - r); x <= MIN(i + r, H - 1); x++) { hist[(int)(src[x][j - r - 1]) >> TRANSBIT]--; } if (j < W - r) for (int x = MAX(0, i - r); x <= MIN(i + r, H - 1); x++) { hist[((int)src[x][j + r]) >> 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 << TRANSBIT)); } if (v + k < (1 << BINBIT)) { weight = hist [v + k/*+frac*/] * w; totwt += weight; buff_final[i][j] += weight * (src[i][j] + (k << TRANSBIT)); } } buff_final[i][j] /= totwt; } } for (int i = row_from; i < row_to; i++) for (int j = 0; j < W; j++) { dst[i][j] = (T)CLIP(buff_final[i][j]); } //delete [] real_buff_final; //delete [] buff_final; } #undef BINBIT #undef TRANSBIT #endif