/* * 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 . */ #include #include #ifdef _OPENMP #include #endif #include #include #include namespace rtengine { #undef CLIP #undef CMAXVAL #undef ABS #define CMAXVAL 0xffff #define CLIP(a) ((a)>0?((a)sharpening.enabled==false || params->sharpening.deconvamount<1) return; int W = lab->W, H = lab->H; float** tmpI = new float*[H]; for (int i=0; iL[i][j]; } float** tmp = (float**)b2; #ifdef _OPENMP #pragma omp parallel #endif { AlignedBuffer* buffer = new AlignedBuffer (MAX(W,H)); float damping = params->sharpening.deconvdamping / 5.0; bool needdamp = params->sharpening.deconvdamping > 0; for (int k=0; ksharpening.deconviter; k++) { // apply blur function (gaussian blur) gaussHorizontal (tmpI, tmp, buffer, W, H, params->sharpening.deconvradius / scale, multiThread); gaussVertical (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale, multiThread); if (!needdamp) { #ifdef _OPENMP #pragma omp for #endif for (int i=0; i0) tmp[i][j] = (float)lab->L[i][j] / tmp[i][j]; } else dcdamping (tmp, lab->L, damping, W, H); gaussHorizontal (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale, multiThread); gaussVertical (tmp, tmp, buffer, W, H, params->sharpening.deconvradius / scale, multiThread); #ifdef _OPENMP #pragma omp for #endif for (int i=0; iL[i][j] = lab->L[i][j]*(100-params->sharpening.deconvamount) / 100 + (int)CLIP(tmpI[i][j])*params->sharpening.deconvamount / 100; for (int i=0; isharpening.method=="rld") { deconvsharpening (lab, b2); return; } if (params->sharpening.enabled==false || params->sharpening.amount<1 || lab->W<8 || lab->H<8) return; int W = lab->W, H = lab->H; #ifdef _OPENMP #pragma omp parallel #endif { unsigned short** b3; AlignedBuffer* buffer = new AlignedBuffer (MAX(W,H)); if (params->sharpening.edgesonly==false) { gaussHorizontal (lab->L, b2, buffer, W, H, params->sharpening.radius / scale, multiThread); gaussVertical (b2, b2, buffer, W, H, params->sharpening.radius / scale, multiThread); } else { b3 = new unsigned short*[H]; for (int i=0; i (lab->L, (unsigned short**)b3, b2, W, H, params->sharpening.edges_radius / scale, params->sharpening.edges_tolerance, multiThread); gaussHorizontal (b3, b2, buffer, W, H, params->sharpening.radius / scale, multiThread); gaussVertical (b2, b2, buffer, W, H, params->sharpening.radius / scale, multiThread); } delete buffer; unsigned short** base = lab->L; if (params->sharpening.edgesonly) base = b3; if (params->sharpening.halocontrol==false) { #pragma omp for for (int i=0; iparams->sharpening.threshold) { int val = lab->L[i][j] + params->sharpening.amount * diff / 100; lab->L[i][j] = CLIP(val); } } } else sharpenHaloCtrl (lab, b2, base, W, H); if (params->sharpening.edgesonly) { for (int i=0; isharpening.halocontrol_amount); unsigned short** nL = base; #pragma omp parallel for if (multiThread) for (int i=2; i params->sharpening.threshold) { // compute maximum/minimum in a delta environment np1 = 2*(nL[i-2][j] + nL[i-2][j+1] + nL[i-2][j+2] + nL[i-1][j] + nL[i-1][j+1] + nL[i-1][j+2] + nL[i][j] + nL[i][j+1] + nL[i][j+2]) / 27 + nL[i-1][j+1] / 3; np2 = 2*(nL[i-1][j] + nL[i-1][j+1] + nL[i-1][j+2] + nL[i][j] + nL[i][j+1] + nL[i][j+2] + nL[i+1][j] + nL[i+1][j+1] + nL[i+1][j+2]) / 27 + nL[i][j+1] / 3; np3 = 2*(nL[i][j] + nL[i][j+1] + nL[i][j+2] + nL[i+1][j] + nL[i+1][j+1] + nL[i+1][j+2] + nL[i+2][j] + nL[i+2][j+1] + nL[i+2][j+2]) / 27 + nL[i+1][j+1] / 3; MINMAX3(np1,np2,np3,maxn,minn); MAX3(max1,max2,maxn,max); MIN3(min1,min2,minn,min); max1 = max2; max2 = maxn; min1 = min2; min2 = minn; if (max < lab->L[i][j]) max = lab->L[i][j]; if (min > lab->L[i][j]) min = lab->L[i][j]; int val = lab->L[i][j] + params->sharpening.amount * diff / 100; int newL = CLIP(val); // applying halo control if (newL > max) newL = max + (newL-max) * scale / 10000; else if (newLL[i][j] = newL; } } } } }