1
/** ===========================================================
4
* This file is a part of digiKam project
5
* <a href="http://www.digikam.org">http://www.digikam.org</a>
8
* @brief Transitions, AspectRatioCorrection and otherImageEffects
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>
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)
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.
24
* ============================================================ */
26
#include "processimage.moc"
34
#include "magickiface.h"
36
#define INC(v) incValue(v, step, steps)
37
#define DEC(v) decValue(v, step, steps)
42
ProcessImage::ProcessImage(MagickApi* const api)
47
MagickImage* ProcessImage::aspectRatioCorrection(MagickImage& img, double aspectratio, ASPECTCORRECTION_TYPE aspectcorrection)
49
MagickImage* newimg = 0;
50
double img_aspectratio = (double) img.getWidth() / (double) img.getHeight();
52
// tolerate some error in double value
53
if(abs(img_aspectratio - aspectratio) <= 0.001)
56
if (aspectcorrection == ASPECTCORRECTION_TYPE_AUTO)
58
// find out whether we should use fitin, fillin or none
59
if (img_aspectratio > 1.0)
60
aspectcorrection = ASPECTCORRECTION_TYPE_FILLIN;
62
aspectcorrection = ASPECTCORRECTION_TYPE_FITIN;
65
switch (aspectcorrection)
67
case ASPECTCORRECTION_TYPE_FITIN:
68
//fit in with black bars
69
if (img_aspectratio < aspectratio)
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");
75
m_api->overlayImage(*newimg, (newimg->getWidth() - img.getWidth()) / 2,0, img);
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");
83
m_api->overlayImage(*newimg, 0, (newimg->getHeight() - img.getHeight()) / 2, img);
87
case ASPECTCORRECTION_TYPE_FILLIN:
88
// part of image is cut off
89
if (img_aspectratio < aspectratio)
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");
95
m_api->bitblitImage(*newimg, 0, 0, img, 0, (img.getHeight() - newimg->getHeight()) / 2, newimg->getWidth(), newimg->getHeight());
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");
103
m_api->bitblitImage(*newimg, 0, 0, img,(img.getWidth() - newimg->getWidth()) / 2,0, newimg->getWidth(), newimg->getHeight());
107
case ASPECTCORRECTION_TYPE_NONE:
109
// no correction needed
115
// swap the images if we got a new one
116
m_api->freeImage(img);
122
int ProcessImage::incValue(int v, int step, int steps) const
124
return (v) * (step + 1) / steps;
127
int ProcessImage::decValue(int v, int step, int steps) const
129
return (v) * (steps - step - 1) / steps;
132
MagickImage* ProcessImage::transition(const MagickImage& from, const MagickImage& to, int type, int step, int steps)
136
if (step < 0 || step >= steps)
137
Q_EMIT signalProcessError(QString("step: %1 is out of range (%2)").arg(step).arg(steps));
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());
146
case TRANSITION_TYPE_SLIDE_L2R:
147
m_api->overlayImage(*dst, 0, 0, from);
148
m_api->overlayImage(*dst, DEC(-w), 0, to);
151
case TRANSITION_TYPE_SLIDE_R2L:
152
m_api->overlayImage(*dst, 0, 0, from);
153
m_api->overlayImage(*dst, DEC(w), 0, to);
156
case TRANSITION_TYPE_SLIDE_T2B:
157
m_api->overlayImage(*dst, 0, 0, from);
158
m_api->overlayImage(*dst, 0, DEC(-h), to);
161
case TRANSITION_TYPE_SLIDE_B2T:
162
m_api->overlayImage(*dst, 0, 0, from);
163
m_api->overlayImage(*dst, 0, DEC(h), to);
168
case TRANSITION_TYPE_PUSH_L2R:
169
m_api->overlayImage(*dst, INC(w), 0, from);
170
m_api->overlayImage(*dst, DEC(-w), 0, to);
173
case TRANSITION_TYPE_PUSH_R2L:
174
m_api->overlayImage(*dst, INC(-w), 0, from);
175
m_api->overlayImage(*dst, DEC(w), 0, to);
178
case TRANSITION_TYPE_PUSH_T2B:
179
m_api->overlayImage(*dst, 0, INC(h), from);
180
m_api->overlayImage(*dst, 0, DEC(-h), to);
183
case TRANSITION_TYPE_PUSH_B2T:
184
m_api->overlayImage(*dst, 0, INC(-h), from);
185
m_api->overlayImage(*dst, 0, DEC(h), to);
190
case TRANSITION_TYPE_SWAP_L2R:
191
if (step < steps / 2)
193
m_api->overlayImage(*dst, INC(w), 0, to);
194
m_api->overlayImage(*dst, INC(-w), 0, from);
198
m_api->overlayImage(*dst, DEC(-w), 0, from);
199
m_api->overlayImage(*dst, DEC(w), 0, to);
203
case TRANSITION_TYPE_SWAP_R2L:
204
if (step < steps / 2)
206
m_api->overlayImage(*dst, INC(-w), 0, to);
207
m_api->overlayImage(*dst, INC(w), 0, from);
211
m_api->overlayImage(*dst, DEC(w), 0, from);
212
m_api->overlayImage(*dst, DEC(-w), 0, to);
216
case TRANSITION_TYPE_SWAP_T2B:
217
if (step < steps / 2)
219
m_api->overlayImage(*dst, 0, INC(h), to);
220
m_api->overlayImage(*dst, 0, INC(-h), from);
224
m_api->overlayImage(*dst, 0, DEC(-h), from);
225
m_api->overlayImage(*dst, 0, DEC(h), to);
229
case TRANSITION_TYPE_SWAP_B2T:
230
if (step < steps / 2)
232
m_api->overlayImage(*dst, 0, INC(-h), to);
233
m_api->overlayImage(*dst, 0, INC(h), from);
237
m_api->overlayImage(*dst, 0, DEC(h), from);
238
m_api->overlayImage(*dst, 0, DEC(-h), to);
244
case TRANSITION_TYPE_ROLL_L2R:
246
m_api->scaleblitImage(*dst, 0, 0, INC(w), h, to, 0, 0, w, h);
248
m_api->scaleblitImage(*dst, INC(w), 0, DEC(w), h, from, 0, 0, w, h);
251
case TRANSITION_TYPE_ROLL_R2L:
253
m_api->scaleblitImage(*dst, 0, 0, DEC(w), h, from, 0, 0, w, h);
255
m_api->scaleblitImage(*dst, DEC(w), 0, INC(w), h, to, 0, 0, w, h);
258
case TRANSITION_TYPE_ROLL_T2B:
260
m_api->scaleblitImage(*dst, 0, 0, w, INC(h), to, 0, 0, w, h);
262
m_api->scaleblitImage(*dst, 0, INC(h), w, DEC(h), from, 0, 0, w, h);
265
case TRANSITION_TYPE_ROLL_B2T:
267
m_api->scaleblitImage(*dst, 0, 0, w, DEC(h), from, 0, 0, w, h);
269
m_api->scaleblitImage(*dst, 0, DEC(h), w, INC(h), to, 0, 0, w, h);
274
case TRANSITION_TYPE_FADE:
276
m_api->blendImage(*dst, from, to, 1.0 / steps * step);
283
GeoImage* ProcessImage::getGeometry(const GeoImage& from, const GeoImage& to, int image_width, int image_height,
284
int step, int steps) const
286
GeoImage* const geometry = new GeoImage();
287
// compute the dimesions in current step
292
geometry->x = lround(from.x);
293
geometry->y = lround(from.y);
294
geometry->w = lround(from.w);
295
geometry->h = lround(from.h);
297
else if (step >= steps)
299
geometry->x = lround(to.x);
300
geometry->y = lround(to.y);
301
geometry->w = lround(to.w);
302
geometry->h = lround(to.h);
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);
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);
320
} // namespace KIPIPlugins