root/ext/gd/libgd/gd_matrix.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. gdAffineApplyToPointF
  2. gdAffineInvert
  3. gdAffineFlip
  4. gdAffineConcat
  5. gdAffineIdentity
  6. gdAffineScale
  7. gdAffineRotate
  8. gdAffineShearHorizontal
  9. gdAffineShearVertical
  10. gdAffineTranslate
  11. gdAffineExpansion
  12. gdAffineRectilinear
  13. gdAffineEqual

   1 #include "gd.h"
   2 #include <math.h>
   3 
   4 #ifndef M_PI
   5 # define M_PI 3.14159265358979323846
   6 #endif
   7 
   8 /**
   9  * Title: Matrix
  10  * Group: Affine Matrix
  11  */
  12 
  13 /**
  14  * Function: gdAffineApplyToPointF
  15  *  Applies an affine transformation to a point (floating point
  16  *  gdPointF)
  17  *
  18  *
  19  * Parameters:
  20  *      dst - Where to store the resulting point
  21  *  affine - Source Point
  22  *  flip_horz - affine matrix
  23  *
  24  * Returns:
  25  *  GD_TRUE if the affine is rectilinear or GD_FALSE
  26  */
  27 int gdAffineApplyToPointF (gdPointFPtr dst, const gdPointFPtr src,
  28                   const double affine[6])
  29 {
  30         double x = src->x;
  31         double y = src->y;
  32         x = src->x;
  33         y = src->y;
  34         dst->x = x * affine[0] + y * affine[2] + affine[4];
  35         dst->y = x * affine[1] + y * affine[3] + affine[5];
  36         return GD_TRUE;
  37 }
  38 
  39 /**
  40  * Function: gdAffineInvert
  41  *  Find the inverse of an affine transformation.
  42  *
  43  * All non-degenerate affine transforms are invertible. Applying the
  44  * inverted matrix will restore the original values. Multiplying <src>
  45  * by <dst> (commutative) will return the identity affine (rounding
  46  * error possible).
  47  *
  48  * Parameters:
  49  *      dst - Where to store the resulting affine transform
  50  *  src_affine - Original affine matrix
  51  *  flip_horz - Whether or not to flip horizontally
  52  *  flip_vert - Whether or not to flip vertically
  53  *
  54  * See also:
  55  *  <gdAffineIdentity>
  56  *
  57  * Returns:
  58  *  GD_TRUE if the affine is rectilinear or GD_FALSE
  59  */
  60 int gdAffineInvert (double dst[6], const double src[6])
  61 {
  62         double r_det = (src[0] * src[3] - src[1] * src[2]);
  63 
  64         if (r_det <= 0.0) {
  65                 return GD_FALSE;
  66         }
  67 
  68         r_det = 1.0 / r_det;
  69         dst[0] = src[3] * r_det;
  70         dst[1] = -src[1] * r_det;
  71         dst[2] = -src[2] * r_det;
  72         dst[3] = src[0] * r_det;
  73         dst[4] = -src[4] * dst[0] - src[5] * dst[2];
  74         dst[5] = -src[4] * dst[1] - src[5] * dst[3];
  75         return GD_TRUE;
  76 }
  77 
  78 /**
  79  * Function: gdAffineFlip
  80  *  Flip an affine transformation horizontally or vertically.
  81  *
  82  * Flips the affine transform, giving GD_FALSE for <flip_horz> and
  83  * <flip_vert> will clone the affine matrix. GD_TRUE for both will
  84  * copy a 180° rotation.
  85  *
  86  * Parameters:
  87  *      dst - Where to store the resulting affine transform
  88  *  src_affine - Original affine matrix
  89  *  flip_h - Whether or not to flip horizontally
  90  *  flip_v - Whether or not to flip vertically
  91  *
  92  * Returns:
  93  *  GD_SUCCESS on success or GD_FAILURE
  94  */
  95 int gdAffineFlip (double dst[6], const double src[6], const int flip_h, const int flip_v)
  96 {
  97         dst[0] = flip_h ? - src[0] : src[0];
  98         dst[1] = flip_h ? - src[1] : src[1];
  99         dst[2] = flip_v ? - src[2] : src[2];
 100         dst[3] = flip_v ? - src[3] : src[3];
 101         dst[4] = flip_h ? - src[4] : src[4];
 102         dst[5] = flip_v ? - src[5] : src[5];
 103         return GD_TRUE;
 104 }
 105 
 106 /**
 107  * Function: gdAffineConcat
 108  * Concat (Multiply) two affine transformation matrices.
 109  *
 110  * Concats two affine transforms together, i.e. the result
 111  * will be the equivalent of doing first the transformation m1 and then
 112  * m2. All parameters can be the same matrix (safe to call using
 113  * the same array for all three arguments).
 114  *
 115  * Parameters:
 116  *      dst - Where to store the resulting affine transform
 117  *  m1 - First affine matrix
 118  *  m2 - Second affine matrix
 119  *
 120  * Returns:
 121  *  GD_SUCCESS on success or GD_FAILURE
 122  */
 123 int gdAffineConcat (double dst[6], const double m1[6], const double m2[6])
 124 {
 125         double dst0, dst1, dst2, dst3, dst4, dst5;
 126 
 127         dst0 = m1[0] * m2[0] + m1[1] * m2[2];
 128         dst1 = m1[0] * m2[1] + m1[1] * m2[3];
 129         dst2 = m1[2] * m2[0] + m1[3] * m2[2];
 130         dst3 = m1[2] * m2[1] + m1[3] * m2[3];
 131         dst4 = m1[4] * m2[0] + m1[5] * m2[2] + m2[4];
 132         dst5 = m1[4] * m2[1] + m1[5] * m2[3] + m2[5];
 133         dst[0] = dst0;
 134         dst[1] = dst1;
 135         dst[2] = dst2;
 136         dst[3] = dst3;
 137         dst[4] = dst4;
 138         dst[5] = dst5;
 139         return GD_TRUE;
 140 }
 141 
 142 /**
 143  * Function: gdAffineIdentity
 144  * Set up the identity matrix.
 145  *
 146  * Parameters:
 147  *      dst - Where to store the resulting affine transform
 148  *
 149  * Returns:
 150  *  GD_SUCCESS on success or GD_FAILURE
 151  */
 152 int gdAffineIdentity (double dst[6])
 153 {
 154         dst[0] = 1;
 155         dst[1] = 0;
 156         dst[2] = 0;
 157         dst[3] = 1;
 158         dst[4] = 0;
 159         dst[5] = 0;
 160         return GD_TRUE;
 161 }
 162 
 163 /**
 164  * Function: gdAffineScale
 165  * Set up a scaling matrix.
 166  *
 167  * Parameters:
 168  *      scale_x - X scale factor
 169  *      scale_y - Y scale factor
 170  *
 171  * Returns:
 172  *  GD_SUCCESS on success or GD_FAILURE
 173  */
 174 int gdAffineScale (double dst[6], const double scale_x, const double scale_y)
 175 {
 176         dst[0] = scale_x;
 177         dst[1] = 0;
 178         dst[2] = 0;
 179         dst[3] = scale_y;
 180         dst[4] = 0;
 181         dst[5] = 0;
 182         return GD_TRUE;
 183 }
 184 
 185 /**
 186  * Function: gdAffineRotate
 187  * Set up a rotation affine transform.
 188  *
 189  * Like the other angle in libGD, in which increasing y moves
 190  * downward, this is a counterclockwise rotation.
 191  *
 192  * Parameters:
 193  *      dst - Where to store the resulting affine transform
 194  *      angle - Rotation angle in degrees
 195  *
 196  * Returns:
 197  *  GD_SUCCESS on success or GD_FAILURE
 198  */
 199 int gdAffineRotate (double dst[6], const double angle)
 200 {
 201         const double sin_t = sin (angle * M_PI / 180.0);
 202         const double cos_t = cos (angle * M_PI / 180.0);
 203 
 204         dst[0] = cos_t;
 205         dst[1] = sin_t;
 206         dst[2] = -sin_t;
 207         dst[3] = cos_t;
 208         dst[4] = 0;
 209         dst[5] = 0;
 210         return GD_TRUE;
 211 }
 212 
 213 /**
 214  * Function: gdAffineShearHorizontal
 215  * Set up a horizontal shearing matrix || becomes \\.
 216  *
 217  * Parameters:
 218  *      dst - Where to store the resulting affine transform
 219  *      angle - Shear angle in degrees
 220  *
 221  * Returns:
 222  *  GD_SUCCESS on success or GD_FAILURE
 223  */
 224 int gdAffineShearHorizontal(double dst[6], const double angle)
 225 {
 226         dst[0] = 1;
 227         dst[1] = 0;
 228         dst[2] = tan(angle * M_PI / 180.0);
 229         dst[3] = 1;
 230         dst[4] = 0;
 231         dst[5] = 0;
 232         return GD_TRUE;
 233 }
 234 
 235 /**
 236  * Function: gdAffineShearVertical
 237  * Set up a vertical shearing matrix, columns are untouched.
 238  *
 239  * Parameters:
 240  *      dst - Where to store the resulting affine transform
 241  *      angle - Shear angle in degrees
 242  *
 243  * Returns:
 244  *  GD_SUCCESS on success or GD_FAILURE
 245  */
 246 int gdAffineShearVertical(double dst[6], const double angle)
 247 {
 248         dst[0] = 1;
 249         dst[1] = tan(angle * M_PI / 180.0);;
 250         dst[2] = 0;
 251         dst[3] = 1;
 252         dst[4] = 0;
 253         dst[5] = 0;
 254         return GD_TRUE;
 255 }
 256 
 257 /**
 258  * Function: gdAffineTranslate
 259  * Set up a translation matrix.
 260  *
 261  * Parameters:
 262  *      dst - Where to store the resulting affine transform
 263  *      offset_x - Horizontal translation amount
 264  *      offset_y - Vertical translation amount
 265  *
 266  * Returns:
 267  *  GD_SUCCESS on success or GD_FAILURE
 268  */
 269 int gdAffineTranslate (double dst[6], const double offset_x, const double offset_y)
 270 {
 271         dst[0] = 1;
 272         dst[1] = 0;
 273         dst[2] = 0;
 274         dst[3] = 1;
 275         dst[4] = offset_x;
 276         dst[5] = offset_y;
 277     return GD_TRUE;
 278 }
 279 
 280 /**
 281  * gdAffineexpansion: Find the affine's expansion factor.
 282  * @src: The affine transformation.
 283  *
 284  * Finds the expansion factor, i.e. the square root of the factor
 285  * by which the affine transform affects area. In an affine transform
 286  * composed of scaling, rotation, shearing, and translation, returns
 287  * the amount of scaling.
 288  *
 289  *  GD_SUCCESS on success or GD_FAILURE
 290  **/
 291 double gdAffineExpansion (const double src[6])
 292 {
 293   return sqrt (fabs (src[0] * src[3] - src[1] * src[2]));
 294 }
 295 
 296 /**
 297  * Function: gdAffineRectilinear
 298  * Determines whether the affine transformation is axis aligned. A
 299  * tolerance has been implemented using GD_EPSILON.
 300  *
 301  * Parameters:
 302  *      m - The affine transformation
 303  *
 304  * Returns:
 305  *  GD_TRUE if the affine is rectilinear or GD_FALSE
 306  */
 307 int gdAffineRectilinear (const double m[6])
 308 {
 309   return ((fabs (m[1]) < GD_EPSILON && fabs (m[2]) < GD_EPSILON) ||
 310           (fabs (m[0]) < GD_EPSILON && fabs (m[3]) < GD_EPSILON));
 311 }
 312 
 313 /**
 314  * Function: gdAffineEqual
 315  * Determines whether two affine transformations are equal. A tolerance
 316  * has been implemented using GD_EPSILON.
 317  *
 318  * Parameters:
 319  *      m1 - The first affine transformation
 320  *      m2 - The first affine transformation
 321  *
 322  * Returns:
 323  *      GD_SUCCESS on success or GD_FAILURE
 324  */
 325 int gdAffineEqual (const double m1[6], const double m2[6])
 326 {
 327   return (fabs (m1[0] - m2[0]) < GD_EPSILON &&
 328           fabs (m1[1] - m2[1]) < GD_EPSILON &&
 329           fabs (m1[2] - m2[2]) < GD_EPSILON &&
 330           fabs (m1[3] - m2[3]) < GD_EPSILON &&
 331           fabs (m1[4] - m2[4]) < GD_EPSILON &&
 332           fabs (m1[5] - m2[5]) < GD_EPSILON);
 333 }
 334 

/* [<][>][^][v][top][bottom][index][help] */