~ubuntu-branches/ubuntu/trusty/digikam/trusty

« back to all changes in this revision

Viewing changes to extra/kipi-plugins/videoslideshow/magickiface/processimage.cpp

  • Committer: Package Import Robot
  • Author(s): Mark Purcell
  • Date: 2012-09-27 21:41:30 UTC
  • mfrom: (1.2.43)
  • mto: This revision was merged to the branch mainline in revision 86.
  • Revision ID: package-import@ubuntu.com-20120927214130-i8v3ufr21nesp29i
Tags: 4:3.0.0~beta1a-1
* New upstream release

* Fix "wrongly conflicts phonon-backend-vlc" dropped (Closes: #688142)
* debian/watch include download.kde.org

* digikam 3.0.0 uses features from unreleased kdegraphics >=4.10 & ships 
a private version of the kdegraphics libs - this is not the Debian way :-(
* Unsatisfactory Conflicts: libkipi8, libkexiv2-10, libkdcraw20, libksane0
* Suspend digikam-dbg >130Mb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/** ===========================================================
 
2
 * @file
 
3
 *
 
4
 * This file is a part of digiKam project
 
5
 * <a href="http://www.digikam.org">http://www.digikam.org</a>
 
6
 *
 
7
 * @date   2012-06-01
 
8
 * @brief  Transitions, AspectRatioCorrection and otherImageEffects
 
9
 *
 
10
 * @author Copyright (C) 2012 by A Janardhan Reddy <annapareddyjanardhanreddy at gmail dot com>
 
11
 *         Copyright (C) 2012 by Gilles Caulier <caulier dot gilles at gmail dot com>
 
12
 *
 
13
 * This program is free software; you can redistribute it
 
14
 * and/or modify it under the terms of the GNU General
 
15
 * Public License as published by the Free Software Foundation;
 
16
 * either version 2, or (at your option)
 
17
 * any later version.
 
18
 *
 
19
 * This program is distributed in the hope that it will be useful,
 
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
22
 * GNU General Public License for more details.
 
23
 *
 
24
 * ============================================================ */
 
25
 
 
26
#include "processimage.moc"
 
27
 
 
28
// C++ includes
 
29
 
 
30
#include <cmath>
 
31
 
 
32
// Local includes
 
33
 
 
34
#include "magickiface.h"
 
35
 
 
36
#define INC(v) incValue(v, step, steps)
 
37
#define DEC(v) decValue(v, step, steps)
 
38
 
 
39
namespace KIPIPlugins
 
40
{
 
41
 
 
42
ProcessImage::ProcessImage(MagickApi* const api)
 
43
{
 
44
    m_api = api;
 
45
}
 
46
 
 
47
MagickImage* ProcessImage::aspectRatioCorrection(MagickImage& img, double aspectratio, ASPECTCORRECTION_TYPE aspectcorrection)
 
48
{
 
49
    MagickImage* newimg    = 0;
 
50
    double img_aspectratio = (double) img.getWidth() / (double) img.getHeight();
 
51
 
 
52
    // tolerate some error in double value
 
53
    if(abs(img_aspectratio - aspectratio) <= 0.001)
 
54
        return &img;
 
55
 
 
56
    if (aspectcorrection == ASPECTCORRECTION_TYPE_AUTO)
 
57
    {
 
58
        // find out whether we should use fitin, fillin or none
 
59
        if (img_aspectratio > 1.0)
 
60
            aspectcorrection = ASPECTCORRECTION_TYPE_FILLIN;
 
61
        else
 
62
            aspectcorrection = ASPECTCORRECTION_TYPE_FITIN;
 
63
    }
 
64
 
 
65
    switch (aspectcorrection)
 
66
    {
 
67
        case ASPECTCORRECTION_TYPE_FITIN:
 
68
            //fit in with black bars
 
69
            if (img_aspectratio < aspectratio)
 
70
            {
 
71
                // resulting image will have black bars on right and left side
 
72
                if (!(newimg = m_api->createImage("black", img.getHeight() * aspectratio,img.getHeight())))
 
73
                    Q_EMIT signalProcessError("couldn't create image\n");
 
74
 
 
75
                m_api->overlayImage(*newimg, (newimg->getWidth() - img.getWidth()) / 2,0, img);
 
76
            }
 
77
            else
 
78
            {
 
79
                // resulting image will have black bars on top and bottom
 
80
                if (!(newimg = m_api->createImage("black", img.getHeight() * aspectratio, img.getHeight())))
 
81
                    Q_EMIT signalProcessError("couldn't create image\n");
 
82
 
 
83
                m_api->overlayImage(*newimg, 0, (newimg->getHeight() - img.getHeight()) / 2, img);
 
84
            }
 
85
            break;
 
86
 
 
87
        case ASPECTCORRECTION_TYPE_FILLIN:
 
88
            // part of image is cut off
 
89
            if (img_aspectratio < aspectratio)
 
90
            {
 
91
                // cut on top and bottom side
 
92
                if (!(newimg = m_api->createImage("black", img.getHeight() * aspectratio, img.getHeight())))
 
93
                    Q_EMIT signalProcessError("couldn't create image\n");
 
94
 
 
95
                m_api->bitblitImage(*newimg, 0, 0, img, 0, (img.getHeight() - newimg->getHeight()) / 2, newimg->getWidth(), newimg->getHeight());
 
96
            }
 
97
            else
 
98
            {
 
99
                // cut on right and left side
 
100
                if (!(newimg = m_api->createImage("black", img.getHeight() * aspectratio, img.getHeight())))
 
101
                    Q_EMIT signalProcessError("couldn't create image\n");
 
102
 
 
103
                m_api->bitblitImage(*newimg, 0, 0, img,(img.getWidth() - newimg->getWidth()) / 2,0, newimg->getWidth(), newimg->getHeight());
 
104
            }
 
105
            break;
 
106
 
 
107
        case ASPECTCORRECTION_TYPE_NONE:
 
108
        default:
 
109
            // no correction needed
 
110
            break;
 
111
    }
 
112
 
 
113
    if (newimg)
 
114
    {
 
115
        // swap the images if we got a new one
 
116
        m_api->freeImage(img);
 
117
        img = *newimg;
 
118
    }
 
119
    return &img;
 
120
}
 
121
 
 
122
int ProcessImage::incValue(int v, int step, int steps) const
 
123
{
 
124
    return (v) * (step + 1) / steps;
 
125
}
 
126
 
 
127
int ProcessImage::decValue(int v, int step, int steps) const
 
128
{
 
129
    return (v) * (steps - step - 1) / steps;
 
130
}
 
131
 
 
132
MagickImage* ProcessImage::transition(const MagickImage& from, const MagickImage& to, int type, int step, int steps)
 
133
{
 
134
    int w, h;
 
135
 
 
136
    if (step < 0 || step >= steps)
 
137
        Q_EMIT signalProcessError(QString("step: %1 is out of range (%2)").arg(step).arg(steps));
 
138
 
 
139
    // create a new target image and copy the from image onto
 
140
    MagickImage* const dst = m_api->createImage("black", w = from.getWidth(), h = from.getHeight());
 
141
 
 
142
    switch (type)
 
143
    {
 
144
        // sliding
 
145
 
 
146
        case TRANSITION_TYPE_SLIDE_L2R:
 
147
            m_api->overlayImage(*dst, 0,       0, from);
 
148
            m_api->overlayImage(*dst, DEC(-w), 0, to);
 
149
            break;
 
150
 
 
151
        case TRANSITION_TYPE_SLIDE_R2L:
 
152
            m_api->overlayImage(*dst, 0,      0, from);
 
153
            m_api->overlayImage(*dst, DEC(w), 0, to);
 
154
            break;
 
155
 
 
156
        case TRANSITION_TYPE_SLIDE_T2B:
 
157
            m_api->overlayImage(*dst, 0, 0,       from);
 
158
            m_api->overlayImage(*dst, 0, DEC(-h), to);
 
159
            break;
 
160
 
 
161
        case TRANSITION_TYPE_SLIDE_B2T:
 
162
            m_api->overlayImage(*dst, 0, 0,      from);
 
163
            m_api->overlayImage(*dst, 0, DEC(h), to);
 
164
            break;
 
165
 
 
166
        // pushing
 
167
 
 
168
        case TRANSITION_TYPE_PUSH_L2R:
 
169
            m_api->overlayImage(*dst, INC(w),  0, from);
 
170
            m_api->overlayImage(*dst, DEC(-w), 0, to);
 
171
            break;
 
172
 
 
173
        case TRANSITION_TYPE_PUSH_R2L:
 
174
            m_api->overlayImage(*dst, INC(-w), 0, from);
 
175
            m_api->overlayImage(*dst, DEC(w),  0, to);
 
176
            break;
 
177
 
 
178
        case TRANSITION_TYPE_PUSH_T2B:
 
179
            m_api->overlayImage(*dst, 0, INC(h),  from);
 
180
            m_api->overlayImage(*dst, 0, DEC(-h), to);
 
181
            break;
 
182
 
 
183
        case TRANSITION_TYPE_PUSH_B2T:
 
184
            m_api->overlayImage(*dst, 0, INC(-h), from);
 
185
            m_api->overlayImage(*dst, 0, DEC(h),  to);
 
186
            break;
 
187
 
 
188
        // swapping
 
189
 
 
190
        case TRANSITION_TYPE_SWAP_L2R:
 
191
            if (step < steps / 2)
 
192
            {
 
193
                m_api->overlayImage(*dst, INC(w),  0, to);
 
194
                m_api->overlayImage(*dst, INC(-w), 0, from);
 
195
            }
 
196
            else
 
197
            {
 
198
                m_api->overlayImage(*dst, DEC(-w), 0, from);
 
199
                m_api->overlayImage(*dst, DEC(w),  0, to);
 
200
            }
 
201
            break;
 
202
 
 
203
        case TRANSITION_TYPE_SWAP_R2L:
 
204
            if (step < steps / 2)
 
205
            {
 
206
                m_api->overlayImage(*dst, INC(-w), 0, to);
 
207
                m_api->overlayImage(*dst, INC(w),  0, from);
 
208
            }
 
209
            else
 
210
            {
 
211
                m_api->overlayImage(*dst, DEC(w),  0, from);
 
212
                m_api->overlayImage(*dst, DEC(-w), 0, to);
 
213
            }
 
214
            break;
 
215
 
 
216
        case TRANSITION_TYPE_SWAP_T2B:
 
217
            if (step < steps / 2)
 
218
            {
 
219
                m_api->overlayImage(*dst, 0, INC(h),  to);
 
220
                m_api->overlayImage(*dst, 0, INC(-h), from);
 
221
            }
 
222
            else
 
223
            {
 
224
                m_api->overlayImage(*dst, 0, DEC(-h), from);
 
225
                m_api->overlayImage(*dst, 0, DEC(h),  to);
 
226
            }
 
227
            break;
 
228
 
 
229
        case TRANSITION_TYPE_SWAP_B2T:
 
230
            if (step < steps / 2)
 
231
            {
 
232
                m_api->overlayImage(*dst, 0, INC(-h), to);
 
233
                m_api->overlayImage(*dst, 0, INC(h),  from);
 
234
            }
 
235
            else
 
236
            {
 
237
                m_api->overlayImage(*dst, 0, DEC(h),  from);
 
238
                m_api->overlayImage(*dst, 0, DEC(-h), to);
 
239
            }
 
240
            break;
 
241
 
 
242
        // rolling
 
243
 
 
244
        case TRANSITION_TYPE_ROLL_L2R:
 
245
            if (INC(w))
 
246
                m_api->scaleblitImage(*dst, 0,      0, INC(w), h, to,   0, 0, w, h);
 
247
            if (DEC(w))
 
248
                m_api->scaleblitImage(*dst, INC(w), 0, DEC(w), h, from, 0, 0, w, h);
 
249
            break;
 
250
 
 
251
        case TRANSITION_TYPE_ROLL_R2L:
 
252
            if (DEC(w))
 
253
                m_api->scaleblitImage(*dst, 0,      0, DEC(w), h, from, 0, 0, w, h);
 
254
            if (INC(w))
 
255
                m_api->scaleblitImage(*dst, DEC(w), 0, INC(w), h, to,   0, 0, w, h);
 
256
            break;
 
257
 
 
258
        case TRANSITION_TYPE_ROLL_T2B:
 
259
            if (INC(h))
 
260
                m_api->scaleblitImage(*dst, 0, 0,      w, INC(h), to,   0, 0, w, h);
 
261
            if (DEC(h))
 
262
                m_api->scaleblitImage(*dst, 0, INC(h), w, DEC(h), from, 0, 0, w, h);
 
263
            break;
 
264
 
 
265
        case TRANSITION_TYPE_ROLL_B2T:
 
266
            if (DEC(h))
 
267
                m_api->scaleblitImage(*dst, 0, 0,      w, DEC(h), from, 0, 0, w, h);
 
268
            if (INC(h))
 
269
                m_api->scaleblitImage(*dst, 0, DEC(h), w, INC(h), to,   0, 0, w, h);
 
270
            break;
 
271
 
 
272
        // fade
 
273
 
 
274
        case TRANSITION_TYPE_FADE:
 
275
        default:
 
276
            m_api->blendImage(*dst, from, to, 1.0 / steps * step);
 
277
            break;
 
278
    }
 
279
 
 
280
    return dst;
 
281
}
 
282
 
 
283
GeoImage* ProcessImage::getGeometry(const GeoImage& from, const GeoImage& to, int image_width, int image_height, 
 
284
                                    int step, int steps) const
 
285
{
 
286
    GeoImage* const geometry = new GeoImage();
 
287
    // compute the dimesions in current step
 
288
    steps--;
 
289
 
 
290
    if (step <= 0)
 
291
    {
 
292
        geometry->x = lround(from.x);
 
293
        geometry->y = lround(from.y);
 
294
        geometry->w = lround(from.w);
 
295
        geometry->h = lround(from.h);
 
296
    }
 
297
    else if (step >= steps)
 
298
    {
 
299
        geometry->x = lround(to.x);
 
300
        geometry->y = lround(to.y);
 
301
        geometry->w = lround(to.w);
 
302
        geometry->h = lround(to.h);
 
303
    }
 
304
    else
 
305
    {
 
306
        geometry->x = lround(from.x + (to.x - from.x) * (double) step / (double) steps);
 
307
        geometry->y = lround(from.y + (to.y - from.y) * (double) step / (double) steps);
 
308
        geometry->w = lround(from.w + (to.w - from.w) * (double) step / (double) steps);
 
309
        geometry->h = lround(from.h + (to.h - from.h) * (double) step / (double) steps);
 
310
    }
 
311
 
 
312
    geometry->x = qMin(qMax(geometry->x, 0), image_width  - 1);
 
313
    geometry->y = qMin(qMax(geometry->y, 0), image_height - 1);
 
314
    geometry->w = qMin(qMax(geometry->w, 0), image_width  - 1 - geometry->x);
 
315
    geometry->h = qMin(qMax(geometry->h, 0), image_height - 1 - geometry->y);
 
316
 
 
317
    return geometry;
 
318
}
 
319
 
 
320
} // namespace KIPIPlugins