File indexing completed on 2025-01-19 03:51:13

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2005-02-17
0007  * Description : a matrix implementation for image
0008  *               perspective adjustment.
0009  *
0010  * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2006-2012 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0012  *
0013  * Based on PerspectiveMatrix3 implementation inspired from gimp 2.0
0014  * from Spencer Kimball and Peter Mattis.
0015  *
0016  * SPDX-License-Identifier: GPL-2.0-or-later
0017  *
0018  * ============================================================ */
0019 
0020 #include "perspectivematrix.h"
0021 
0022 // C++ includes
0023 
0024 #include <cstring>
0025 
0026 namespace DigikamEditorPerspectiveToolPlugin
0027 {
0028 
0029 static double identityPerspectiveMatrix[3][3] =
0030                                      {
0031                                        { 1.0, 0.0, 0.0 },
0032                                        { 0.0, 1.0, 0.0 },
0033                                        { 0.0, 0.0, 1.0 }
0034                                      };
0035 
0036 PerspectiveMatrix::PerspectiveMatrix()
0037 {
0038     memcpy(coeff, identityPerspectiveMatrix, sizeof(coeff));
0039 }
0040 
0041 void PerspectiveMatrix::translate (double x, double y)
0042 {
0043     double g, h, i;
0044 
0045     g = coeff[2][0];
0046     h = coeff[2][1];
0047     i = coeff[2][2];
0048 
0049     coeff[0][0] += x * g;
0050     coeff[0][1] += x * h;
0051     coeff[0][2] += x * i;
0052     coeff[1][0] += y * g;
0053     coeff[1][1] += y * h;
0054     coeff[1][2] += y * i;
0055 }
0056 
0057 void PerspectiveMatrix::scale(double x, double y)
0058 {
0059     coeff[0][0] *= x;
0060     coeff[0][1] *= x;
0061     coeff[0][2] *= x;
0062 
0063     coeff[1][0] *= y;
0064     coeff[1][1] *= y;
0065     coeff[1][2] *= y;
0066 }
0067 
0068 void PerspectiveMatrix::multiply(const PerspectiveMatrix& matrix)
0069 {
0070     PerspectiveMatrix tmp;
0071     double t1, t2, t3;
0072 
0073     for (int i = 0; i < 3; ++i)
0074     {
0075         t1 = matrix.coeff[i][0];
0076         t2 = matrix.coeff[i][1];
0077         t3 = matrix.coeff[i][2];
0078 
0079         for (int j = 0; j < 3; ++j)
0080         {
0081             tmp.coeff[i][j]  = t1 * coeff[0][j];
0082             tmp.coeff[i][j] += t2 * coeff[1][j];
0083             tmp.coeff[i][j] += t3 * coeff[2][j];
0084         }
0085     }
0086 
0087     *this = tmp;
0088 }
0089 
0090 void PerspectiveMatrix::transformPoint(double x, double y, double* newx, double* newy) const
0091 {
0092     double  w = coeff[2][0] * x + coeff[2][1] * y + coeff[2][2];
0093 
0094     if (w == 0.0)
0095     {
0096         w = 1.0;
0097     }
0098     else
0099     {
0100         w = 1.0/w;
0101     }
0102 
0103     *newx = (coeff[0][0]  * x +
0104              coeff[0][1]  * y +
0105              coeff[0][2]) * w;
0106     *newy = (coeff[1][0]  * x +
0107              coeff[1][1]  * y +
0108              coeff[1][2]) * w;
0109 }
0110 
0111 void PerspectiveMatrix::invert()
0112 {
0113     PerspectiveMatrix  inv;
0114     double  det = determinant();
0115 
0116     if (det == 0.0)
0117     {
0118         return;
0119     }
0120 
0121     det = 1.0 / det;
0122 
0123     inv.coeff[0][0] =   (coeff[1][1] * coeff[2][2] -
0124                          coeff[1][2] * coeff[2][1]) * det;
0125 
0126     inv.coeff[1][0] = - (coeff[1][0] * coeff[2][2] -
0127                          coeff[1][2] * coeff[2][0]) * det;
0128 
0129     inv.coeff[2][0] =   (coeff[1][0] * coeff[2][1] -
0130                          coeff[1][1] * coeff[2][0]) * det;
0131 
0132     inv.coeff[0][1] = - (coeff[0][1] * coeff[2][2] -
0133                          coeff[0][2] * coeff[2][1]) * det;
0134 
0135     inv.coeff[1][1] =   (coeff[0][0] * coeff[2][2] -
0136                          coeff[0][2] * coeff[2][0]) * det;
0137 
0138     inv.coeff[2][1] = - (coeff[0][0] * coeff[2][1] -
0139                          coeff[0][1] * coeff[2][0]) * det;
0140 
0141     inv.coeff[0][2] =   (coeff[0][1] * coeff[1][2] -
0142                          coeff[0][2] * coeff[1][1]) * det;
0143 
0144     inv.coeff[1][2] = - (coeff[0][0] * coeff[1][2] -
0145                          coeff[0][2] * coeff[1][0]) * det;
0146 
0147     inv.coeff[2][2] =   (coeff[0][0] * coeff[1][1] -
0148                          coeff[0][1] * coeff[1][0]) * det;
0149 
0150     *this = inv;
0151 }
0152 
0153 double PerspectiveMatrix::determinant() const
0154 {
0155     double determinant;
0156 
0157     determinant  = (coeff[0][0]  *
0158                     (coeff[1][1] * coeff[2][2] -
0159                      coeff[1][2] * coeff[2][1]));
0160     determinant -= (coeff[1][0]  *
0161                     (coeff[0][1] * coeff[2][2] -
0162                      coeff[0][2] * coeff[2][1]));
0163     determinant += (coeff[2][0]  *
0164                     (coeff[0][1] * coeff[1][2] -
0165                      coeff[0][2] * coeff[1][1]));
0166 
0167     return determinant;
0168 }
0169 
0170 } // namespace DigikamEditorPerspectiveToolPlugin