/* This file is part of GEGL * * GEGL 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 3 of the License, or (at your option) any later version. * * GEGL 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with GEGL; if not, see . * * Copyright 2006 Philip Lafleur */ #include "config.h" #include #include #include #include "gegl-matrix.h" #if 0 static void gegl_matrix3_debug (GeglMatrix3 *matrix) { if (matrix) { gchar *str = gegl_matrix3_to_string (matrix); g_print("%s\n", str); g_free (str); } else { g_print("NULL matrix\n"); } } #endif GeglMatrix3 * gegl_matrix3_new (void) { return g_new0(GeglMatrix3, 1); } GType gegl_matrix3_get_type (void) { static GType matrix_type = 0; if (!matrix_type) { matrix_type = g_boxed_type_register_static ("GeglMatrix3", (GBoxedCopyFunc) gegl_matrix3_copy, (GBoxedFreeFunc) g_free); } return matrix_type; } void gegl_matrix3_identity (GeglMatrix3 *matrix) { matrix->coeff [0][0] = matrix->coeff [1][1] = matrix->coeff [2][2] = 1.; matrix->coeff [0][1] = matrix->coeff [0][2] = 0.; matrix->coeff [1][0] = matrix->coeff [1][2] = 0.; matrix->coeff [2][0] = matrix->coeff [2][1] = 0.; } gboolean gegl_matrix3_equal (GeglMatrix3 *matrix1, GeglMatrix3 *matrix2) { gint x, y; for (y = 0; y < 3; y++) for (x = 0; x < 3; x++) if (matrix1->coeff [y][x] != matrix2->coeff [y][x]) return FALSE; return TRUE; } gboolean gegl_matrix3_is_identity (GeglMatrix3 *matrix) { GeglMatrix3 identity; gegl_matrix3_identity (&identity); return gegl_matrix3_equal (&identity, matrix); } gboolean gegl_matrix3_is_scale (GeglMatrix3 *matrix) { GeglMatrix3 copy; gegl_matrix3_copy_into (©, matrix); copy.coeff [0][0] = copy.coeff [1][1] = 1.; copy.coeff [0][2] = copy.coeff [1][2] = 0.; return gegl_matrix3_is_identity (©); } gboolean gegl_matrix3_is_translate (GeglMatrix3 *matrix) { GeglMatrix3 copy; gegl_matrix3_copy_into (©, matrix); copy.coeff [0][2] = copy.coeff [1][2] = 0.; return gegl_matrix3_is_identity (©); } void gegl_matrix3_copy_into (GeglMatrix3 *dst, GeglMatrix3 *src) { memcpy (dst->coeff [0], src->coeff [0], 3 * sizeof (gdouble)); memcpy (dst->coeff [1], src->coeff [1], 3 * sizeof (gdouble)); memcpy (dst->coeff [2], src->coeff [2], 3 * sizeof (gdouble)); } GeglMatrix3 * gegl_matrix3_copy (GeglMatrix3 *matrix) { return (GeglMatrix3 *) g_memdup (matrix, sizeof (GeglMatrix3)); } gdouble gegl_matrix3_determinant (GeglMatrix3 *matrix) { gdouble determinant; determinant = matrix->coeff [0][0] * (matrix->coeff [1][1] * matrix->coeff [2][2] - matrix->coeff [1][2] * matrix->coeff [2][1]) - matrix->coeff [0][1] * (matrix->coeff [1][0] * matrix->coeff [2][2] - matrix->coeff [1][2] * matrix->coeff [2][0]) + matrix->coeff [0][2] * (matrix->coeff [1][0] * matrix->coeff [2][1] - matrix->coeff [1][1] * matrix->coeff [2][0]); return determinant; } void gegl_matrix3_invert (GeglMatrix3 *matrix) { GeglMatrix3 copy; gdouble coeff; gegl_matrix3_copy_into (©, matrix); coeff = 1 / gegl_matrix3_determinant (matrix); matrix->coeff [0][0] = (copy.coeff [1][1] * copy.coeff [2][2] - copy.coeff [1][2] * copy.coeff [2][1]) * coeff; matrix->coeff [1][0] = (copy.coeff [1][2] * copy.coeff [2][0] - copy.coeff [1][0] * copy.coeff [2][2]) * coeff; matrix->coeff [2][0] = (copy.coeff [1][0] * copy.coeff [2][1] - copy.coeff [1][1] * copy.coeff [2][0]) * coeff; matrix->coeff [0][1] = (copy.coeff [0][2] * copy.coeff [2][1] - copy.coeff [0][1] * copy.coeff [2][2]) * coeff; matrix->coeff [1][1] = (copy.coeff [0][0] * copy.coeff [2][2] - copy.coeff [0][2] * copy.coeff [2][0]) * coeff; matrix->coeff [2][1] = (copy.coeff [0][1] * copy.coeff [2][0] - copy.coeff [0][0] * copy.coeff [2][1]) * coeff; matrix->coeff [0][2] = (copy.coeff [0][1] * copy.coeff [1][2] - copy.coeff [0][2] * copy.coeff [1][1]) * coeff; matrix->coeff [1][2] = (copy.coeff [0][2] * copy.coeff [1][0] - copy.coeff [0][0] * copy.coeff [1][2]) * coeff; matrix->coeff [2][2] = (copy.coeff [0][0] * copy.coeff [1][1] - copy.coeff [0][1] * copy.coeff [1][0]) * coeff; } void gegl_matrix3_multiply (GeglMatrix3 *left, GeglMatrix3 *right, GeglMatrix3 *product) { GeglMatrix3 temp; gint i; for (i = 0; i < 3; i++) { temp.coeff [i][0] = left->coeff [i][0] * right->coeff [0][0] + left->coeff [i][1] * right->coeff [1][0] + left->coeff [i][2] * right->coeff [2][0]; temp.coeff [i][1] = left->coeff [i][0] * right->coeff [0][1] + left->coeff [i][1] * right->coeff [1][1] + left->coeff [i][2] * right->coeff [2][1]; temp.coeff [i][2] = left->coeff [i][0] * right->coeff [0][2] + left->coeff [i][1] * right->coeff [1][2] + left->coeff [i][2] * right->coeff [2][2]; } gegl_matrix3_copy_into (product, &temp); } void gegl_matrix3_originate (GeglMatrix3 *matrix, gdouble x, gdouble y) { /* assumes last row is [0 0 1] (true for affine transforms) */ matrix->coeff [0][2] = matrix->coeff [0][0] * (-x) + matrix->coeff [0][1] * (-y) + matrix->coeff [0][2] + x; matrix->coeff [1][2] = matrix->coeff [1][0] * (-x) + matrix->coeff [1][1] * (-y) + matrix->coeff [1][2] + y; } void gegl_matrix3_transform_point (GeglMatrix3 *matrix, gdouble *x, gdouble *y) { gdouble xp, yp, w; w = (*x * matrix->coeff [2][0] + *y * matrix->coeff [2][1] + matrix->coeff [2][2]); xp = (*x * matrix->coeff [0][0] + *y * matrix->coeff [0][1] + matrix->coeff [0][2]) /w; yp = (*x * matrix->coeff [1][0] + *y * matrix->coeff [1][1] + matrix->coeff [1][2]) /w; *x = xp; *y = yp; } void gegl_matrix3_parse_string (GeglMatrix3 *matrix, const gchar *string) { gegl_matrix3_identity (matrix); if (strstr (string, "translate")) { gchar *p = strchr (string, '('); gfloat a; gfloat b; if (!p) return; p++; a = strtod(p, &p); if (!p) return; p = strchr (string, ','); if (!p) return; p++; b = strtod (p, &p); if (!p) return; matrix->coeff [0][2] = a; matrix->coeff [1][2] = b; } else if (strstr (string, "matrix")) { gchar *p = strchr (string, '('); gfloat a; gint i,j; if (!p) return; p++; for (i=0;i<3;i++) for (j=0;j<3;j++) { a = strtod(p, &p); matrix->coeff [j][i] = a; if (!p) return; p = strchr (p, ','); if (!p) return; p++; } } } gchar *gegl_matrix3_to_string (GeglMatrix3 *matrix) { gchar *res; GString *str = g_string_new ("matrix("); gint i, j; gint a=0; for (i=0;i<3;i++) for (j=0;j<3;j++) { if (a!=0) g_string_append (str, ","); a=1; g_string_append_printf (str, "%f", matrix->coeff[j][i]); } g_string_append (str, ")"); res = str->str; g_string_free (str, FALSE); return res; }