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

« back to all changes in this revision

Viewing changes to libs/dimg/filters/lens/pixelaccess.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
 
 * This file is a part of digiKam project
4
 
 * http://www.digikam.org
5
 
 *
6
 
 * Date        : 2004-12-27
7
 
 * Description : access pixels method for lens distortion algorithm.
8
 
 *
9
 
 * Copyright (C) 2004-2010 by Gilles Caulier <caulier dot gilles at gmail dot com>
10
 
 * Copyright (C) 2006-2010 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
11
 
 *
12
 
 * This program is free software; you can redistribute it
13
 
 * and/or modify it under the terms of the GNU General
14
 
 * Public License as published by the Free Software Foundation;
15
 
 * either version 2, or (at your option)
16
 
 * any later version.
17
 
 *
18
 
 * This program is distributed in the hope that it will be useful,
19
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
 
 * GNU General Public License for more details.
22
 
 *
23
 
 * ============================================================ */
24
 
 
25
 
#include "pixelaccess.h"
26
 
 
27
 
// C++ includes
28
 
 
29
 
#include <cstring>
30
 
#include <cmath>
31
 
#include <cstdlib>
32
 
 
33
 
namespace Digikam
34
 
{
35
 
 
36
 
PixelAccess::PixelAccess(DImg* srcImage)
37
 
{
38
 
    m_image       = srcImage;
39
 
 
40
 
    m_width       = PixelAccessWidth;
41
 
    m_height      = PixelAccessHeight;
42
 
 
43
 
    m_depth       = m_image->bytesDepth();
44
 
    m_imageWidth  = m_image->width();
45
 
    m_imageHeight = m_image->height();
46
 
    m_sixteenBit  = m_image->sixteenBit();
47
 
 
48
 
    for ( int i = 0 ; i < PixelAccessRegions ; ++i )
49
 
    {
50
 
        m_buffer[i] = new DImg(m_image->copy(0, 0, m_width, m_height));
51
 
 
52
 
        m_tileMinX[i] = 1;
53
 
        m_tileMaxX[i] = m_width - 2;
54
 
        m_tileMinY[i] = 1;
55
 
        m_tileMaxY[i] = m_height - 2;
56
 
    }
57
 
}
58
 
 
59
 
PixelAccess::~PixelAccess()
60
 
{
61
 
    for ( int i = 0 ; i < PixelAccessRegions ; ++i )
62
 
    {
63
 
        delete m_buffer[i];
64
 
    }
65
 
}
66
 
 
67
 
uchar* PixelAccess::pixelAccessAddress(int i, int j)
68
 
{
69
 
    return m_buffer[0]->bits() + m_depth * (m_width * (j + 1 - m_tileMinY[0]) + (i + 1 - m_tileMinX[0]));
70
 
}
71
 
 
72
 
// Swap region[n] with region[0].
73
 
void PixelAccess::pixelAccessSelectRegion(int n)
74
 
{
75
 
    DImg* temp;
76
 
    int    a, b, c, d;
77
 
    int    i;
78
 
 
79
 
    temp = m_buffer[n];
80
 
    a    = m_tileMinX[n];
81
 
    b    = m_tileMaxX[n];
82
 
    c    = m_tileMinY[n];
83
 
    d    = m_tileMaxY[n];
84
 
 
85
 
    for ( i = n ; i > 0 ; --i)
86
 
    {
87
 
        m_buffer[i]   = m_buffer[i-1];
88
 
        m_tileMinX[i] = m_tileMinX[i-1];
89
 
        m_tileMaxX[i] = m_tileMaxX[i-1];
90
 
        m_tileMinY[i] = m_tileMinY[i-1];
91
 
        m_tileMaxY[i] = m_tileMaxY[i-1];
92
 
    }
93
 
 
94
 
    m_buffer[0]   = temp;
95
 
    m_tileMinX[0] = a;
96
 
    m_tileMaxX[0] = b;
97
 
    m_tileMinY[0] = c;
98
 
    m_tileMaxY[0] = d;
99
 
}
100
 
 
101
 
// Buffer[0] is cleared, should start at [i, j], fill rows that overlap image.
102
 
void PixelAccess::pixelAccessDoEdge(int i, int j)
103
 
{
104
 
    int    lineStart, lineEnd;
105
 
    int    rowStart, rowEnd;
106
 
    int    lineWidth;
107
 
    uchar* line;
108
 
 
109
 
    lineStart = i;
110
 
 
111
 
    if (lineStart < 0)
112
 
    {
113
 
        lineStart = 0;
114
 
    }
115
 
 
116
 
    lineEnd = i + m_width;
117
 
 
118
 
    if (lineEnd > m_imageWidth)
119
 
    {
120
 
        lineEnd = m_imageWidth;
121
 
    }
122
 
 
123
 
    lineWidth = lineEnd - lineStart;
124
 
 
125
 
    if ( lineStart >= lineEnd )
126
 
    {
127
 
        return;
128
 
    }
129
 
 
130
 
    rowStart = j;
131
 
 
132
 
    if (rowStart < 0)
133
 
    {
134
 
        rowStart = 0;
135
 
    }
136
 
 
137
 
    rowEnd = j + m_height;
138
 
 
139
 
    if (rowEnd > m_imageHeight)
140
 
    {
141
 
        rowEnd = m_imageHeight;
142
 
    }
143
 
 
144
 
    for ( int y = rowStart ; y < rowEnd ; ++y )
145
 
    {
146
 
        line = pixelAccessAddress(lineStart, y);
147
 
        memcpy(line, m_image->scanLine(y) + lineStart * m_depth, lineWidth * m_depth);
148
 
    }
149
 
}
150
 
 
151
 
// Moves buffer[0] so that [x, y] is inside it.
152
 
void PixelAccess::pixelAccessReposition(int xInt, int yInt)
153
 
{
154
 
    int newStartX = xInt - PixelAccessXOffset;
155
 
    int newStartY = yInt - PixelAccessYOffset;
156
 
 
157
 
    m_tileMinX[0] = newStartX + 1;
158
 
    m_tileMaxX[0] = newStartX + m_width - 2;
159
 
    m_tileMinY[0] = newStartY + 1;
160
 
    m_tileMaxY[0] = newStartY + m_height - 2;
161
 
 
162
 
 
163
 
    if ( (newStartX < 0) || ((newStartX + m_width) >= m_imageWidth) ||
164
 
         (newStartY < 0) || ((newStartY + m_height) >= m_imageHeight) )
165
 
    {
166
 
        // some data is off edge of image
167
 
 
168
 
        m_buffer[0]->fill(DColor(0,0,0,0, m_sixteenBit));
169
 
 
170
 
        // This could probably be done by bitBltImage but I did not figure out how,
171
 
        // so leave the working code here. And no, it is not this:
172
 
        //m_buffer[0]->bitBltImage(m_image, newStartX, newStartY, m_width, m_height, 0, 0);
173
 
 
174
 
        if ( ((newStartX + m_width) < 0) || (newStartX >= m_imageWidth) ||
175
 
             ((newStartY + m_height) < 0) || (newStartY >= m_imageHeight) )
176
 
        {
177
 
            // totally outside, just leave it.
178
 
        }
179
 
        else
180
 
        {
181
 
            pixelAccessDoEdge(newStartX, newStartY);
182
 
        }
183
 
    }
184
 
    else
185
 
    {
186
 
        m_buffer[0]->bitBltImage(m_image, newStartX, newStartY, m_width, m_height, 0, 0);
187
 
    }
188
 
}
189
 
 
190
 
void PixelAccess::pixelAccessGetCubic(double srcX, double srcY, double brighten, uchar* dst)
191
 
{
192
 
    int    xInt, yInt;
193
 
    double dx, dy;
194
 
    uchar* corner;
195
 
 
196
 
    xInt = (int)floor(srcX);
197
 
    dx   = srcX - xInt;
198
 
    yInt = (int)floor(srcY);
199
 
    dy   = srcY - yInt;
200
 
 
201
 
    // We need 4x4 pixels, xInt-1 to xInt+2 horz, yInt-1 to yInt+2 vert
202
 
    // they're probably in the last place we looked...
203
 
 
204
 
    if ((xInt >= m_tileMinX[0]) && (xInt < m_tileMaxX[0]) &&
205
 
        (yInt >= m_tileMinY[0]) && (yInt < m_tileMaxY[0]) )
206
 
    {
207
 
        corner = pixelAccessAddress(xInt - 1, yInt - 1);
208
 
        cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten);
209
 
        return;
210
 
    }
211
 
 
212
 
    // Or maybe it was a while back...
213
 
 
214
 
    for ( int i = 1 ; i < PixelAccessRegions ; ++i)
215
 
    {
216
 
        if ((xInt >= m_tileMinX[i]) && (xInt < m_tileMaxX[i]) &&
217
 
            (yInt >= m_tileMinY[i]) && (yInt < m_tileMaxY[i]) )
218
 
        {
219
 
            // Check here first next time
220
 
 
221
 
            pixelAccessSelectRegion(i);
222
 
            corner = pixelAccessAddress(xInt - 1, yInt - 1);
223
 
            cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten);
224
 
            return;
225
 
        }
226
 
    }
227
 
 
228
 
    // Nope, recycle an old region.
229
 
 
230
 
    pixelAccessSelectRegion(PixelAccessRegions - 1);
231
 
    pixelAccessReposition(xInt, yInt);
232
 
 
233
 
    corner = pixelAccessAddress(xInt - 1, yInt - 1);
234
 
    cubicInterpolate(corner, m_depth * m_width, dst, m_sixteenBit, dx, dy, brighten);
235
 
}
236
 
 
237
 
/*
238
 
 * Catmull-Rom cubic interpolation
239
 
 *
240
 
 * equally spaced points p0, p1, p2, p3
241
 
 * interpolate 0 <= u < 1 between p1 and p2
242
 
 *
243
 
 * (1 u u^2 u^3) (  0.0  1.0  0.0  0.0 ) (p0)
244
 
 *               ( -0.5  0.0  0.5  0.0 ) (p1)
245
 
 *               (  1.0 -2.5  2.0 -0.5 ) (p2)
246
 
 *               ( -0.5  1.5 -1.5  0.5 ) (p3)
247
 
 *
248
 
 */
249
 
void PixelAccess::cubicInterpolate(uchar* src, int rowStride, uchar* dst,
250
 
                                   bool sixteenBit, double dx, double dy, double brighten)
251
 
{
252
 
    float um1, u, up1, up2;
253
 
    float vm1, v, vp1, vp2;
254
 
    int   c;
255
 
    const int numberOfComponents = 4;
256
 
    float verts[4 * numberOfComponents];
257
 
 
258
 
    um1 = ((-0.5 * dx + 1.0) * dx - 0.5) * dx;
259
 
    u   = (1.5 * dx - 2.5) * dx * dx + 1.0;
260
 
    up1 = ((-1.5 * dx + 2.0) * dx + 0.5) * dx;
261
 
    up2 = (0.5 * dx - 0.5) * dx * dx;
262
 
 
263
 
    vm1 = ((-0.5 * dy + 1.0) * dy - 0.5) * dy;
264
 
    v   = (1.5 * dy - 2.5) * dy * dy + 1.0;
265
 
    vp1 = ((-1.5 * dy + 2.0) * dy + 0.5) * dy;
266
 
    vp2 = (0.5 * dy - 0.5) * dy * dy;
267
 
 
268
 
    if (sixteenBit)
269
 
    {
270
 
        unsigned short* src16 = (unsigned short*)src;
271
 
        unsigned short* dst16 = (unsigned short*)dst;
272
 
 
273
 
        // for each component, read the values of 4 pixels into array
274
 
 
275
 
        for (c = 0 ; c < 4 * numberOfComponents ; ++c)
276
 
        {
277
 
            verts[c] = vm1 * src16[c] + v * src16[c+rowStride] + vp1 * src16[c+rowStride*2] + vp2 * src16[c+rowStride*3];
278
 
        }
279
 
 
280
 
        // for each component, compute resulting value from array
281
 
 
282
 
        for (c = 0 ; c < numberOfComponents ; ++c)
283
 
        {
284
 
            float result;
285
 
            result = um1 * verts[c] + u * verts[c+numberOfComponents]
286
 
                     + up1 * verts[c+numberOfComponents*2] + up2 * verts[c+numberOfComponents*3];
287
 
            result *= brighten;
288
 
 
289
 
            if (result < 0.0)
290
 
            {
291
 
                dst16[c] = 0;
292
 
            }
293
 
            else if (result > 65535.0)
294
 
            {
295
 
                dst16[c] = 65535;
296
 
            }
297
 
            else
298
 
            {
299
 
                dst16[c] = (uint)result;
300
 
            }
301
 
        }
302
 
    }
303
 
    else
304
 
    {
305
 
        for (c = 0 ; c < 4 * numberOfComponents ; ++c)
306
 
        {
307
 
            verts[c] = vm1 * src[c] + v * src[c+rowStride] + vp1 * src[c+rowStride*2] + vp2 * src[c+rowStride*3];
308
 
        }
309
 
 
310
 
        for (c = 0 ; c < numberOfComponents ; ++c)
311
 
        {
312
 
            float result;
313
 
            result = um1 * verts[c] + u * verts[c+numberOfComponents]
314
 
                     + up1 * verts[c+numberOfComponents*2] + up2 * verts[c+numberOfComponents*3];
315
 
            result *= brighten;
316
 
 
317
 
            if (result < 0.0)
318
 
            {
319
 
                dst[c] = 0;
320
 
            }
321
 
            else if (result > 255.0)
322
 
            {
323
 
                dst[c] = 255;
324
 
            }
325
 
            else
326
 
            {
327
 
                dst[c] = (uint)result;
328
 
            }
329
 
        }
330
 
    }
331
 
}
332
 
 
333
 
}  // namespace Digikam