1 /* LIBGIMP - The GIMP Library
2 * Copyright (C) 1995-1997 Peter Mattis and Spencer Kimball
3 *
4 * gimpmatrix.c
5 * Copyright (C) 1998 Jay Cox <jaycox@gimp.org>
6 *
7 * This library is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library. If not, see
19 * <https://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <glib-object.h>
25
26 #include "gimpmath.h"
27
28
29 /**
30 * SECTION: gimpmatrix
31 * @title: GimpMatrix
32 * @short_description: Utilities to set up and manipulate 3x3
33 * transformation matrices.
34 * @see_also: #GimpVector2, #GimpVector3, #GimpVector4
35 *
36 * When doing image manipulation you will often need 3x3
37 * transformation matrices that define translation, rotation, scaling,
38 * shearing and arbitrary perspective transformations using a 3x3
39 * matrix. Here you'll find a set of utility functions to set up those
40 * matrices and to perform basic matrix manipulations and tests.
41 *
42 * Each matrix class has a 2 dimensional gdouble coeff member. The
43 * element for row r and column c of the matrix is coeff[r][c].
44 **/
45
46
47 #define EPSILON 1e-6
48
49
50 static GimpMatrix2 * matrix2_copy (const GimpMatrix2 *matrix);
51
52 /**
53 * gimp_matrix2_get_type:
54 *
55 * Reveals the object type
56 *
57 * Returns: the #GType for Matrix2 objects
58 *
59 * Since: 2.4
60 **/
61 GType
gimp_matrix2_get_type(void)62 gimp_matrix2_get_type (void)
63 {
64 static GType matrix_type = 0;
65
66 if (!matrix_type)
67 matrix_type = g_boxed_type_register_static ("GimpMatrix2",
68 (GBoxedCopyFunc) matrix2_copy,
69 (GBoxedFreeFunc) g_free);
70
71 return matrix_type;
72 }
73
74
75 /*
76 * GIMP_TYPE_PARAM_MATRIX2
77 */
78
79 #define GIMP_PARAM_SPEC_MATRIX2(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_MATRIX2, GimpParamSpecMatrix2))
80
81 static void gimp_param_matrix2_class_init (GParamSpecClass *class);
82 static void gimp_param_matrix2_init (GParamSpec *pspec);
83 static void gimp_param_matrix2_set_default (GParamSpec *pspec,
84 GValue *value);
85 static gint gimp_param_matrix2_values_cmp (GParamSpec *pspec,
86 const GValue *value1,
87 const GValue *value2);
88
89 typedef struct _GimpParamSpecMatrix2 GimpParamSpecMatrix2;
90
91 struct _GimpParamSpecMatrix2
92 {
93 GParamSpecBoxed parent_instance;
94
95 GimpMatrix2 default_value;
96 };
97
98 /**
99 * gimp_param_matrix2_get_type:
100 *
101 * Reveals the object type
102 *
103 * Returns: the #GType for a GimpMatrix2 object
104 *
105 * Since: 2.4
106 **/
107 GType
gimp_param_matrix2_get_type(void)108 gimp_param_matrix2_get_type (void)
109 {
110 static GType spec_type = 0;
111
112 if (!spec_type)
113 {
114 static const GTypeInfo type_info =
115 {
116 sizeof (GParamSpecClass),
117 NULL, NULL,
118 (GClassInitFunc) gimp_param_matrix2_class_init,
119 NULL, NULL,
120 sizeof (GimpParamSpecMatrix2),
121 0,
122 (GInstanceInitFunc) gimp_param_matrix2_init
123 };
124
125 spec_type = g_type_register_static (G_TYPE_PARAM_BOXED,
126 "GimpParamMatrix2",
127 &type_info, 0);
128 }
129
130 return spec_type;
131 }
132
133 static void
gimp_param_matrix2_class_init(GParamSpecClass * class)134 gimp_param_matrix2_class_init (GParamSpecClass *class)
135 {
136 class->value_type = GIMP_TYPE_MATRIX2;
137 class->value_set_default = gimp_param_matrix2_set_default;
138 class->values_cmp = gimp_param_matrix2_values_cmp;
139 }
140
141 static void
gimp_param_matrix2_init(GParamSpec * pspec)142 gimp_param_matrix2_init (GParamSpec *pspec)
143 {
144 GimpParamSpecMatrix2 *cspec = GIMP_PARAM_SPEC_MATRIX2 (pspec);
145
146 gimp_matrix2_identity (&cspec->default_value);
147 }
148
149 static void
gimp_param_matrix2_set_default(GParamSpec * pspec,GValue * value)150 gimp_param_matrix2_set_default (GParamSpec *pspec,
151 GValue *value)
152 {
153 GimpParamSpecMatrix2 *cspec = GIMP_PARAM_SPEC_MATRIX2 (pspec);
154
155 g_value_set_static_boxed (value, &cspec->default_value);
156 }
157
158 static gint
gimp_param_matrix2_values_cmp(GParamSpec * pspec,const GValue * value1,const GValue * value2)159 gimp_param_matrix2_values_cmp (GParamSpec *pspec,
160 const GValue *value1,
161 const GValue *value2)
162 {
163 GimpMatrix2 *matrix1;
164 GimpMatrix2 *matrix2;
165 gint i, j;
166
167 matrix1 = value1->data[0].v_pointer;
168 matrix2 = value2->data[0].v_pointer;
169
170 /* try to return at least *something*, it's useless anyway... */
171
172 if (! matrix1)
173 return matrix2 != NULL ? -1 : 0;
174 else if (! matrix2)
175 return matrix1 != NULL;
176
177 for (i = 0; i < 2; i++)
178 for (j = 0; j < 2; j++)
179 if (matrix1->coeff[i][j] != matrix2->coeff[i][j])
180 return 1;
181
182 return 0;
183 }
184
185 /**
186 * gimp_param_spec_matrix2:
187 * @name: Canonical name of the param
188 * @nick: Nickname of the param
189 * @blurb: Brief description of param.
190 * @default_value: Value to use if none is assigned.
191 * @flags: a combination of #GParamFlags
192 *
193 * Creates a param spec to hold a #GimpMatrix2 value.
194 * See g_param_spec_internal() for more information.
195 *
196 * Returns: a newly allocated #GParamSpec instance
197 *
198 * Since: 2.4
199 **/
200 GParamSpec *
gimp_param_spec_matrix2(const gchar * name,const gchar * nick,const gchar * blurb,const GimpMatrix2 * default_value,GParamFlags flags)201 gimp_param_spec_matrix2 (const gchar *name,
202 const gchar *nick,
203 const gchar *blurb,
204 const GimpMatrix2 *default_value,
205 GParamFlags flags)
206 {
207 GimpParamSpecMatrix2 *cspec;
208
209 g_return_val_if_fail (default_value != NULL, NULL);
210
211 cspec = g_param_spec_internal (GIMP_TYPE_PARAM_MATRIX2,
212 name, nick, blurb, flags);
213
214 cspec->default_value = *default_value;
215
216 return G_PARAM_SPEC (cspec);
217 }
218
219
220 static GimpMatrix2 *
matrix2_copy(const GimpMatrix2 * matrix)221 matrix2_copy (const GimpMatrix2 *matrix)
222 {
223 return (GimpMatrix2 *) g_memdup (matrix, sizeof (GimpMatrix2));
224 }
225
226
227 /**
228 * gimp_matrix2_identity:
229 * @matrix: A matrix.
230 *
231 * Sets the matrix to the identity matrix.
232 */
233 void
gimp_matrix2_identity(GimpMatrix2 * matrix)234 gimp_matrix2_identity (GimpMatrix2 *matrix)
235 {
236 static const GimpMatrix2 identity = { { { 1.0, 0.0 },
237 { 0.0, 1.0 } } };
238
239 *matrix = identity;
240 }
241
242 /**
243 * gimp_matrix2_mult:
244 * @matrix1: The first input matrix.
245 * @matrix2: The second input matrix which will be overwritten by the result.
246 *
247 * Multiplies two matrices and puts the result into the second one.
248 */
249 void
gimp_matrix2_mult(const GimpMatrix2 * matrix1,GimpMatrix2 * matrix2)250 gimp_matrix2_mult (const GimpMatrix2 *matrix1,
251 GimpMatrix2 *matrix2)
252 {
253 GimpMatrix2 tmp;
254
255 tmp.coeff[0][0] = (matrix1->coeff[0][0] * matrix2->coeff[0][0] +
256 matrix1->coeff[0][1] * matrix2->coeff[1][0]);
257 tmp.coeff[0][1] = (matrix1->coeff[0][0] * matrix2->coeff[0][1] +
258 matrix1->coeff[0][1] * matrix2->coeff[1][1]);
259 tmp.coeff[1][0] = (matrix1->coeff[1][0] * matrix2->coeff[0][0] +
260 matrix1->coeff[1][1] * matrix2->coeff[1][0]);
261 tmp.coeff[1][1] = (matrix1->coeff[1][0] * matrix2->coeff[0][1] +
262 matrix1->coeff[1][1] * matrix2->coeff[1][1]);
263
264 *matrix2 = tmp;
265 }
266
267 /**
268 * gimp_matrix2_determinant:
269 * @matrix: The input matrix.
270 *
271 * Calculates the determinant of the given matrix.
272 *
273 * Returns: The determinant.
274 *
275 * Since: 2.10.16
276 */
277
278 gdouble
gimp_matrix2_determinant(const GimpMatrix2 * matrix)279 gimp_matrix2_determinant (const GimpMatrix2 *matrix)
280 {
281 return matrix->coeff[0][0] * matrix->coeff[1][1] -
282 matrix->coeff[0][1] * matrix->coeff[1][0];
283 }
284
285 /**
286 * gimp_matrix2_invert:
287 * @matrix: The matrix that is to be inverted.
288 *
289 * Inverts the given matrix.
290 *
291 * Since: 2.10.16
292 */
293 void
gimp_matrix2_invert(GimpMatrix2 * matrix)294 gimp_matrix2_invert (GimpMatrix2 *matrix)
295 {
296 gdouble det = gimp_matrix2_determinant (matrix);
297 gdouble temp;
298
299 if (fabs (det) <= EPSILON)
300 return;
301
302 temp = matrix->coeff[0][0];
303
304 matrix->coeff[0][0] = matrix->coeff[1][1] / det;
305 matrix->coeff[0][1] /= -det;
306 matrix->coeff[1][0] /= -det;
307 matrix->coeff[1][1] = temp / det;
308 }
309
310 /**
311 * gimp_matrix2_transform_point:
312 * @matrix: The transformation matrix.
313 * @x: The source X coordinate.
314 * @y: The source Y coordinate.
315 * @newx: The transformed X coordinate.
316 * @newy: The transformed Y coordinate.
317 *
318 * Transforms a point in 2D as specified by the transformation matrix.
319 *
320 * Since: 2.10.16
321 */
322 void
gimp_matrix2_transform_point(const GimpMatrix2 * matrix,gdouble x,gdouble y,gdouble * newx,gdouble * newy)323 gimp_matrix2_transform_point (const GimpMatrix2 *matrix,
324 gdouble x,
325 gdouble y,
326 gdouble *newx,
327 gdouble *newy)
328 {
329 *newx = matrix->coeff[0][0] * x + matrix->coeff[0][1] * y;
330 *newy = matrix->coeff[1][0] * x + matrix->coeff[1][1] * y;
331 }
332
333
334 static GimpMatrix3 * matrix3_copy (const GimpMatrix3 *matrix);
335
336 /**
337 * gimp_matrix3_get_type:
338 *
339 * Reveals the object type
340 *
341 * Returns: the #GType for Matrix3 objects
342 *
343 * Since: 2.8
344 **/
345 GType
gimp_matrix3_get_type(void)346 gimp_matrix3_get_type (void)
347 {
348 static GType matrix_type = 0;
349
350 if (!matrix_type)
351 matrix_type = g_boxed_type_register_static ("GimpMatrix3",
352 (GBoxedCopyFunc) matrix3_copy,
353 (GBoxedFreeFunc) g_free);
354
355 return matrix_type;
356 }
357
358
359 /*
360 * GIMP_TYPE_PARAM_MATRIX3
361 */
362
363 #define GIMP_PARAM_SPEC_MATRIX3(pspec) (G_TYPE_CHECK_INSTANCE_CAST ((pspec), GIMP_TYPE_PARAM_MATRIX3, GimpParamSpecMatrix3))
364
365 static void gimp_param_matrix3_class_init (GParamSpecClass *class);
366 static void gimp_param_matrix3_init (GParamSpec *pspec);
367 static void gimp_param_matrix3_set_default (GParamSpec *pspec,
368 GValue *value);
369 static gint gimp_param_matrix3_values_cmp (GParamSpec *pspec,
370 const GValue *value1,
371 const GValue *value2);
372
373 typedef struct _GimpParamSpecMatrix3 GimpParamSpecMatrix3;
374
375 struct _GimpParamSpecMatrix3
376 {
377 GParamSpecBoxed parent_instance;
378
379 GimpMatrix3 default_value;
380 };
381
382 /**
383 * gimp_param_matrix3_get_type:
384 *
385 * Reveals the object type
386 *
387 * Returns: the #GType for a GimpMatrix3 object
388 *
389 * Since: 2.8
390 **/
391 GType
gimp_param_matrix3_get_type(void)392 gimp_param_matrix3_get_type (void)
393 {
394 static GType spec_type = 0;
395
396 if (!spec_type)
397 {
398 static const GTypeInfo type_info =
399 {
400 sizeof (GParamSpecClass),
401 NULL, NULL,
402 (GClassInitFunc) gimp_param_matrix3_class_init,
403 NULL, NULL,
404 sizeof (GimpParamSpecMatrix3),
405 0,
406 (GInstanceInitFunc) gimp_param_matrix3_init
407 };
408
409 spec_type = g_type_register_static (G_TYPE_PARAM_BOXED,
410 "GimpParamMatrix3",
411 &type_info, 0);
412 }
413
414 return spec_type;
415 }
416
417 static void
gimp_param_matrix3_class_init(GParamSpecClass * class)418 gimp_param_matrix3_class_init (GParamSpecClass *class)
419 {
420 class->value_type = GIMP_TYPE_MATRIX3;
421 class->value_set_default = gimp_param_matrix3_set_default;
422 class->values_cmp = gimp_param_matrix3_values_cmp;
423 }
424
425 static void
gimp_param_matrix3_init(GParamSpec * pspec)426 gimp_param_matrix3_init (GParamSpec *pspec)
427 {
428 GimpParamSpecMatrix3 *cspec = GIMP_PARAM_SPEC_MATRIX3 (pspec);
429
430 gimp_matrix3_identity (&cspec->default_value);
431 }
432
433 static void
gimp_param_matrix3_set_default(GParamSpec * pspec,GValue * value)434 gimp_param_matrix3_set_default (GParamSpec *pspec,
435 GValue *value)
436 {
437 GimpParamSpecMatrix3 *cspec = GIMP_PARAM_SPEC_MATRIX3 (pspec);
438
439 g_value_set_static_boxed (value, &cspec->default_value);
440 }
441
442 static gint
gimp_param_matrix3_values_cmp(GParamSpec * pspec,const GValue * value1,const GValue * value2)443 gimp_param_matrix3_values_cmp (GParamSpec *pspec,
444 const GValue *value1,
445 const GValue *value2)
446 {
447 GimpMatrix3 *matrix1;
448 GimpMatrix3 *matrix2;
449 gint i, j;
450
451 matrix1 = value1->data[0].v_pointer;
452 matrix2 = value2->data[0].v_pointer;
453
454 /* try to return at least *something*, it's useless anyway... */
455
456 if (! matrix1)
457 return matrix2 != NULL ? -1 : 0;
458 else if (! matrix2)
459 return matrix1 != NULL;
460
461 for (i = 0; i < 3; i++)
462 for (j = 0; j < 3; j++)
463 if (matrix1->coeff[i][j] != matrix2->coeff[i][j])
464 return 1;
465
466 return 0;
467 }
468
469 /**
470 * gimp_param_spec_matrix3:
471 * @name: Canonical name of the param
472 * @nick: Nickname of the param
473 * @blurb: Brief description of param.
474 * @default_value: Value to use if none is assigned.
475 * @flags: a combination of #GParamFlags
476 *
477 * Creates a param spec to hold a #GimpMatrix3 value.
478 * See g_param_spec_internal() for more information.
479 *
480 * Returns: a newly allocated #GParamSpec instance
481 *
482 * Since: 2.8
483 **/
484 GParamSpec *
gimp_param_spec_matrix3(const gchar * name,const gchar * nick,const gchar * blurb,const GimpMatrix3 * default_value,GParamFlags flags)485 gimp_param_spec_matrix3 (const gchar *name,
486 const gchar *nick,
487 const gchar *blurb,
488 const GimpMatrix3 *default_value,
489 GParamFlags flags)
490 {
491 GimpParamSpecMatrix3 *cspec;
492
493 cspec = g_param_spec_internal (GIMP_TYPE_PARAM_MATRIX3,
494 name, nick, blurb, flags);
495
496 if (default_value)
497 cspec->default_value = *default_value;
498
499 return G_PARAM_SPEC (cspec);
500 }
501
502
503 static GimpMatrix3 *
matrix3_copy(const GimpMatrix3 * matrix)504 matrix3_copy (const GimpMatrix3 *matrix)
505 {
506 return (GimpMatrix3 *) g_memdup (matrix, sizeof (GimpMatrix3));
507 }
508
509
510 /**
511 * gimp_matrix3_identity:
512 * @matrix: A matrix.
513 *
514 * Sets the matrix to the identity matrix.
515 */
516 void
gimp_matrix3_identity(GimpMatrix3 * matrix)517 gimp_matrix3_identity (GimpMatrix3 *matrix)
518 {
519 static const GimpMatrix3 identity = { { { 1.0, 0.0, 0.0 },
520 { 0.0, 1.0, 0.0 },
521 { 0.0, 0.0, 1.0 } } };
522
523 *matrix = identity;
524 }
525
526 /**
527 * gimp_matrix3_transform_point:
528 * @matrix: The transformation matrix.
529 * @x: The source X coordinate.
530 * @y: The source Y coordinate.
531 * @newx: The transformed X coordinate.
532 * @newy: The transformed Y coordinate.
533 *
534 * Transforms a point in 2D as specified by the transformation matrix.
535 */
536 void
gimp_matrix3_transform_point(const GimpMatrix3 * matrix,gdouble x,gdouble y,gdouble * newx,gdouble * newy)537 gimp_matrix3_transform_point (const GimpMatrix3 *matrix,
538 gdouble x,
539 gdouble y,
540 gdouble *newx,
541 gdouble *newy)
542 {
543 gdouble w;
544
545 w = matrix->coeff[2][0] * x + matrix->coeff[2][1] * y + matrix->coeff[2][2];
546
547 if (w == 0.0)
548 w = 1.0;
549 else
550 w = 1.0/w;
551
552 *newx = (matrix->coeff[0][0] * x +
553 matrix->coeff[0][1] * y +
554 matrix->coeff[0][2]) * w;
555 *newy = (matrix->coeff[1][0] * x +
556 matrix->coeff[1][1] * y +
557 matrix->coeff[1][2]) * w;
558 }
559
560 /**
561 * gimp_matrix3_mult:
562 * @matrix1: The first input matrix.
563 * @matrix2: The second input matrix which will be overwritten by the result.
564 *
565 * Multiplies two matrices and puts the result into the second one.
566 */
567 void
gimp_matrix3_mult(const GimpMatrix3 * matrix1,GimpMatrix3 * matrix2)568 gimp_matrix3_mult (const GimpMatrix3 *matrix1,
569 GimpMatrix3 *matrix2)
570 {
571 gint i, j;
572 GimpMatrix3 tmp;
573 gdouble t1, t2, t3;
574
575 for (i = 0; i < 3; i++)
576 {
577 t1 = matrix1->coeff[i][0];
578 t2 = matrix1->coeff[i][1];
579 t3 = matrix1->coeff[i][2];
580
581 for (j = 0; j < 3; j++)
582 {
583 tmp.coeff[i][j] = t1 * matrix2->coeff[0][j];
584 tmp.coeff[i][j] += t2 * matrix2->coeff[1][j];
585 tmp.coeff[i][j] += t3 * matrix2->coeff[2][j];
586 }
587 }
588
589 *matrix2 = tmp;
590 }
591
592 /**
593 * gimp_matrix3_translate:
594 * @matrix: The matrix that is to be translated.
595 * @x: Translation in X direction.
596 * @y: Translation in Y direction.
597 *
598 * Translates the matrix by x and y.
599 */
600 void
gimp_matrix3_translate(GimpMatrix3 * matrix,gdouble x,gdouble y)601 gimp_matrix3_translate (GimpMatrix3 *matrix,
602 gdouble x,
603 gdouble y)
604 {
605 gdouble g, h, i;
606
607 g = matrix->coeff[2][0];
608 h = matrix->coeff[2][1];
609 i = matrix->coeff[2][2];
610
611 matrix->coeff[0][0] += x * g;
612 matrix->coeff[0][1] += x * h;
613 matrix->coeff[0][2] += x * i;
614 matrix->coeff[1][0] += y * g;
615 matrix->coeff[1][1] += y * h;
616 matrix->coeff[1][2] += y * i;
617 }
618
619 /**
620 * gimp_matrix3_scale:
621 * @matrix: The matrix that is to be scaled.
622 * @x: X scale factor.
623 * @y: Y scale factor.
624 *
625 * Scales the matrix by x and y
626 */
627 void
gimp_matrix3_scale(GimpMatrix3 * matrix,gdouble x,gdouble y)628 gimp_matrix3_scale (GimpMatrix3 *matrix,
629 gdouble x,
630 gdouble y)
631 {
632 matrix->coeff[0][0] *= x;
633 matrix->coeff[0][1] *= x;
634 matrix->coeff[0][2] *= x;
635
636 matrix->coeff[1][0] *= y;
637 matrix->coeff[1][1] *= y;
638 matrix->coeff[1][2] *= y;
639 }
640
641 /**
642 * gimp_matrix3_rotate:
643 * @matrix: The matrix that is to be rotated.
644 * @theta: The angle of rotation (in radians).
645 *
646 * Rotates the matrix by theta degrees.
647 */
648 void
gimp_matrix3_rotate(GimpMatrix3 * matrix,gdouble theta)649 gimp_matrix3_rotate (GimpMatrix3 *matrix,
650 gdouble theta)
651 {
652 gdouble t1, t2;
653 gdouble cost, sint;
654
655 cost = cos (theta);
656 sint = sin (theta);
657
658 t1 = matrix->coeff[0][0];
659 t2 = matrix->coeff[1][0];
660 matrix->coeff[0][0] = cost * t1 - sint * t2;
661 matrix->coeff[1][0] = sint * t1 + cost * t2;
662
663 t1 = matrix->coeff[0][1];
664 t2 = matrix->coeff[1][1];
665 matrix->coeff[0][1] = cost * t1 - sint * t2;
666 matrix->coeff[1][1] = sint * t1 + cost * t2;
667
668 t1 = matrix->coeff[0][2];
669 t2 = matrix->coeff[1][2];
670 matrix->coeff[0][2] = cost * t1 - sint * t2;
671 matrix->coeff[1][2] = sint * t1 + cost * t2;
672 }
673
674 /**
675 * gimp_matrix3_xshear:
676 * @matrix: The matrix that is to be sheared.
677 * @amount: X shear amount.
678 *
679 * Shears the matrix in the X direction.
680 */
681 void
gimp_matrix3_xshear(GimpMatrix3 * matrix,gdouble amount)682 gimp_matrix3_xshear (GimpMatrix3 *matrix,
683 gdouble amount)
684 {
685 matrix->coeff[0][0] += amount * matrix->coeff[1][0];
686 matrix->coeff[0][1] += amount * matrix->coeff[1][1];
687 matrix->coeff[0][2] += amount * matrix->coeff[1][2];
688 }
689
690 /**
691 * gimp_matrix3_yshear:
692 * @matrix: The matrix that is to be sheared.
693 * @amount: Y shear amount.
694 *
695 * Shears the matrix in the Y direction.
696 */
697 void
gimp_matrix3_yshear(GimpMatrix3 * matrix,gdouble amount)698 gimp_matrix3_yshear (GimpMatrix3 *matrix,
699 gdouble amount)
700 {
701 matrix->coeff[1][0] += amount * matrix->coeff[0][0];
702 matrix->coeff[1][1] += amount * matrix->coeff[0][1];
703 matrix->coeff[1][2] += amount * matrix->coeff[0][2];
704 }
705
706 /**
707 * gimp_matrix3_affine:
708 * @matrix: The input matrix.
709 * @a: the 'a' coefficient
710 * @b: the 'b' coefficient
711 * @c: the 'c' coefficient
712 * @d: the 'd' coefficient
713 * @e: the 'e' coefficient
714 * @f: the 'f' coefficient
715 *
716 * Applies the affine transformation given by six values to @matrix.
717 * The six values form define an affine transformation matrix as
718 * illustrated below:
719 *
720 * ( a c e )
721 * ( b d f )
722 * ( 0 0 1 )
723 **/
724 void
gimp_matrix3_affine(GimpMatrix3 * matrix,gdouble a,gdouble b,gdouble c,gdouble d,gdouble e,gdouble f)725 gimp_matrix3_affine (GimpMatrix3 *matrix,
726 gdouble a,
727 gdouble b,
728 gdouble c,
729 gdouble d,
730 gdouble e,
731 gdouble f)
732 {
733 GimpMatrix3 affine;
734
735 affine.coeff[0][0] = a;
736 affine.coeff[1][0] = b;
737 affine.coeff[2][0] = 0.0;
738
739 affine.coeff[0][1] = c;
740 affine.coeff[1][1] = d;
741 affine.coeff[2][1] = 0.0;
742
743 affine.coeff[0][2] = e;
744 affine.coeff[1][2] = f;
745 affine.coeff[2][2] = 1.0;
746
747 gimp_matrix3_mult (&affine, matrix);
748 }
749
750 /**
751 * gimp_matrix3_determinant:
752 * @matrix: The input matrix.
753 *
754 * Calculates the determinant of the given matrix.
755 *
756 * Returns: The determinant.
757 */
758 gdouble
gimp_matrix3_determinant(const GimpMatrix3 * matrix)759 gimp_matrix3_determinant (const GimpMatrix3 *matrix)
760 {
761 gdouble determinant;
762
763 determinant = (matrix->coeff[0][0] *
764 (matrix->coeff[1][1] * matrix->coeff[2][2] -
765 matrix->coeff[1][2] * matrix->coeff[2][1]));
766 determinant -= (matrix->coeff[1][0] *
767 (matrix->coeff[0][1] * matrix->coeff[2][2] -
768 matrix->coeff[0][2] * matrix->coeff[2][1]));
769 determinant += (matrix->coeff[2][0] *
770 (matrix->coeff[0][1] * matrix->coeff[1][2] -
771 matrix->coeff[0][2] * matrix->coeff[1][1]));
772
773 return determinant;
774 }
775
776 /**
777 * gimp_matrix3_invert:
778 * @matrix: The matrix that is to be inverted.
779 *
780 * Inverts the given matrix.
781 */
782 void
gimp_matrix3_invert(GimpMatrix3 * matrix)783 gimp_matrix3_invert (GimpMatrix3 *matrix)
784 {
785 GimpMatrix3 inv;
786 gdouble det;
787
788 det = gimp_matrix3_determinant (matrix);
789
790 if (det == 0.0)
791 return;
792
793 det = 1.0 / det;
794
795 inv.coeff[0][0] = (matrix->coeff[1][1] * matrix->coeff[2][2] -
796 matrix->coeff[1][2] * matrix->coeff[2][1]) * det;
797
798 inv.coeff[1][0] = - (matrix->coeff[1][0] * matrix->coeff[2][2] -
799 matrix->coeff[1][2] * matrix->coeff[2][0]) * det;
800
801 inv.coeff[2][0] = (matrix->coeff[1][0] * matrix->coeff[2][1] -
802 matrix->coeff[1][1] * matrix->coeff[2][0]) * det;
803
804 inv.coeff[0][1] = - (matrix->coeff[0][1] * matrix->coeff[2][2] -
805 matrix->coeff[0][2] * matrix->coeff[2][1]) * det;
806
807 inv.coeff[1][1] = (matrix->coeff[0][0] * matrix->coeff[2][2] -
808 matrix->coeff[0][2] * matrix->coeff[2][0]) * det;
809
810 inv.coeff[2][1] = - (matrix->coeff[0][0] * matrix->coeff[2][1] -
811 matrix->coeff[0][1] * matrix->coeff[2][0]) * det;
812
813 inv.coeff[0][2] = (matrix->coeff[0][1] * matrix->coeff[1][2] -
814 matrix->coeff[0][2] * matrix->coeff[1][1]) * det;
815
816 inv.coeff[1][2] = - (matrix->coeff[0][0] * matrix->coeff[1][2] -
817 matrix->coeff[0][2] * matrix->coeff[1][0]) * det;
818
819 inv.coeff[2][2] = (matrix->coeff[0][0] * matrix->coeff[1][1] -
820 matrix->coeff[0][1] * matrix->coeff[1][0]) * det;
821
822 *matrix = inv;
823 }
824
825
826 /* functions to test for matrix properties */
827
828 /**
829 * gimp_matrix3_is_identity:
830 * @matrix: The matrix that is to be tested.
831 *
832 * Checks if the given matrix is the identity matrix.
833 *
834 * Returns: %TRUE if the matrix is the identity matrix, %FALSE otherwise
835 */
836 gboolean
gimp_matrix3_is_identity(const GimpMatrix3 * matrix)837 gimp_matrix3_is_identity (const GimpMatrix3 *matrix)
838 {
839 gint i, j;
840
841 for (i = 0; i < 3; i++)
842 {
843 for (j = 0; j < 3; j++)
844 {
845 if (i == j)
846 {
847 if (fabs (matrix->coeff[i][j] - 1.0) > EPSILON)
848 return FALSE;
849 }
850 else
851 {
852 if (fabs (matrix->coeff[i][j]) > EPSILON)
853 return FALSE;
854 }
855 }
856 }
857
858 return TRUE;
859 }
860
861 /**
862 * gimp_matrix3_is_diagonal:
863 * @matrix: The matrix that is to be tested.
864 *
865 * Checks if the given matrix is diagonal.
866 *
867 * Returns: %TRUE if the matrix is diagonal, %FALSE otherwise
868 */
869 gboolean
gimp_matrix3_is_diagonal(const GimpMatrix3 * matrix)870 gimp_matrix3_is_diagonal (const GimpMatrix3 *matrix)
871 {
872 gint i, j;
873
874 for (i = 0; i < 3; i++)
875 {
876 for (j = 0; j < 3; j++)
877 {
878 if (i != j && fabs (matrix->coeff[i][j]) > EPSILON)
879 return FALSE;
880 }
881 }
882
883 return TRUE;
884 }
885
886 /**
887 * gimp_matrix3_is_affine:
888 * @matrix: The matrix that is to be tested.
889 *
890 * Checks if the given matrix defines an affine transformation.
891 *
892 * Returns: %TRUE if the matrix defines an affine transformation,
893 * %FALSE otherwise
894 *
895 * Since: 2.4
896 */
897 gboolean
gimp_matrix3_is_affine(const GimpMatrix3 * matrix)898 gimp_matrix3_is_affine (const GimpMatrix3 *matrix)
899 {
900 return (fabs (matrix->coeff[2][0]) < EPSILON &&
901 fabs (matrix->coeff[2][1]) < EPSILON &&
902 fabs (matrix->coeff[2][2] - 1.0) < EPSILON);
903 }
904
905 /**
906 * gimp_matrix3_is_simple:
907 * @matrix: The matrix that is to be tested.
908 *
909 * Checks if we'll need to interpolate when applying this matrix as
910 * a transformation.
911 *
912 * Returns: %TRUE if all entries of the upper left 2x2 matrix are
913 * either 0 or 1, %FALSE otherwise
914 */
915 gboolean
gimp_matrix3_is_simple(const GimpMatrix3 * matrix)916 gimp_matrix3_is_simple (const GimpMatrix3 *matrix)
917 {
918 gdouble absm;
919 gint i, j;
920
921 for (i = 0; i < 2; i++)
922 {
923 for (j = 0; j < 2; j++)
924 {
925 absm = fabs (matrix->coeff[i][j]);
926 if (absm > EPSILON && fabs (absm - 1.0) > EPSILON)
927 return FALSE;
928 }
929 }
930
931 return TRUE;
932 }
933
934 /**
935 * gimp_matrix3_equal:
936 * @matrix1: The first matrix
937 * @matrix2: The second matrix
938 *
939 * Checks if two matrices are equal.
940 *
941 * Returns: %TRUE the matrices are equal, %FALSE otherwise
942 *
943 * Since: 2.10.16
944 */
945 gboolean
gimp_matrix3_equal(const GimpMatrix3 * matrix1,const GimpMatrix3 * matrix2)946 gimp_matrix3_equal (const GimpMatrix3 *matrix1,
947 const GimpMatrix3 *matrix2)
948 {
949 gint i, j;
950
951 for (i = 0; i < 3; i++)
952 {
953 for (j = 0; j < 3; j++)
954 {
955 if (fabs (matrix1->coeff[i][j] - matrix2->coeff[i][j]) > EPSILON)
956 return FALSE;
957 }
958 }
959
960 return TRUE;
961 }
962
963 /**
964 * gimp_matrix4_identity:
965 * @matrix: A matrix.
966 *
967 * Sets the matrix to the identity matrix.
968 *
969 * Since: 2.10.16
970 */
971 void
gimp_matrix4_identity(GimpMatrix4 * matrix)972 gimp_matrix4_identity (GimpMatrix4 *matrix)
973 {
974 gint i, j;
975
976 for (i = 0; i < 4; i++)
977 {
978 for (j = 0; j < 4; j++)
979 matrix->coeff[i][j] = i == j;
980 }
981 }
982
983 /**
984 * gimp_matrix4_mult:
985 * @matrix1: The first input matrix.
986 * @matrix2: The second input matrix which will be overwritten by the result.
987 *
988 * Multiplies two matrices and puts the result into the second one.
989 *
990 * Since: 2.10.16
991 */
992 void
gimp_matrix4_mult(const GimpMatrix4 * matrix1,GimpMatrix4 * matrix2)993 gimp_matrix4_mult (const GimpMatrix4 *matrix1,
994 GimpMatrix4 *matrix2)
995 {
996 GimpMatrix4 result = {};
997 gint i, j, k;
998
999 for (i = 0; i < 4; i++)
1000 {
1001 for (j = 0; j < 4; j++)
1002 {
1003 for (k = 0; k < 4; k++)
1004 result.coeff[i][j] += matrix1->coeff[i][k] * matrix2->coeff[k][j];
1005 }
1006 }
1007
1008 *matrix2 = result;
1009 }
1010
1011 /**
1012 * gimp_matrix4_to_deg:
1013 * @matrix:
1014 * @a:
1015 * @b:
1016 * @c:
1017 *
1018 *
1019 **/
1020 void
gimp_matrix4_to_deg(const GimpMatrix4 * matrix,gdouble * a,gdouble * b,gdouble * c)1021 gimp_matrix4_to_deg (const GimpMatrix4 *matrix,
1022 gdouble *a,
1023 gdouble *b,
1024 gdouble *c)
1025 {
1026 *a = 180 * (asin (matrix->coeff[1][0]) / G_PI_2);
1027 *b = 180 * (asin (matrix->coeff[2][0]) / G_PI_2);
1028 *c = 180 * (asin (matrix->coeff[2][1]) / G_PI_2);
1029 }
1030
1031 /**
1032 * gimp_matrix4_transform_point:
1033 * @matrix: The transformation matrix.
1034 * @x: The source X coordinate.
1035 * @y: The source Y coordinate.
1036 * @z: The source Z coordinate.
1037 * @newx: The transformed X coordinate.
1038 * @newy: The transformed Y coordinate.
1039 * @newz: The transformed Z coordinate.
1040 *
1041 * Transforms a point in 3D as specified by the transformation matrix.
1042 *
1043 * Returns: The transformed W coordinate.
1044 *
1045 * Since: 2.10.16
1046 */
1047 gdouble
gimp_matrix4_transform_point(const GimpMatrix4 * matrix,gdouble x,gdouble y,gdouble z,gdouble * newx,gdouble * newy,gdouble * newz)1048 gimp_matrix4_transform_point (const GimpMatrix4 *matrix,
1049 gdouble x,
1050 gdouble y,
1051 gdouble z,
1052 gdouble *newx,
1053 gdouble *newy,
1054 gdouble *newz)
1055 {
1056 gdouble neww;
1057
1058 *newx = matrix->coeff[0][0] * x +
1059 matrix->coeff[0][1] * y +
1060 matrix->coeff[0][2] * z +
1061 matrix->coeff[0][3];
1062 *newy = matrix->coeff[1][0] * x +
1063 matrix->coeff[1][1] * y +
1064 matrix->coeff[1][2] * z +
1065 matrix->coeff[1][3];
1066 *newz = matrix->coeff[2][0] * x +
1067 matrix->coeff[2][1] * y +
1068 matrix->coeff[2][2] * z +
1069 matrix->coeff[2][3];
1070 neww = matrix->coeff[3][0] * x +
1071 matrix->coeff[3][1] * y +
1072 matrix->coeff[3][2] * z +
1073 matrix->coeff[3][3];
1074
1075 *newx /= neww;
1076 *newy /= neww;
1077 *newz /= neww;
1078
1079 return neww;
1080 }
1081