~ubuntu-branches/ubuntu/vivid/rawstudio/vivid

« back to all changes in this revision

Viewing changes to plugins/denoise/fftdenoiser.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Bernd Zeimetz
  • Date: 2011-07-28 17:36:32 UTC
  • mfrom: (2.1.11 upstream)
  • Revision ID: james.westby@ubuntu.com-20110728173632-5czluz9ye3c83zc5
Tags: 2.0-1
* [3750b2cf] Merge commit 'upstream/2.0'
* [63637468] Removing Patch, not necessary anymore.
* [2fb580dc] Add new build-dependencies.
* [c57d953b] Run dh_autoreconf due to patches in configure.in
* [13febe39] Add patch to remove the libssl requirement.
* [5ae773fe] Replace libjpeg62-dev by libjpeg8-dev :)
* [1969d755] Don't build static libraries.
* [7cfe0a2e] Add a patch to fix the plugin directory path.
  As plugins are shared libraries, they need to go into /usr/lib,
  not into /usr/share.
  Thanks to Andrew McMillan
* [c1d0d9dd] Don't install .la files for all plugins and libraries.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * * Copyright (C) 2006-2011 Anders Brander <anders@brander.dk>, 
 
3
 * * Anders Kvist <akv@lnxbx.dk> and Klaus Post <klauspost@gmail.com>
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this program; if not, write to the Free Software
 
17
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 
18
 */
 
19
 
 
20
#include "fftdenoiser.h"
 
21
#include "complexblock.h"
 
22
#include "fftdenoiseryuv.h"
 
23
 
 
24
#ifdef WIN32
 
25
int rs_get_number_of_processor_cores(){return 4;}
 
26
#endif
 
27
 
 
28
namespace RawStudio {
 
29
namespace FFTFilter {
 
30
 
 
31
 
 
32
FFTDenoiser::FFTDenoiser(void)
 
33
{
 
34
  nThreads = rs_get_number_of_processor_cores();
 
35
  threads = new DenoiseThread[nThreads];
 
36
  initializeFFT();
 
37
  FloatPlanarImage::initConvTable();
 
38
}
 
39
 
 
40
FFTDenoiser::~FFTDenoiser(void)
 
41
{
 
42
  delete[] threads;
 
43
  fftwf_destroy_plan(plan_forward);
 
44
  fftwf_destroy_plan(plan_reverse); 
 
45
}
 
46
 
 
47
void FFTDenoiser::denoiseImage( RS_IMAGE16* image )
 
48
{
 
49
  FloatPlanarImage img;
 
50
  img.bw = FFT_BLOCK_SIZE;
 
51
  img.bh = FFT_BLOCK_SIZE;
 
52
  img.ox = FFT_BLOCK_OVERLAP;
 
53
  img.oy = FFT_BLOCK_OVERLAP;
 
54
 
 
55
  if ((image->w < FFT_BLOCK_SIZE) || (image->h < FFT_BLOCK_SIZE))
 
56
     return;   // Image too small to denoise
 
57
 
 
58
  if (image->channels > 1 && image->filters==0) {
 
59
     img.unpackInterleaved(image);
 
60
  } else {
 
61
    return;
 
62
  }
 
63
  if (abort) return;
 
64
 
 
65
  img.mirrorEdges();
 
66
  if (abort) return;
 
67
 
 
68
  FFTWindow window(img.bw,img.bh);
 
69
  window.createHalfCosineWindow(img.ox, img.oy);
 
70
  
 
71
  ComplexFilter *filter = new ComplexWienerFilterDeGrid(img.bw, img.bh, beta, sigma, 1.0, plan_forward, &window);
 
72
  filter->setSharpen(sharpen, sharpenMinSigma, sharpenMaxSigma, sharpenCutoff);
 
73
  img.setFilter(0,filter,&window);
 
74
 
 
75
  filter = new ComplexWienerFilterDeGrid(img.bw, img.bh, beta, sigma, 1.0, plan_forward, &window);
 
76
  filter->setSharpen(sharpen, sharpenMinSigma, sharpenMaxSigma, sharpenCutoff);
 
77
  img.setFilter(1,filter,&window);
 
78
 
 
79
  filter = new ComplexWienerFilterDeGrid(img.bw, img.bh, beta, sigma, 1.0, plan_forward, &window);
 
80
  filter->setSharpen(sharpen, sharpenMinSigma, sharpenMaxSigma, sharpenCutoff);
 
81
  img.setFilter(2,filter,&window);
 
82
 
 
83
  FloatPlanarImage outImg(img);
 
84
 
 
85
  processJobs(img, outImg);
 
86
  if (abort) return;
 
87
 
 
88
  // Convert back
 
89
  if (image->channels > 1 && image->filters==0) {
 
90
     outImg.packInterleaved(image);
 
91
  }
 
92
}
 
93
 
 
94
void FFTDenoiser::processJobs(FloatPlanarImage &img, FloatPlanarImage &outImg)
 
95
{
 
96
  // Prepare for reassembling the image
 
97
  outImg.allocate_planes();
 
98
  // Split input image
 
99
  JobQueue* waiting_jobs = img.getJobs(outImg);
 
100
  JobQueue* finished_jobs = new JobQueue();
 
101
 
 
102
  // Count waiting jobs
 
103
  gint njobs = waiting_jobs->jobsLeft();
 
104
 
 
105
  for (guint i = 0; i < nThreads; i++) {
 
106
    threads[i].addJobs(waiting_jobs,finished_jobs);
 
107
  }
 
108
 
 
109
 
 
110
  gint jobs_added  = 0;
 
111
  while (jobs_added < njobs) {
 
112
    Job *_j = finished_jobs->waitForJob();
 
113
 
 
114
    if (_j->type == JOB_FFT) {
 
115
      delete _j;
 
116
      jobs_added++;
 
117
      if (abort) {
 
118
        jobs_added += waiting_jobs->removeRemaining();
 
119
        jobs_added += finished_jobs->removeRemaining();
 
120
      }
 
121
    }
 
122
  }
 
123
 
 
124
  for (guint i = 0; i < nThreads; i++)
 
125
    threads[i].jobsEnded();
 
126
 
 
127
  delete finished_jobs;
 
128
  delete waiting_jobs;
 
129
}
 
130
 
 
131
void FFTDenoiser::waitForJobs(JobQueue *waiting_jobs)
 
132
{
 
133
  JobQueue* finished_jobs = new JobQueue();
 
134
 
 
135
  gint njobs = waiting_jobs->jobsLeft();
 
136
 
 
137
  for (guint i = 0; i < nThreads; i++) {
 
138
    threads[i].addJobs(waiting_jobs,finished_jobs);
 
139
  }
 
140
 
 
141
  gint jobs_added  = 0;
 
142
  while (jobs_added < njobs) {
 
143
    Job *j = finished_jobs->waitForJob();
 
144
    delete j;
 
145
    jobs_added++;
 
146
  }
 
147
 
 
148
  for (guint i = 0; i < nThreads; i++)
 
149
    threads[i].jobsEnded();
 
150
  
 
151
  delete waiting_jobs;
 
152
  delete finished_jobs;
 
153
}
 
154
 
 
155
gboolean FFTDenoiser::initializeFFT()
 
156
{
 
157
  // Create dummy block
 
158
  FloatImagePlane plane(FFT_BLOCK_SIZE,FFT_BLOCK_SIZE);
 
159
  plane.allocateImage();
 
160
  ComplexBlock complex(FFT_BLOCK_SIZE,FFT_BLOCK_SIZE);
 
161
  int dim[2];
 
162
  dim[0] = FFT_BLOCK_SIZE;
 
163
  dim[1] = FFT_BLOCK_SIZE;
 
164
  plan_forward = fftwf_plan_dft_r2c(2, dim, plane.data, complex.complex,FFTW_MEASURE|FFTW_DESTROY_INPUT);
 
165
  plan_reverse = fftwf_plan_dft_c2r(2, dim, complex.complex, plane.data,FFTW_MEASURE|FFTW_DESTROY_INPUT);
 
166
  for (guint i = 0; i < nThreads; i++) {
 
167
    threads[i].forward = plan_forward;
 
168
    threads[i].reverse = plan_reverse;
 
169
  }
 
170
  return (plan_forward && plan_reverse);
 
171
}
 
172
 
 
173
 
 
174
void FFTDenoiser::setParameters( FFTDenoiseInfo *info )
 
175
{
 
176
  sigma = info->sigmaLuma *SIGMA_FACTOR;
 
177
  beta = max(1.0f, info->betaLuma);
 
178
  sharpen = info->sharpenLuma;
 
179
  sharpenCutoff = info->sharpenCutoffLuma;
 
180
  sharpenMinSigma = info->sharpenMinSigmaLuma*SIGMA_FACTOR;
 
181
  sharpenMaxSigma = info->sharpenMaxSigmaLuma*SIGMA_FACTOR;
 
182
}
 
183
 
 
184
}}// namespace RawStudio::FFTFilter
 
185
 
 
186
extern "C" {
 
187
 
 
188
  /** INTERFACE **/
 
189
 
 
190
  void initDenoiser(FFTDenoiseInfo* info) {
 
191
    RawStudio::FFTFilter::FFTDenoiser *t;
 
192
    switch (info->processMode) {
 
193
    case PROCESS_RGB:
 
194
      t = new RawStudio::FFTFilter::FFTDenoiser();
 
195
      break;
 
196
    case PROCESS_YUV:
 
197
      t = new RawStudio::FFTFilter::FFTDenoiserYUV();
 
198
      break;
 
199
    default:
 
200
      g_assert(false);
 
201
    }
 
202
    info->_this = t;
 
203
    // Initialize parameters to default
 
204
    info->betaLuma = 1.0f;
 
205
        info->betaChroma = 1.0f;
 
206
        info->sigmaLuma = 1.0f;
 
207
    info->sigmaChroma = 1.0f;
 
208
    info->sharpenLuma = 0.0f;
 
209
    info->sharpenChroma = 0.0f;
 
210
    info->sharpenCutoffLuma = 0.10f;
 
211
    info->sharpenCutoffChroma = 0.3f;
 
212
    info->sharpenMinSigmaLuma = 4.0f;
 
213
    info->sharpenMinSigmaChroma = 4.0f;
 
214
    info->sharpenMaxSigmaLuma = 20.0f;
 
215
    info->sharpenMaxSigmaChroma = 20.0f;
 
216
    info->redCorrection = 1.0f;
 
217
    info->blueCorrection = 1.0f;
 
218
  }
 
219
 
 
220
  void denoiseImage(FFTDenoiseInfo* info) {
 
221
    RawStudio::FFTFilter::FFTDenoiser *t = (RawStudio::FFTFilter::FFTDenoiser*)info->_this;  
 
222
    t->abort = false;
 
223
    t->setParameters(info);
 
224
    t->denoiseImage(info->image);
 
225
  }
 
226
 
 
227
  void destroyDenoiser(FFTDenoiseInfo* info) {
 
228
    RawStudio::FFTFilter::FFTDenoiser *t = (RawStudio::FFTFilter::FFTDenoiser*)info->_this;  
 
229
    delete t;
 
230
  }
 
231
 
 
232
  void abortDenoiser(FFTDenoiseInfo* info) {
 
233
    RawStudio::FFTFilter::FFTDenoiser *t = (RawStudio::FFTFilter::FFTDenoiser*)info->_this;
 
234
    t->abort = true;
 
235
  }
 
236
 
 
237
} // extern "C"
 
238