mirror of https://github.com/GNOME/gimp.git
252 lines
5.1 KiB
C
252 lines
5.1 KiB
C
/* gimpmatrix.c
|
|
* Copyright (C) 1998 Jay Cox <jaycox@earthlink.net>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2 of the License, or (at your option) any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Library General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with this library; if not, write to the
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*/
|
|
|
|
#include <glib.h>
|
|
#include <math.h>
|
|
#include <string.h>
|
|
#include "gimpmatrix.h"
|
|
|
|
#define EPSILON 1e-6
|
|
|
|
void
|
|
gimp_matrix_transform_point (GimpMatrix m, double x, double y,
|
|
double *newx, double *newy)
|
|
{
|
|
double w;
|
|
w = m[2][0]*x + m[2][1]*y + m[2][2];
|
|
|
|
if (w == 0.0)
|
|
w = 1.0;
|
|
else
|
|
w = 1.0/w;
|
|
|
|
*newx = (m[0][0]*x + m[0][1]*y + m[0][2])*w;
|
|
*newy = (m[1][0]*x + m[1][1]*y + m[1][2])*w;
|
|
}
|
|
|
|
void
|
|
gimp_matrix_mult (GimpMatrix m1, GimpMatrix m2)
|
|
{
|
|
int i, j;
|
|
GimpMatrix tmp;
|
|
double t1, t2, t3;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
t1 = m1[i][0];
|
|
t2 = m1[i][1];
|
|
t3 = m1[i][2];
|
|
for (j = 0; j < 3; j++)
|
|
{
|
|
tmp[i][j] = t1 * m2[0][j];
|
|
tmp[i][j] += t2 * m2[1][j];
|
|
tmp[i][j] += t3 * m2[2][j];
|
|
}
|
|
}
|
|
/* put the results in m2 */
|
|
memcpy(&m2[0][0], &tmp[0][0], sizeof(GimpMatrix));
|
|
}
|
|
|
|
void
|
|
gimp_matrix_identity (GimpMatrix m)
|
|
{
|
|
static GimpMatrix identity = { {1.0, 0.0, 0.0},
|
|
{0.0, 1.0, 0.0},
|
|
{0.0, 0.0, 1.0} };
|
|
|
|
memcpy(&m[0][0], &identity[0][0], sizeof(GimpMatrix));
|
|
}
|
|
|
|
void
|
|
gimp_matrix_translate (GimpMatrix m, double x, double y)
|
|
{
|
|
double g, h, i;
|
|
g = m[2][0];
|
|
h = m[2][1];
|
|
i = m[2][2];
|
|
m[0][0] += x*g;
|
|
m[0][1] += x*h;
|
|
m[0][2] += x*i;
|
|
m[1][0] += y*g;
|
|
m[1][1] += y*h;
|
|
m[1][2] += y*i;
|
|
}
|
|
|
|
void
|
|
gimp_matrix_scale (GimpMatrix m, double x, double y)
|
|
{
|
|
m[0][0] *= x;
|
|
m[0][1] *= x;
|
|
m[0][2] *= x;
|
|
|
|
m[1][0] *= y;
|
|
m[1][1] *= y;
|
|
m[1][2] *= y;
|
|
}
|
|
|
|
void
|
|
gimp_matrix_rotate (GimpMatrix m, double theta)
|
|
{
|
|
double t1, t2;
|
|
double cost, sint;
|
|
|
|
cost = cos(theta);
|
|
sint = sin(theta);
|
|
|
|
t1 = m[0][0];
|
|
t2 = m[1][0];
|
|
m[0][0] = cost*t1 - sint*t2;
|
|
m[1][0] = sint*t1 + cost*t2;
|
|
|
|
t1 = m[0][1];
|
|
t2 = m[1][1];
|
|
m[0][1] = cost*t1 - sint*t2;
|
|
m[1][1] = sint*t1 + cost*t2;
|
|
|
|
t1 = m[0][2];
|
|
t2 = m[1][2];
|
|
m[0][2] = cost*t1 - sint*t2;
|
|
m[1][2] = sint*t1 + cost*t2;
|
|
}
|
|
|
|
void
|
|
gimp_matrix_xshear (GimpMatrix m, double amnt)
|
|
{
|
|
m[0][0] += amnt * m[1][0];
|
|
m[0][1] += amnt * m[1][1];
|
|
m[0][2] += amnt * m[1][2];
|
|
}
|
|
|
|
void
|
|
gimp_matrix_yshear (GimpMatrix m, double amnt)
|
|
{
|
|
m[1][0] += amnt * m[0][0];
|
|
m[1][1] += amnt * m[0][1];
|
|
m[1][2] += amnt * m[0][2];
|
|
}
|
|
|
|
|
|
double
|
|
gimp_matrix_determinant (GimpMatrix m)
|
|
{
|
|
double determinant;
|
|
|
|
determinant = m[0][0] * (m[1][1]*m[2][2] - m[1][2]*m[2][1]);
|
|
determinant -= m[1][0] * (m[0][1]*m[2][2] - m[0][2]*m[2][1]);
|
|
determinant += m[2][0] * (m[0][1]*m[1][2] - m[0][2]*m[1][1]);
|
|
|
|
return determinant;
|
|
}
|
|
|
|
void
|
|
gimp_matrix_invert (GimpMatrix m, GimpMatrix m_inv)
|
|
{
|
|
double det_1;
|
|
|
|
det_1 = gimp_matrix_determinant (m);
|
|
if (det_1 == 0.0)
|
|
return;
|
|
det_1 = 1.0 / det_1;
|
|
|
|
m_inv[0][0] = ( m[1][1] * m[2][2] - m[1][2] * m[2][1] ) * det_1;
|
|
m_inv[1][0] = - ( m[1][0] * m[2][2] - m[1][2] * m[2][0] ) * det_1;
|
|
m_inv[2][0] = ( m[1][0] * m[2][1] - m[1][1] * m[2][0] ) * det_1;
|
|
m_inv[0][1] = - ( m[0][1] * m[2][2] - m[0][2] * m[2][1] ) * det_1;
|
|
m_inv[1][1] = ( m[0][0] * m[2][2] - m[0][2] * m[2][0] ) * det_1;
|
|
m_inv[2][1] = - ( m[0][0] * m[2][1] - m[0][1] * m[2][0] ) * det_1;
|
|
m_inv[0][2] = ( m[0][1] * m[1][2] - m[0][2] * m[1][1] ) * det_1;
|
|
m_inv[1][2] = - ( m[0][0] * m[1][2] - m[0][2] * m[1][0] ) * det_1;
|
|
m_inv[2][2] = ( m[0][0] * m[1][1] - m[0][1] * m[1][0] ) * det_1;
|
|
}
|
|
|
|
void
|
|
gimp_matrix_duplicate (GimpMatrix src, GimpMatrix target)
|
|
{
|
|
memcpy (&target[0][0], &src[0][0], sizeof(GimpMatrix));
|
|
}
|
|
|
|
|
|
/* functions to test for matrix properties */
|
|
|
|
int
|
|
gimp_matrix_is_diagonal (GimpMatrix m)
|
|
{
|
|
int i,j;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
for (j = 0; j < 3; j++)
|
|
{
|
|
if (i != j && fabs (m[i][j]) > EPSILON)
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
int
|
|
gimp_matrix_is_identity (GimpMatrix m)
|
|
{
|
|
int i,j;
|
|
|
|
for (i = 0; i < 3; i++)
|
|
{
|
|
for (j = 0; j < 3; j++)
|
|
{
|
|
if (i == j)
|
|
{
|
|
if (fabs (m[i][j] - 1.0) > EPSILON)
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
if (fabs (m[i][j]) > EPSILON)
|
|
return FALSE;
|
|
}
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/* Check if we'll need to interpolate when applying this matrix.
|
|
This function returns TRUE if all entries of the upper left
|
|
2x2 matrix are either 0 or 1
|
|
*/
|
|
int
|
|
gimp_matrix_is_simple (GimpMatrix m)
|
|
{
|
|
double absm;
|
|
int i,j;
|
|
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
for (j = 0; j < 2; j++)
|
|
{
|
|
absm = fabs (m[i][j]);
|
|
if (absm > EPSILON && fabs (absm - 1.0) > EPSILON)
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
|