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

« back to all changes in this revision

Viewing changes to extra/libkexiv2/libkexiv2/rotationmatrix.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
 * @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   2009-08-03
 
8
 * @brief  Tools for combining rotation operations
 
9
 *
 
10
 * @author Copyright (C) 2006-2011 by Gilles Caulier
 
11
 *         <a href="mailto:caulier dot gilles at gmail dot com">caulier dot gilles at gmail dot com</a>
 
12
 * @author Copyright (C) 2004-2011 by Marcel Wiesweg
 
13
 *         <a href="mailto:marcel dot wiesweg at gmx dot de">marcel dot wiesweg at gmx dot de</a>
 
14
 *
 
15
 * This program is free software; you can redistribute it
 
16
 * and/or modify it under the terms of the GNU General
 
17
 * Public License as published by the Free Software Foundation;
 
18
 * either version 2, or (at your option)
 
19
 * any later version.
 
20
 *
 
21
 * This program is distributed in the hope that it will be useful,
 
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 
24
 * GNU General Public License for more details.
 
25
 *
 
26
 * ============================================================ */
 
27
 
 
28
#include "rotationmatrix.h"
 
29
 
 
30
// KDE includes
 
31
 
 
32
#include <kdebug.h>
 
33
 
 
34
// local includes
 
35
 
 
36
#include "version.h"
 
37
 
 
38
namespace KExiv2Iface
 
39
{
 
40
 
 
41
/**
 
42
   If the picture is displayed according to the exif orientation tag,
 
43
   the user will request rotating operations relative to what he sees,
 
44
   and that is the picture rotated according to the EXIF tag.
 
45
   So the operation requested and the given EXIF angle must be combined.
 
46
   E.g. if orientation is "6" (rotate 90 clockwiseto show correctly)
 
47
   and the user selects 180 clockwise, the operation is 270.
 
48
   If the user selected 270, the operation would be None (and clearing the exif tag).
 
49
 
 
50
   This requires to describe the transformations in a model which
 
51
   cares for both composing (180+90=270) and eliminating (180+180=no action),
 
52
   as well as the non-commutative nature of the operations (vflip+90 is not 90+vflip)
 
53
 
 
54
   All 2D transformations can be described by a 2x3 matrix, see QWRotationMatrix.
 
55
   All transformations needed here - rotate 90, 180, 270, flipV, flipH -
 
56
   can be described in a 2x2 matrix with the values 0,1,-1
 
57
   (because flipping is expressed by changing the sign only,
 
58
    and sine and cosine of 90, 180 and 270 are either 0,1 or -1).
 
59
 
 
60
    x' = m11 x + m12 y
 
61
    y' = m21 x + m22 y
 
62
 
 
63
   Moreover, all combinations of these rotate/flip operations result in one of the eight
 
64
   matrices defined below.
 
65
   (I did not proof that mathematically, but empirically)
 
66
 
 
67
   static const RotationMatrix identity;               //( 1,  0,  0,  1)
 
68
   static const RotationMatrix rotate90;               //( 0, -1,  1,  0)
 
69
   static const RotationMatrix rotate180;              //(-1,  0,  0, -1)
 
70
   static const RotationMatrix rotate270;              //( 0,  1, -1,  0)
 
71
   static const RotationMatrix flipHorizontal;         //(-1,  0,  0,  1)
 
72
   static const RotationMatrix flipVertical;           //( 1,  0,  0, -1)
 
73
   static const RotationMatrix rotate90flipHorizontal; //( 0,  1,  1,  0), first rotate, then flip
 
74
   static const RotationMatrix rotate90flipVertical;   //( 0, -1, -1,  0), first rotate, then flip
 
75
 
 
76
*/
 
77
 
 
78
namespace Matrix
 
79
{
 
80
 
 
81
static const RotationMatrix identity               ( 1,  0,  0,  1);
 
82
static const RotationMatrix rotate90               ( 0, -1,  1,  0);
 
83
static const RotationMatrix rotate180              (-1,  0,  0, -1);
 
84
static const RotationMatrix rotate270              ( 0,  1, -1,  0);
 
85
static const RotationMatrix flipHorizontal         (-1,  0,  0,  1);
 
86
static const RotationMatrix flipVertical           ( 1,  0,  0, -1);
 
87
static const RotationMatrix rotate90flipHorizontal ( 0,  1,  1,  0);
 
88
static const RotationMatrix rotate90flipVertical   ( 0, -1, -1,  0);
 
89
 
 
90
RotationMatrix matrix(RotationMatrix::TransformationAction action)
 
91
{
 
92
    switch (action)
 
93
    {
 
94
        case RotationMatrix::NoTransformation:
 
95
            return identity;
 
96
        case RotationMatrix::FlipHorizontal:
 
97
            return flipHorizontal;
 
98
        case RotationMatrix::FlipVertical:
 
99
            return flipVertical;
 
100
        case RotationMatrix::Rotate90:
 
101
            return rotate90;
 
102
        case RotationMatrix::Rotate180:
 
103
            return rotate180;
 
104
        case RotationMatrix::Rotate270:
 
105
            return rotate270;
 
106
    }
 
107
    return identity;
 
108
}
 
109
 
 
110
RotationMatrix matrix(KExiv2::ImageOrientation exifOrientation)
 
111
{
 
112
    switch (exifOrientation)
 
113
    {
 
114
        case KExiv2::ORIENTATION_NORMAL:
 
115
            return identity;
 
116
        case KExiv2::ORIENTATION_HFLIP:
 
117
            return flipHorizontal;
 
118
        case KExiv2::ORIENTATION_ROT_180:
 
119
            return rotate180;
 
120
        case KExiv2::ORIENTATION_VFLIP:
 
121
            return flipVertical;
 
122
        case KExiv2::ORIENTATION_ROT_90_HFLIP:
 
123
            return rotate90flipHorizontal;
 
124
        case KExiv2::ORIENTATION_ROT_90:
 
125
            return rotate90;
 
126
        case KExiv2::ORIENTATION_ROT_90_VFLIP:
 
127
            return rotate90flipVertical;
 
128
        case KExiv2::ORIENTATION_ROT_270:
 
129
            return rotate270;
 
130
        case KExiv2::ORIENTATION_UNSPECIFIED:
 
131
            return identity;
 
132
    }
 
133
    return identity;
 
134
}
 
135
 
 
136
 
 
137
} // namespace Matrix
 
138
 
 
139
RotationMatrix::RotationMatrix()
 
140
{
 
141
    set( 1, 0, 0, 1 );
 
142
}
 
143
 
 
144
RotationMatrix::RotationMatrix(TransformationAction action)
 
145
{
 
146
    *this = Matrix::matrix(action);
 
147
}
 
148
 
 
149
RotationMatrix::RotationMatrix(KExiv2::ImageOrientation exifOrientation)
 
150
{
 
151
    *this = Matrix::matrix(exifOrientation);
 
152
}
 
153
 
 
154
RotationMatrix::RotationMatrix(int m11, int m12, int m21, int m22)
 
155
{
 
156
    set(m11, m12, m21, m22);
 
157
}
 
158
 
 
159
void RotationMatrix::set(int m11, int m12, int m21, int m22)
 
160
{
 
161
    m[0][0]=m11;
 
162
    m[0][1]=m12;
 
163
    m[1][0]=m21;
 
164
    m[1][1]=m22;
 
165
}
 
166
 
 
167
bool RotationMatrix::isNoTransform() const
 
168
{
 
169
    return *this == Matrix::identity;
 
170
}
 
171
 
 
172
RotationMatrix& RotationMatrix::operator*=(const RotationMatrix& ma)
 
173
{
 
174
    set( ma.m[0][0]*m[0][0] + ma.m[0][1]*m[1][0],  ma.m[0][0]*m[0][1] + ma.m[0][1]*m[1][1],
 
175
         ma.m[1][0]*m[0][0] + ma.m[1][1]*m[1][0],  ma.m[1][0]*m[0][1] + ma.m[1][1]*m[1][1] );
 
176
         return *this;
 
177
}
 
178
 
 
179
bool RotationMatrix::operator==(const RotationMatrix& ma) const
 
180
{
 
181
    return m[0][0]==ma.m[0][0] &&
 
182
    m[0][1]==ma.m[0][1] &&
 
183
    m[1][0]==ma.m[1][0] &&
 
184
    m[1][1]==ma.m[1][1];
 
185
}
 
186
 
 
187
bool RotationMatrix::operator!=(const RotationMatrix& ma) const
 
188
{
 
189
    return !(*this==ma);
 
190
}
 
191
 
 
192
RotationMatrix& RotationMatrix::operator*=(TransformationAction action)
 
193
{
 
194
    return (*this *= Matrix::matrix(action));
 
195
}
 
196
 
 
197
RotationMatrix& RotationMatrix::operator*=(QList<TransformationAction> actions)
 
198
{
 
199
    foreach (const TransformationAction& action, actions)
 
200
    {
 
201
        *this *= Matrix::matrix(action);
 
202
    }
 
203
 
 
204
    return *this;
 
205
}
 
206
 
 
207
RotationMatrix& RotationMatrix::operator*=(KExiv2::ImageOrientation exifOrientation)
 
208
{
 
209
    return (*this *= Matrix::matrix(exifOrientation));
 
210
}
 
211
 
 
212
/** Converts the mathematically correct description
 
213
    into the primitive operations that can be carried out losslessly.
 
214
*/
 
215
QList<RotationMatrix::TransformationAction> RotationMatrix::transformations() const
 
216
{
 
217
    QList<TransformationAction> transforms;
 
218
 
 
219
    if (*this == Matrix::rotate90)
 
220
    {
 
221
        transforms << Rotate90;
 
222
    }
 
223
    else if (*this == Matrix::rotate180)
 
224
    {
 
225
        transforms << Rotate180;
 
226
    }
 
227
    else if (*this == Matrix::rotate270)
 
228
    {
 
229
        transforms << Rotate270;
 
230
    }
 
231
    else if (*this == Matrix::flipHorizontal)
 
232
    {
 
233
        transforms << FlipHorizontal;
 
234
    }
 
235
    else if (*this == Matrix::flipVertical)
 
236
    {
 
237
        transforms << FlipVertical;
 
238
    }
 
239
    else if (*this == Matrix::rotate90flipHorizontal)
 
240
    {
 
241
        //first rotate, then flip!
 
242
        transforms << Rotate90;
 
243
        transforms << FlipHorizontal;
 
244
    }
 
245
    else if (*this == Matrix::rotate90flipVertical)
 
246
    {
 
247
        //first rotate, then flip!
 
248
        transforms << Rotate90;
 
249
        transforms << FlipVertical;
 
250
    }
 
251
    return transforms;
 
252
}
 
253
 
 
254
KExiv2::ImageOrientation RotationMatrix::exifOrientation() const
 
255
{
 
256
    if (*this == Matrix::identity)
 
257
    {
 
258
        return KExiv2::ORIENTATION_NORMAL;
 
259
    }
 
260
    if (*this == Matrix::rotate90)
 
261
    {
 
262
        return KExiv2::ORIENTATION_ROT_90;
 
263
    }
 
264
    else if (*this == Matrix::rotate180)
 
265
    {
 
266
        return KExiv2::ORIENTATION_ROT_180;
 
267
    }
 
268
    else if (*this == Matrix::rotate270)
 
269
    {
 
270
        return KExiv2::ORIENTATION_ROT_270;
 
271
    }
 
272
    else if (*this == Matrix::flipHorizontal)
 
273
    {
 
274
        return KExiv2::ORIENTATION_HFLIP;
 
275
    }
 
276
    else if (*this == Matrix::flipVertical)
 
277
    {
 
278
        return KExiv2::ORIENTATION_VFLIP;
 
279
    }
 
280
    else if (*this == Matrix::rotate90flipHorizontal)
 
281
    {
 
282
        return KExiv2::ORIENTATION_ROT_90_HFLIP;
 
283
    }
 
284
    else if (*this == Matrix::rotate90flipVertical)
 
285
    {
 
286
        return KExiv2::ORIENTATION_ROT_90_VFLIP;
 
287
    }
 
288
    return KExiv2::ORIENTATION_UNSPECIFIED;
 
289
}
 
290
 
 
291
QMatrix RotationMatrix::toMatrix() const
 
292
{
 
293
    return toMatrix(exifOrientation());
 
294
}
 
295
 
 
296
QMatrix RotationMatrix::toMatrix(KExiv2::ImageOrientation orientation)
 
297
{
 
298
    QMatrix matrix;
 
299
 
 
300
    switch (orientation)
 
301
    {
 
302
        case KExiv2::ORIENTATION_NORMAL:
 
303
        case KExiv2::ORIENTATION_UNSPECIFIED:
 
304
            break;
 
305
 
 
306
        case KExiv2::ORIENTATION_HFLIP:
 
307
            matrix.scale(-1, 1);
 
308
            break;
 
309
 
 
310
        case KExiv2::ORIENTATION_ROT_180:
 
311
            matrix.rotate(180);
 
312
            break;
 
313
 
 
314
        case KExiv2::ORIENTATION_VFLIP:
 
315
            matrix.scale(1, -1);
 
316
            break;
 
317
 
 
318
        case KExiv2::ORIENTATION_ROT_90_HFLIP:
 
319
            matrix.scale(-1, 1);
 
320
            matrix.rotate(90);
 
321
            break;
 
322
 
 
323
        case KExiv2::ORIENTATION_ROT_90:
 
324
            matrix.rotate(90);
 
325
            break;
 
326
 
 
327
        case KExiv2::ORIENTATION_ROT_90_VFLIP:
 
328
            matrix.scale(1, -1);
 
329
            matrix.rotate(90);
 
330
            break;
 
331
 
 
332
        case KExiv2::ORIENTATION_ROT_270:
 
333
            matrix.rotate(270);
 
334
            break;
 
335
    }
 
336
 
 
337
    return matrix;
 
338
}
 
339
 
 
340
}  // namespace KExiv2Iface