"Fossies" - the Fresh Open Source Software Archive

Member "libgd-2.3.3/src/gd_matrix.c" (11 Sep 2021, 8734 Bytes) of package /linux/www/libgd-2.3.3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "gd_matrix.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.3.2_vs_2.3.3.

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