/* * * Copyright (C) 2006-2011 Anders Brander , * * Anders Kvist and Klaus Post * * This program 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 2 * of the License, or (at your option) any later version. * * This program 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 this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * * Based on FFT3DFilter plugin for Avisynth 2.5 - 3D Frequency Domain filter * Copyright(C)2004-2005 A.G.Balakhnin aka Fizick, email: bag@hotmail.ru, web: http://bag.hotmail.ru */ #include "complexfilter.h" #include #include "fftwindow.h" /* * These classes define the processing that must be done * to each block. * Note that the process() function must be re-entrant, * as all threads will use the same instance for each plane. * */ #ifndef MAX #define MAX(x,y) ((x) > (y) ? (x) : (y)) #endif namespace RawStudio { namespace FFTFilter { /**** BASE CLASS *****/ ComplexFilter::ComplexFilter( int block_width, int block_height ) : bw(block_width), bh(block_height), norm(1.0f/(block_width*block_height)), sharpen(0), sigmaSquaredSharpenMin(0), sigmaSquaredSharpenMax(0), sharpenWindow(0) {} ComplexFilter::~ComplexFilter(void) { if (sharpenWindow) delete sharpenWindow; sharpenWindow = 0; } void ComplexFilter::setSharpen( float _sharpen, float sigmaSharpenMin, float sigmaSharpenMax, float scutoff ) { if (ABS(_sharpen) <0.001f) return; sharpen = _sharpen; sigmaSquaredSharpenMin = sigmaSharpenMin*sigmaSharpenMin/norm; sigmaSquaredSharpenMax = sigmaSharpenMax*sigmaSharpenMax/norm; // window for sharpen float svr = 1.0f; // Horizontal to vertical ratio if (!sharpenWindow) { sharpenWindow = new FloatImagePlane(bw, bh); sharpenWindow->allocateImage(); } for (int j=0; j=bh/2) dj = bh-j; float d2v = float(dj*dj)*(svr*svr)/((bh/2)*(bh/2)); float *wsharpen = sharpenWindow->getLine(j); for (int i=0; i0.001f) processSharpen(block); else processNoSharpen(block); } gboolean ComplexFilter::skipBlock() { if (ABS(sharpen) >0.001f) return false; return true; } /** DeGridComplexFilter **/ DeGridComplexFilter::DeGridComplexFilter(int block_width, int block_height, float _degrid, FFTWindow *_window, fftwf_plan plan_forward) : ComplexFilter(block_width, block_height), degrid(_degrid), window(_window) { grid = new ComplexBlock(bw, bh); FloatImagePlane realGrid(bw, bh); realGrid.allocateImage(); float* f = realGrid.data; int count = bh*realGrid.pitch; for (int i = 0 ; i < count; i++){ f[i] = 65535.0f; } window->applyAnalysisWindow(&realGrid,&realGrid); fftwf_execute_dft_r2c(plan_forward, f, grid->complex); } DeGridComplexFilter::~DeGridComplexFilter( void ) { delete grid; } void DeGridComplexFilter::processSharpenOnly(ComplexBlock* block) { #if defined (__i386__) || defined (__x86_64__) guint cpu = rs_detect_cpu_features(); if (cpu & RS_CPU_FLAG_SSE3) return processSharpenOnlySSE3(block); else if (cpu & RS_CPU_FLAG_SSE) return processSharpenOnlySSE(block); #endif int x,y; fftwf_complex* outcur = block->complex; fftwf_complex* gridsample = grid->complex; float gridfraction = degrid*outcur[0][0]/gridsample[0][0]; for (y=0; ygetLine(y); for (x=0; x0.001f) return false; if (sigmaSquaredNoiseNormed > 1e-15f) return false; return true; } void ComplexWienerFilter::processNoSharpen( ComplexBlock* block ) { int x,y; float psd; float WienerFactor; fftwf_complex* outcur = block->complex; g_assert(bw == block->w); g_assert(bh == block->h); for (y=0; ycomplex; g_assert(bw == block->w); g_assert(bh == block->h); for (y=0; ygetLine(y); for (x=0; xw); g_assert(bh == block->h); int x,y; float psd; fftwf_complex* outcur = block->complex; float* pattern2d = pattern->data; float patternfactor; for (y=0; ypitch; } } void ComplexPatternFilter::processSharpen( ComplexBlock* block ) { g_assert(!"Not implemented"); } gboolean ComplexPatternFilter::skipBlock() { if (ABS(sharpen) >0.001f) return false; if (pfactor > 1e-15f) return false; return true; } ComplexWienerFilterDeGrid::ComplexWienerFilterDeGrid( int block_width, int block_height, float _beta, float _sigma, float _degrid, fftwf_plan plan_forward, FFTWindow *_window) : DeGridComplexFilter(block_width, block_height, _degrid, _window, plan_forward) { lowlimit = (_beta-1)/_beta; sigmaSquaredNoiseNormed = _sigma*_sigma/norm; } ComplexWienerFilterDeGrid::~ComplexWienerFilterDeGrid( void ) { } gboolean ComplexWienerFilterDeGrid::skipBlock() { if (ABS(sharpen) >0.001f) return false; if (sigmaSquaredNoiseNormed > 1e-15f) return false; return true; } void ComplexWienerFilterDeGrid::processNoSharpen( ComplexBlock* block ) { if (sigmaSquaredNoiseNormed <= 1e-15f) return; #if defined (__i386__) || defined (__x86_64__) guint cpu = rs_detect_cpu_features(); if (cpu & RS_CPU_FLAG_SSE3) return processNoSharpen_SSE3(block); else if (cpu & RS_CPU_FLAG_SSE) return processNoSharpen_SSE(block); #endif int x,y; float psd; float WienerFactor; fftwf_complex* outcur = block->complex; fftwf_complex* gridsample = grid->complex; float gridfraction = degrid*outcur[0][0]/gridsample[0][0]; for (y=0; ycomplex; fftwf_complex* gridsample = grid->complex; float gridfraction = degrid*outcur[0][0]/gridsample[0][0]; for (y=0; ygetLine(y); for (x=0; xcomplex; fftwf_complex* gridsample = grid->complex; float gridfraction = degrid*outcur[0][0]/gridsample[0][0]; for (y=0; ygetLine(y); for (x=0; xcomplex; fftwf_complex* gridsample = grid->complex; float gridfraction = degrid*outcur[0][0]/gridsample[0][0]; for (y=0; ygetLine(y); float *wsharpen = sharpenWindow->getLine(y); for (x=0; x