~ubuntu-branches/ubuntu/saucy/digikam/saucy

« back to all changes in this revision

Viewing changes to core/libs/dimg/filters/lens/lensfunfilter.cpp

  • Committer: Package Import Robot
  • Author(s): Felix Geyer, Rohan Garg, Philip Muškovac, Felix Geyer
  • Date: 2011-09-23 18:18:55 UTC
  • mfrom: (1.2.36 upstream)
  • Revision ID: package-import@ubuntu.com-20110923181855-ifs67wxkugshev9k
Tags: 2:2.1.1-0ubuntu1
[ Rohan Garg ]
* New upstream release (LP: #834190)
  - debian/control
    + Build with libqtwebkit-dev
 - debian/kipi-plugins-common
    + Install libkvkontakte required by kipi-plugins
 - debian/digikam
    + Install panoramagui

[ Philip Muškovac ]
* New upstream release
  - debian/control:
    + Add libcv-dev, libcvaux-dev, libhighgui-dev, libboost-graph1.46-dev,
      libksane-dev, libxml2-dev, libxslt-dev, libqt4-opengl-dev, libqjson-dev,
      libgpod-dev and libqca2-dev to build-deps
    + Add packages for kipi-plugins, libmediawiki, libkface, libkgeomap and
      libkvkontakte
  - debian/rules:
    + Don't build with gphoto2 since it doesn't build with it.
  - Add kubuntu_fix_test_linking.diff to fix linking of the dngconverter test
  - update install files
  - update kubuntu_01_mysqld_executable_name.diff for new cmake layout
    and rename to kubuntu_mysqld_executable_name.diff
* Fix typo in digikam-data description (LP: #804894)
* Fix Vcs links

[ Felix Geyer ]
* Move library data files to the new packages libkface-data, libkgeomap-data
  and libkvkontakte-data.
* Override version of the embedded library packages to 1.0~digikam<version>.
* Exclude the library packages from digikam-dbg to prevent file conflicts in
  the future.
* Call dh_install with --list-missing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ============================================================
 
2
 *
 
3
 * Date        : 2008-02-10
 
4
 * Description : a tool to fix automatically camera lens aberrations
 
5
 *
 
6
 * Copyright (C) 2008 by Adrian Schroeter <adrian at suse dot de>
 
7
 * Copyright (C) 2008-2010 by Gilles Caulier <caulier dot gilles at gmail dot com>
 
8
 *
 
9
 * This program is free software; you can redistribute it
 
10
 * and/or modify it under the terms of the GNU General
 
11
 * Public License as published by the Free Software Foundation;
 
12
 * either version 2, or (at your option) any later version.
 
13
 *
 
14
 * This program is distributed in the hope that it will be useful,
 
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
17
 * GNU General Public License for more details.
 
18
 *
 
19
 * ============================================================ */
 
20
 
 
21
#include "lensfunfilter.h"
 
22
 
 
23
// Qt includes
 
24
 
 
25
#include <QByteArray>
 
26
#include <QCheckBox>
 
27
#include <QString>
 
28
 
 
29
// KDE includes
 
30
 
 
31
#include <kdebug.h>
 
32
 
 
33
// Local includes
 
34
 
 
35
#include "lensfuniface.h"
 
36
#include "dmetadata.h"
 
37
 
 
38
namespace Digikam
 
39
{
 
40
 
 
41
class LensFunFilter::LensFunFilterPriv
 
42
{
 
43
public:
 
44
 
 
45
    LensFunFilterPriv()
 
46
    {
 
47
        iface    = 0;
 
48
        modifier = 0;
 
49
    }
 
50
 
 
51
    LensFunIface* iface;
 
52
 
 
53
    lfModifier*   modifier;
 
54
};
 
55
 
 
56
LensFunFilter::LensFunFilter(QObject* parent)
 
57
    : DImgThreadedFilter(parent),
 
58
      d(new LensFunFilterPriv)
 
59
{
 
60
    d->iface = new LensFunIface;
 
61
    initFilter();
 
62
}
 
63
 
 
64
LensFunFilter::LensFunFilter(DImg* orgImage, QObject* parent,  const LensFunContainer& settings)
 
65
    : DImgThreadedFilter(orgImage, parent, "LensCorrection"),
 
66
      d(new LensFunFilterPriv)
 
67
{
 
68
    d->iface = new LensFunIface;
 
69
    d->iface->setSettings(settings);
 
70
    initFilter();
 
71
}
 
72
 
 
73
LensFunFilter::~LensFunFilter()
 
74
{
 
75
    cancelFilter();
 
76
 
 
77
    if (d->modifier)
 
78
    {
 
79
        d->modifier->Destroy();
 
80
    }
 
81
 
 
82
    delete d->iface;
 
83
    delete d;
 
84
}
 
85
 
 
86
void LensFunFilter::filterImage()
 
87
{
 
88
    m_destImage.bitBltImage(&m_orgImage, 0, 0);
 
89
 
 
90
    if (!d->iface)
 
91
    {
 
92
        kError() << "ERROR: LensFun Interface is null.";
 
93
        return;
 
94
    }
 
95
 
 
96
    if (!d->iface->usedLens())
 
97
    {
 
98
        kError() << "ERROR: LensFun Interface Lens device is null.";
 
99
        return;
 
100
    }
 
101
 
 
102
    // Lensfun Modifier flags to process
 
103
 
 
104
    int modifyFlags = 0;
 
105
 
 
106
    if ( d->iface->settings().filterDST )
 
107
    {
 
108
        modifyFlags |= LF_MODIFY_DISTORTION;
 
109
    }
 
110
 
 
111
    if ( d->iface->settings().filterGEO )
 
112
    {
 
113
        modifyFlags |= LF_MODIFY_GEOMETRY;
 
114
    }
 
115
 
 
116
    if ( d->iface->settings().filterCCA )
 
117
    {
 
118
        modifyFlags |= LF_MODIFY_TCA;
 
119
    }
 
120
 
 
121
    if ( d->iface->settings().filterVIG )
 
122
    {
 
123
        modifyFlags |= LF_MODIFY_VIGNETTING;
 
124
    }
 
125
 
 
126
    if ( d->iface->settings().filterCCI )
 
127
    {
 
128
        modifyFlags |= LF_MODIFY_CCI;
 
129
    }
 
130
 
 
131
    // Init lensfun lib, we are working on the full image.
 
132
 
 
133
    lfPixelFormat colorDepth = m_orgImage.bytesDepth() == 4 ? LF_PF_U8 : LF_PF_U16;
 
134
 
 
135
    d->modifier = lfModifier::Create(d->iface->usedLens(),
 
136
                                     d->iface->settings().cropFactor,
 
137
                                     m_orgImage.width(),
 
138
                                     m_orgImage.height());
 
139
 
 
140
    int modflags = d->modifier->Initialize(d->iface->usedLens(),
 
141
                                           colorDepth,
 
142
                                           d->iface->settings().focalLength,
 
143
                                           d->iface->settings().aperture,
 
144
                                           d->iface->settings().subjectDistance,
 
145
                                           d->iface->settings().cropFactor,
 
146
                                           LF_RECTILINEAR,
 
147
                                           modifyFlags,
 
148
                                           0/*no inverse*/);
 
149
 
 
150
    if (!d->modifier)
 
151
    {
 
152
        kError() << "ERROR: cannot initialize LensFun Modifier.";
 
153
        return;
 
154
    }
 
155
 
 
156
    // Calc necessary steps for progress bar
 
157
 
 
158
    int steps = ( d->iface->settings().filterCCA                                   ) ? 1 : 0 +
 
159
                ( d->iface->settings().filterVIG || d->iface->settings().filterCCI ) ? 1 : 0 +
 
160
                ( d->iface->settings().filterDST || d->iface->settings().filterGEO ) ? 1 : 0;
 
161
 
 
162
    kDebug() << "LensFun Modifier Flags: " << modflags << "  Steps:" << steps;
 
163
 
 
164
    if ( steps < 1 )
 
165
    {
 
166
        kDebug() << "No LensFun Modifier steps. There is nothing to process...";
 
167
        return;
 
168
    }
 
169
 
 
170
    // The real correction to do
 
171
 
 
172
    int loop   = 0;
 
173
    int lwidth = m_orgImage.width() * 2 * 3;
 
174
    float* pos = new float[lwidth];
 
175
 
 
176
    kDebug() << "Image size to process: (" << m_orgImage.width() << ", " << m_orgImage.height() << ")";
 
177
 
 
178
    // Stage 1: Chromatic Aberation Corrections
 
179
 
 
180
    if ( d->iface->settings().filterCCA )
 
181
    {
 
182
        m_orgImage.prepareSubPixelAccess(); // init lanczos kernel
 
183
 
 
184
        for (unsigned int y=0; runningFlag() && (y < m_orgImage.height()); ++y)
 
185
        {
 
186
            if (d->modifier->ApplySubpixelDistortion(0.0, y, m_orgImage.width(), 1, pos))
 
187
            {
 
188
                float* src = pos;
 
189
 
 
190
                for (unsigned x = 0; runningFlag() && (x < m_destImage.width()); ++x)
 
191
                {
 
192
                    DColor destPixel(0, 0, 0, 0xFFFF, m_destImage.sixteenBit());
 
193
 
 
194
                    destPixel.setRed  (m_orgImage.getSubPixelColorFast(src[0], src[1]).red()   );
 
195
                    destPixel.setGreen(m_orgImage.getSubPixelColorFast(src[2], src[3]).green() );
 
196
                    destPixel.setBlue (m_orgImage.getSubPixelColorFast(src[4], src[5]).blue()  );
 
197
 
 
198
                    m_destImage.setPixelColor(x, y, destPixel);
 
199
                    src += 2 * 3;
 
200
                }
 
201
 
 
202
                ++loop;
 
203
            }
 
204
 
 
205
            // Update progress bar in dialog.
 
206
            int progress = (int)(((double)y * 100.0) / m_orgImage.height());
 
207
 
 
208
            if (progress%5 == 0)
 
209
            {
 
210
                postProgress(progress/steps);
 
211
            }
 
212
        }
 
213
 
 
214
        kDebug() << "Chromatic Aberation Corrections applied. (loop: " << loop << ")";
 
215
    }
 
216
 
 
217
    // Stage 2: Color Corrections: Vignetting and Color Contribution Index
 
218
 
 
219
    if ( d->iface->settings().filterVIG || d->iface->settings().filterCCI )
 
220
    {
 
221
        uchar* data   = m_destImage.bits();
 
222
        loop          = 0;
 
223
        double offset = 0.0;
 
224
 
 
225
        if ( steps == 3 )
 
226
        {
 
227
            offset = 33.3;
 
228
        }
 
229
        else if (steps == 2 && d->iface->settings().filterCCA)
 
230
        {
 
231
            offset = 50.0;
 
232
        }
 
233
 
 
234
        for (unsigned int y=0; runningFlag() && (y < m_destImage.height()); ++y)
 
235
        {
 
236
            if (d->modifier->ApplyColorModification(data, 0.0, y, m_destImage.width(),
 
237
                                                    1, m_destImage.bytesDepth(), 0))
 
238
            {
 
239
                data += m_destImage.height() * m_destImage.bytesDepth();
 
240
                ++loop;
 
241
            }
 
242
 
 
243
            // Update progress bar in dialog.
 
244
            int progress = (int)(((double)y * 100.0) / m_destImage.height());
 
245
 
 
246
            if (progress%5 == 0)
 
247
            {
 
248
                postProgress(progress/steps + offset);
 
249
            }
 
250
        }
 
251
 
 
252
        kDebug() << "Vignetting and Color Corrections applied. (loop: " << loop << ")";
 
253
    }
 
254
 
 
255
    // Stage 3: Distortion and Geometry Corrections
 
256
 
 
257
    if ( d->iface->settings().filterDST || d->iface->settings().filterGEO )
 
258
    {
 
259
        loop = 0;
 
260
 
 
261
        // we need a deep copy first
 
262
        DImg tempImage(m_destImage.width(), m_destImage.height(), m_destImage.sixteenBit(), m_destImage.hasAlpha());
 
263
        m_destImage.prepareSubPixelAccess(); // init lanczos kernel
 
264
 
 
265
        for (unsigned long y=0; runningFlag() && (y < tempImage.height()); ++y)
 
266
        {
 
267
            if (d->modifier->ApplyGeometryDistortion(0.0, y, tempImage.width(), 1, pos))
 
268
            {
 
269
                float* src = pos;
 
270
 
 
271
                for (unsigned long x = 0; runningFlag() && (x < tempImage.width()); ++x, ++loop)
 
272
                {
 
273
                    //kDebug() << " ZZ " << src[0] << " " << src[1] << " " << (int)src[0] << " " << (int)src[1];
 
274
 
 
275
                    tempImage.setPixelColor(x, y, m_destImage.getSubPixelColor(src[0], src[1]));
 
276
                    src += 2;
 
277
                }
 
278
            }
 
279
 
 
280
            // Update progress bar in dialog.
 
281
            int progress = (int)(((double)y * 100.0) / tempImage.height());
 
282
 
 
283
            if (progress%5 == 0)
 
284
            {
 
285
                postProgress(progress/steps + 33.3*(steps-1));
 
286
            }
 
287
        }
 
288
 
 
289
        kDebug() << "Distortion and Geometry Corrections applied. (loop: " << loop << ")";
 
290
 
 
291
        if (loop != 0)
 
292
        {
 
293
            m_destImage = tempImage;
 
294
        }
 
295
    }
 
296
 
 
297
    // clean up
 
298
 
 
299
    delete [] pos;
 
300
}
 
301
 
 
302
bool LensFunFilter::registerSettingsToXmp(KExiv2Data& data) const
 
303
{
 
304
    // Register in digiKam Xmp namespace all information about Lens corrections.
 
305
 
 
306
    QString str;
 
307
    LensFunContainer prm = d->iface->settings();
 
308
 
 
309
    str.append(i18n("Camera: %1-%2",        prm.cameraMake, prm.cameraModel));
 
310
    str.append("\n");
 
311
    str.append(i18n("Lens: %1",             prm.lensModel));
 
312
    str.append("\n");
 
313
    str.append(i18n("Subject Distance: %1", QString::number(prm.subjectDistance)));
 
314
    str.append("\n");
 
315
    str.append(i18n("Aperture: %1",         QString::number(prm.aperture)));
 
316
    str.append("\n");
 
317
    str.append(i18n("Focal Length: %1",     QString::number(prm.focalLength)));
 
318
    str.append("\n");
 
319
    str.append(i18n("Crop Factor: %1",      QString::number(prm.cropFactor)));
 
320
    str.append("\n");
 
321
    str.append(i18n("CCA Correction: %1",   prm.filterCCA  && d->iface->supportsCCA()        ? i18n("enabled") : i18n("disabled")));
 
322
    str.append("\n");
 
323
    str.append(i18n("VIG Correction: %1",   prm.filterVIG  && d->iface->supportsVig()        ? i18n("enabled") : i18n("disabled")));
 
324
    str.append("\n");
 
325
    str.append(i18n("CCI Correction: %1",   prm.filterCCI  && d->iface->supportsCCI()        ? i18n("enabled") : i18n("disabled")));
 
326
    str.append("\n");
 
327
    str.append(i18n("DST Correction: %1",   prm.filterDST && d->iface->supportsDistortion() ? i18n("enabled") : i18n("disabled")));
 
328
    str.append("\n");
 
329
    str.append(i18n("GEO Correction: %1",   prm.filterGEO && d->iface->supportsGeometry()   ? i18n("enabled") : i18n("disabled")));
 
330
 
 
331
    DMetadata meta(data);
 
332
    bool ret = meta.setXmpTagString("Xmp.digiKam.LensCorrectionSettings",
 
333
                                    str.replace("\n", " ; "), false);
 
334
    data = meta.data();
 
335
 
 
336
    return ret;
 
337
}
 
338
 
 
339
FilterAction LensFunFilter::filterAction()
 
340
{
 
341
    FilterAction action(FilterIdentifier(), CurrentVersion());
 
342
    action.setDisplayableName(DisplayableName());
 
343
 
 
344
    LensFunContainer prm = d->iface->settings();
 
345
    action.addParameter("ccaCorrection", prm.filterCCA);
 
346
    action.addParameter("vigCorrection", prm.filterVIG);
 
347
    action.addParameter("cciCorrection", prm.filterCCI);
 
348
    action.addParameter("dstCorrection", prm.filterDST);
 
349
    action.addParameter("geoCorrection", prm.filterGEO);
 
350
    action.addParameter("cropFactor", prm.cropFactor);
 
351
    action.addParameter("focalLength", prm.focalLength);
 
352
    action.addParameter("aperture", prm.aperture);
 
353
    action.addParameter("subjectDistance", prm.subjectDistance);
 
354
    action.addParameter("cameraMake", prm.cameraMake);
 
355
    action.addParameter("cameraModel", prm.cameraModel);
 
356
    action.addParameter("lensModel", prm.lensModel);
 
357
 
 
358
    return action;
 
359
}
 
360
 
 
361
void LensFunFilter::readParameters(const Digikam::FilterAction& action)
 
362
{
 
363
    LensFunContainer prm = d->iface->settings();
 
364
    prm.filterCCA   = action.parameter("ccaCorrection").toBool();
 
365
    prm.filterVIG   = action.parameter("vigCorrection").toBool();
 
366
    prm.filterCCI   = action.parameter("cciCorrection").toBool();
 
367
    prm.filterDST   = action.parameter("dstCorrection").toBool();
 
368
    prm.filterGEO   = action.parameter("geoCorrection").toBool();
 
369
    prm.cropFactor  = action.parameter("cropFactor").toDouble();
 
370
    prm.focalLength = action.parameter("focalLength").toDouble();
 
371
    prm.aperture    = action.parameter("aperture").toDouble();
 
372
    prm.subjectDistance = action.parameter("subjectDistance").toDouble();
 
373
    prm.cameraMake  = action.parameter("cameraMake").toString();
 
374
    prm.cameraModel = action.parameter("cameraModel").toString();
 
375
    prm.lensModel   = action.parameter("lensModel").toString();
 
376
    d->iface->setSettings(prm);
 
377
}
 
378
 
 
379
}  // namespace Digikam