/* * 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 . * D. J. Jobson, Z. Rahman, and G. A. Woodell. A multi-scale * Retinex for bridging the gap between color images and the * human observation of scenes. IEEE Transactions on Image Processing, * 1997, 6(7): 965-976 * inspired from 2003 Fabien Pelisson */ #include #include #include #include #include #include "rtengine.h" #include "gauss.h" #include "rawimagesource.h" #include "improcfun.h" #include "opthelper.h" #include "StopWatch.h" #define MAX_DEHAZE_SCALES 6 #define clipdehaz( val, minv, maxv ) (( val = (val < minv ? minv : val ) ) > maxv ? maxv : val ) namespace rtengine { extern const Settings* settings; static float DehazeScales[MAX_DEHAZE_SCALES]; void dehaze_scales( float* scales, int nscales, int mode, int s) { if ( nscales == 1 ) { scales[0] = (float)s / 2.f; } else if (nscales == 2) { scales[0] = (float) s / 2.f; scales[1] = (float) s; } else { float size_step = (float) s / (float) nscales; if(mode==0) { for (int i = 0; i < nscales; ++i ) scales[i] = 2.0f + (float)i * size_step; } else if (mode==1) { size_step = (float)log(s - 2.0f) / (float) nscales; for (int i = 0; i < nscales; ++i ) scales[i] = 2.0f + (float)pow (10.f, (i * size_step) / log (10.f)); } else if(mode==2){ size_step = (float) log(s - 2.0f) / (float) nscales; for ( int i = 0; i < nscales; ++i ) scales[i] = s - (float)pow (10.f, (i * size_step) / log (10.f)); } } } void mean_stddv( float **dst, float &mean, float &stddv, int W_L, int H_L ) { float vsquared = 0.f; float sum = 0.f; #pragma omp parallel for reduction(+:sum,vsquared) // this leads to differences, but parallel summation is more accurate for (int i = 0; i L[i][j] + eps; } } dehaze_scales( DehazeScales, scal, modedehaz, nei ); pond = 1.0f / (float) scal; for ( int scale = 0; scale < scal; scale++ ) { #ifdef _OPENMP #pragma omp parallel #endif { AlignedBufferMP* pBuffer = new AlignedBufferMP (max(W_L, H_L)); gaussHorizontal (src, out, *pBuffer, W_L, H_L, DehazeScales[scale]); gaussVertical (out, out, *pBuffer,W_L, H_L, DehazeScales[scale]); delete pBuffer; } #ifdef __SSE2__ #ifdef _OPENMP #pragma omp parallel { vfloat pondv = F2V(pond); #pragma omp for #endif for ( int i=0; i < H_L; i++) { int j; for (j=0; j < W_L-3; j+=4) { _mm_storeu_ps(&dst[i][j], LVFU(dst[i][j]) + pondv * ( xlogf(LVFU(src[i][j])/LVFU(out[i][j])) )); } for (;j < W_L; j++) { dst[i][j] += pond * ( xlogf((src[i][j])/out[i][j]) ); } } } #else #ifdef _OPENMP #pragma omp parallel for #endif for ( int i=0; i < H_L; i++) for (int j=0; j < W_L; j++) { dst[i][j] += pond * ( xlogf((src[i][j])/out[i][j]) ); } #endif } for (int i = 0; i < H_L; i++) { delete [] out[i]; } delete [] out; for (int i = 0; i < H_L; i++) { delete [] src[i]; } delete [] src; float beta=16384.0f; float logBetaGain = xlogf(beta) * gain; #ifdef _OPENMP #pragma omp parallel for #endif for (int i=0; i< H_L; i++ ) for (int j=0; jL[i][j]=((1.f - strength)* lab->L[i][j] + strength * clipdehaz( cd, 0.f, 32768.f )); } for (int i = 0; i < H_L; i++) { delete [] dst[i]; } delete [] dst; } } }