Blame gegl/gegl-matrix.c

Packit Service 2781ba
/* This file is part of GEGL
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is free software; you can redistribute it and/or
Packit Service 2781ba
 * modify it under the terms of the GNU Lesser General Public
Packit Service 2781ba
 * License as published by the Free Software Foundation; either
Packit Service 2781ba
 * version 3 of the License, or (at your option) any later version.
Packit Service 2781ba
 *
Packit Service 2781ba
 * GEGL is distributed in the hope that it will be useful,
Packit Service 2781ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 2781ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 2781ba
 * Lesser General Public License for more details.
Packit Service 2781ba
 *
Packit Service 2781ba
 * You should have received a copy of the GNU Lesser General Public
Packit Service 2781ba
 * License along with GEGL; if not, see <http://www.gnu.org/licenses/>.
Packit Service 2781ba
 *
Packit Service 2781ba
 * Copyright 2006 Philip Lafleur
Packit Service 2781ba
 */
Packit Service 2781ba
Packit Service 2781ba
#include "config.h"
Packit Service 2781ba
#include <math.h>
Packit Service 2781ba
#include <string.h>
Packit Service 2781ba
#include <stdlib.h>
Packit Service 2781ba
Packit Service 2781ba
#include "gegl-matrix.h"
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
#if 0
Packit Service 2781ba
static void gegl_matrix3_debug (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  if (matrix)
Packit Service 2781ba
    {
Packit Service 2781ba
      gchar *str = gegl_matrix3_to_string (matrix);
Packit Service 2781ba
      g_print("%s\n", str);
Packit Service 2781ba
      g_free (str);
Packit Service 2781ba
    }
Packit Service 2781ba
  else
Packit Service 2781ba
    {
Packit Service 2781ba
      g_print("NULL matrix\n");
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
#endif
Packit Service 2781ba
Packit Service 2781ba
GeglMatrix3 *
Packit Service 2781ba
gegl_matrix3_new (void)
Packit Service 2781ba
{
Packit Service 2781ba
  return g_new0(GeglMatrix3, 1);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GType
Packit Service 2781ba
gegl_matrix3_get_type (void)
Packit Service 2781ba
{
Packit Service 2781ba
  static GType matrix_type = 0;
Packit Service 2781ba
Packit Service 2781ba
  if (!matrix_type) {
Packit Service 2781ba
    matrix_type = g_boxed_type_register_static ("GeglMatrix3",
Packit Service 2781ba
                                               (GBoxedCopyFunc) gegl_matrix3_copy,
Packit Service 2781ba
                                               (GBoxedFreeFunc) g_free);
Packit Service 2781ba
  }
Packit Service 2781ba
Packit Service 2781ba
  return matrix_type;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_matrix3_identity (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  matrix->coeff [0][0] = matrix->coeff [1][1] = matrix->coeff [2][2] = 1.;
Packit Service 2781ba
Packit Service 2781ba
  matrix->coeff [0][1] = matrix->coeff [0][2] = 0.;
Packit Service 2781ba
  matrix->coeff [1][0] = matrix->coeff [1][2] = 0.;
Packit Service 2781ba
  matrix->coeff [2][0] = matrix->coeff [2][1] = 0.;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gboolean
Packit Service 2781ba
gegl_matrix3_equal (GeglMatrix3 *matrix1,
Packit Service 2781ba
                    GeglMatrix3 *matrix2)
Packit Service 2781ba
{
Packit Service 2781ba
  gint x, y;
Packit Service 2781ba
Packit Service 2781ba
  for (y = 0; y < 3; y++)
Packit Service 2781ba
    for (x = 0; x < 3; x++)
Packit Service 2781ba
      if (matrix1->coeff [y][x] != matrix2->coeff [y][x])
Packit Service 2781ba
        return FALSE;
Packit Service 2781ba
  return TRUE;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gboolean
Packit Service 2781ba
gegl_matrix3_is_identity (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglMatrix3 identity;
Packit Service 2781ba
  gegl_matrix3_identity (&identity);
Packit Service 2781ba
  return gegl_matrix3_equal (&identity, matrix);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gboolean
Packit Service 2781ba
gegl_matrix3_is_scale (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglMatrix3 copy;
Packit Service 2781ba
  gegl_matrix3_copy_into (&copy, matrix);
Packit Service 2781ba
  copy.coeff [0][0] = copy.coeff [1][1] = 1.;
Packit Service 2781ba
  copy.coeff [0][2] = copy.coeff [1][2] = 0.;
Packit Service 2781ba
  return gegl_matrix3_is_identity (©);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gboolean
Packit Service 2781ba
gegl_matrix3_is_translate (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglMatrix3 copy;
Packit Service 2781ba
  gegl_matrix3_copy_into (&copy, matrix);
Packit Service 2781ba
  copy.coeff [0][2] = copy.coeff [1][2] = 0.;
Packit Service 2781ba
  return gegl_matrix3_is_identity (©);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_matrix3_copy_into (GeglMatrix3 *dst,
Packit Service 2781ba
                        GeglMatrix3 *src)
Packit Service 2781ba
{
Packit Service 2781ba
  memcpy (dst->coeff [0], src->coeff [0], 3 * sizeof (gdouble));
Packit Service 2781ba
  memcpy (dst->coeff [1], src->coeff [1], 3 * sizeof (gdouble));
Packit Service 2781ba
  memcpy (dst->coeff [2], src->coeff [2], 3 * sizeof (gdouble));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
GeglMatrix3 *
Packit Service 2781ba
gegl_matrix3_copy (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  return (GeglMatrix3 *) g_memdup (matrix, sizeof (GeglMatrix3));
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gdouble
Packit Service 2781ba
gegl_matrix3_determinant (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  gdouble determinant;
Packit Service 2781ba
Packit Service 2781ba
  determinant = matrix->coeff [0][0] * (matrix->coeff [1][1] * matrix->coeff [2][2] -
Packit Service 2781ba
                                 matrix->coeff [1][2] * matrix->coeff [2][1])
Packit Service 2781ba
              - matrix->coeff [0][1] * (matrix->coeff [1][0] * matrix->coeff [2][2] -
Packit Service 2781ba
                                 matrix->coeff [1][2] * matrix->coeff [2][0])
Packit Service 2781ba
              + matrix->coeff [0][2] * (matrix->coeff [1][0] * matrix->coeff [2][1] -
Packit Service 2781ba
                                 matrix->coeff [1][1] * matrix->coeff [2][0]);
Packit Service 2781ba
  return determinant;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_matrix3_invert (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglMatrix3 copy;
Packit Service 2781ba
  gdouble coeff;
Packit Service 2781ba
Packit Service 2781ba
  gegl_matrix3_copy_into (&copy, matrix);
Packit Service 2781ba
  coeff = 1 / gegl_matrix3_determinant (matrix);
Packit Service 2781ba
Packit Service 2781ba
  matrix->coeff [0][0] = (copy.coeff [1][1] * copy.coeff [2][2] -
Packit Service 2781ba
                   copy.coeff [1][2] * copy.coeff [2][1]) * coeff;
Packit Service 2781ba
  matrix->coeff [1][0] = (copy.coeff [1][2] * copy.coeff [2][0] -
Packit Service 2781ba
                   copy.coeff [1][0] * copy.coeff [2][2]) * coeff;
Packit Service 2781ba
  matrix->coeff [2][0] = (copy.coeff [1][0] * copy.coeff [2][1] -
Packit Service 2781ba
                   copy.coeff [1][1] * copy.coeff [2][0]) * coeff;
Packit Service 2781ba
Packit Service 2781ba
  matrix->coeff [0][1] = (copy.coeff [0][2] * copy.coeff [2][1] -
Packit Service 2781ba
                   copy.coeff [0][1] * copy.coeff [2][2]) * coeff;
Packit Service 2781ba
  matrix->coeff [1][1] = (copy.coeff [0][0] * copy.coeff [2][2] -
Packit Service 2781ba
                   copy.coeff [0][2] * copy.coeff [2][0]) * coeff;
Packit Service 2781ba
  matrix->coeff [2][1] = (copy.coeff [0][1] * copy.coeff [2][0] -
Packit Service 2781ba
                   copy.coeff [0][0] * copy.coeff [2][1]) * coeff;
Packit Service 2781ba
Packit Service 2781ba
  matrix->coeff [0][2] = (copy.coeff [0][1] * copy.coeff [1][2] -
Packit Service 2781ba
                   copy.coeff [0][2] * copy.coeff [1][1]) * coeff;
Packit Service 2781ba
  matrix->coeff [1][2] = (copy.coeff [0][2] * copy.coeff [1][0] -
Packit Service 2781ba
                   copy.coeff [0][0] * copy.coeff [1][2]) * coeff;
Packit Service 2781ba
  matrix->coeff [2][2] = (copy.coeff [0][0] * copy.coeff [1][1] -
Packit Service 2781ba
                   copy.coeff [0][1] * copy.coeff [1][0]) * coeff;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_matrix3_multiply (GeglMatrix3 *left,
Packit Service 2781ba
                       GeglMatrix3 *right,
Packit Service 2781ba
                       GeglMatrix3 *product)
Packit Service 2781ba
{
Packit Service 2781ba
  GeglMatrix3 temp;
Packit Service 2781ba
  gint    i;
Packit Service 2781ba
Packit Service 2781ba
  for (i = 0; i < 3; i++)
Packit Service 2781ba
    {
Packit Service 2781ba
      temp.coeff [i][0] = left->coeff [i][0] * right->coeff [0][0]
Packit Service 2781ba
                    + left->coeff [i][1] * right->coeff [1][0]
Packit Service 2781ba
                    + left->coeff [i][2] * right->coeff [2][0];
Packit Service 2781ba
      temp.coeff [i][1] = left->coeff [i][0] * right->coeff [0][1]
Packit Service 2781ba
                    + left->coeff [i][1] * right->coeff [1][1]
Packit Service 2781ba
                    + left->coeff [i][2] * right->coeff [2][1];
Packit Service 2781ba
      temp.coeff [i][2] = left->coeff [i][0] * right->coeff [0][2]
Packit Service 2781ba
                    + left->coeff [i][1] * right->coeff [1][2]
Packit Service 2781ba
                    + left->coeff [i][2] * right->coeff [2][2];
Packit Service 2781ba
    }
Packit Service 2781ba
Packit Service 2781ba
  gegl_matrix3_copy_into (product, &temp);
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_matrix3_originate (GeglMatrix3 *matrix,
Packit Service 2781ba
                   gdouble x,
Packit Service 2781ba
                   gdouble y)
Packit Service 2781ba
{
Packit Service 2781ba
Packit Service 2781ba
  /* assumes last row is [0 0 1] (true for affine transforms) */
Packit Service 2781ba
  matrix->coeff [0][2] = matrix->coeff [0][0] * (-x) +
Packit Service 2781ba
                  matrix->coeff [0][1] * (-y) +
Packit Service 2781ba
                  matrix->coeff [0][2] + x;
Packit Service 2781ba
  matrix->coeff [1][2] = matrix->coeff [1][0] * (-x) +
Packit Service 2781ba
                  matrix->coeff [1][1] * (-y) +
Packit Service 2781ba
                  matrix->coeff [1][2] + y;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_matrix3_transform_point (GeglMatrix3  *matrix,
Packit Service 2781ba
                              gdouble     *x,
Packit Service 2781ba
                              gdouble     *y)
Packit Service 2781ba
{
Packit Service 2781ba
  gdouble xp, yp, w;
Packit Service 2781ba
  
Packit Service 2781ba
  w = (*x * matrix->coeff [2][0] + *y * matrix->coeff [2][1] + matrix->coeff [2][2]);
Packit Service 2781ba
Packit Service 2781ba
  xp = (*x * matrix->coeff [0][0] + *y * matrix->coeff [0][1] + matrix->coeff [0][2]) /w;
Packit Service 2781ba
  yp = (*x * matrix->coeff [1][0] + *y * matrix->coeff [1][1] + matrix->coeff [1][2]) /w;
Packit Service 2781ba
Packit Service 2781ba
  *x = xp;
Packit Service 2781ba
  *y = yp;
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
void
Packit Service 2781ba
gegl_matrix3_parse_string (GeglMatrix3  *matrix,
Packit Service 2781ba
                           const gchar *string)
Packit Service 2781ba
{
Packit Service 2781ba
  gegl_matrix3_identity (matrix);
Packit Service 2781ba
  if (strstr (string, "translate"))
Packit Service 2781ba
    {
Packit Service 2781ba
      gchar *p = strchr (string, '(');
Packit Service 2781ba
      gfloat a;
Packit Service 2781ba
      gfloat b;
Packit Service 2781ba
      if (!p) return;
Packit Service 2781ba
      p++;
Packit Service 2781ba
      a = strtod(p, &p);
Packit Service 2781ba
      if (!p) return;
Packit Service 2781ba
      p = strchr (string, ',');
Packit Service 2781ba
      if (!p) return;
Packit Service 2781ba
      p++;
Packit Service 2781ba
      b = strtod (p, &p);
Packit Service 2781ba
      if (!p) return;
Packit Service 2781ba
Packit Service 2781ba
      matrix->coeff [0][2] = a;
Packit Service 2781ba
      matrix->coeff [1][2] = b;
Packit Service 2781ba
    }
Packit Service 2781ba
  else if (strstr (string, "matrix"))
Packit Service 2781ba
    {
Packit Service 2781ba
      gchar *p = strchr (string, '(');
Packit Service 2781ba
      gfloat a;
Packit Service 2781ba
      gint i,j;
Packit Service 2781ba
      if (!p) return;
Packit Service 2781ba
      p++;
Packit Service 2781ba
Packit Service 2781ba
Packit Service 2781ba
      for (i=0;i<3;i++)
Packit Service 2781ba
        for (j=0;j<3;j++)
Packit Service 2781ba
          {
Packit Service 2781ba
            a = strtod(p, &p);
Packit Service 2781ba
            matrix->coeff [j][i] = a;
Packit Service 2781ba
            if (!p) return;
Packit Service 2781ba
            p = strchr (p, ',');
Packit Service 2781ba
            if (!p) return;
Packit Service 2781ba
            p++;
Packit Service 2781ba
          }
Packit Service 2781ba
    }
Packit Service 2781ba
}
Packit Service 2781ba
Packit Service 2781ba
gchar *gegl_matrix3_to_string (GeglMatrix3 *matrix)
Packit Service 2781ba
{
Packit Service 2781ba
  gchar *res;
Packit Service 2781ba
  GString *str = g_string_new ("matrix(");
Packit Service 2781ba
  gint i, j;
Packit Service 2781ba
  gint a=0;
Packit Service 2781ba
Packit Service 2781ba
  for (i=0;i<3;i++)
Packit Service 2781ba
    for (j=0;j<3;j++)
Packit Service 2781ba
      {
Packit Service 2781ba
        if (a!=0)
Packit Service 2781ba
          g_string_append (str, ",");
Packit Service 2781ba
        a=1;
Packit Service 2781ba
        g_string_append_printf (str, "%f", matrix->coeff[j][i]);
Packit Service 2781ba
      }
Packit Service 2781ba
  g_string_append (str, ")");
Packit Service 2781ba
  res = str->str;
Packit Service 2781ba
  g_string_free (str, FALSE);
Packit Service 2781ba
Packit Service 2781ba
  return res;
Packit Service 2781ba
}