gd_matrix.c 7.7 KB

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