aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlan Third2019-06-11 20:31:24 +0100
committerAlan Third2019-06-16 20:24:53 +0100
commit11b0e33462fa7ebef142953010e25728543d1be8 (patch)
tree9595b80194dcc0a8ea3bf9c999b8dbe6cca82ba9 /src
parenta1508e8d2db0003fafb53ae51ed1104ba957db6b (diff)
downloademacs-11b0e33462fa7ebef142953010e25728543d1be8.tar.gz
emacs-11b0e33462fa7ebef142953010e25728543d1be8.zip
Document image transforms
* doc/lispref/display.texi (Image Descriptors): Document :crop and update :rotation. * src/image.c: Describe the image transform matrix layout. * test/manual/image-transforms-tests.el: New file.
Diffstat (limited to 'src')
-rw-r--r--src/image.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/image.c b/src/image.c
index 86f8e8f4bb7..a3747cfa6b7 100644
--- a/src/image.c
+++ b/src/image.c
@@ -1967,6 +1967,87 @@ compute_image_size (size_t width, size_t height,
1967} 1967}
1968#endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_TRANSFORMS */ 1968#endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_TRANSFORMS */
1969 1969
1970/* image_set_rotation, image_set_crop, image_set_size and
1971 image_set_transform use affine transformation matrices to perform
1972 various transforms on the image. The matrix is a 2D array of
1973 doubles. It is laid out like this:
1974
1975 m[0][0] = m11 | m[1][0] = m12 | m[2][0] = tx
1976 --------------+---------------+-------------
1977 m[0][1] = m21 | m[1][1] = m22 | m[2][1] = ty
1978 --------------+---------------+-------------
1979 m[0][2] = 0 | m[1][2] = 0 | m[2][2] = 1
1980
1981 tx and ty represent translations, m11 and m22 represent scaling
1982 transforms and m21 and m12 represent shear transforms. Most
1983 graphics toolkits don't require the third row, however it is
1984 necessary for multiplication.
1985
1986 Transforms are done by creating a matrix for each action we wish to
1987 take, then multiplying the transformation matrix by each of those
1988 matrices in order (matrix multiplication is not commutative).
1989 After we’ve done that we can use our modified transformation matrix
1990 to transform points. We take the x and y coordinates and convert
1991 them into a 3x1 matrix and multiply that by the transformation
1992 matrix and it gives us a new, transformed, set of coordinates:
1993
1994 [m11 m12 tx] [x] [m11*x+m12*y+tx*1] [x']
1995 [m21 m22 ty] X [y] = [m21*x+m22*y+ty*1] = [y']
1996 [ 0 0 1] [1] [ 0*x+0*y+1*1] [ 1]
1997
1998 We don’t have to worry about the last step as the graphics toolkit
1999 will do it for us.
2000
2001 The three transforms we are concerned with are translation, scaling
2002 and rotation. The translation matrix looks like this:
2003
2004 [1 0 tx]
2005 [0 1 ty]
2006 [0 0 1]
2007
2008 Where tx and ty are the amount to translate the origin in the x and
2009 y coordinates, respectively. Since we are translating the origin
2010 and not the image data itself, it can appear backwards in use, for
2011 example to move the image 10 pixels to the right, you would set tx
2012 to -10.
2013
2014 To scale we use:
2015
2016 [x 0 0]
2017 [0 y 0]
2018 [0 0 1]
2019
2020 Where x and y are the amounts to scale in the x and y dimensions.
2021 Values smaller than 1 make the image larger, values larger than 1
2022 make it smaller. Negative values flip the image. For example to
2023 double the image size set x and y to 0.5.
2024
2025 To rotate we use:
2026
2027 [ cos(r) sin(r) 0]
2028 [-sin(r) cos(r) 0]
2029 [ 0 0 1]
2030
2031 Where r is the angle of rotation required. Rotation occurs around
2032 the origin, not the centre of the image. Note that this is
2033 normally considered a counter-clockwise rotation, however because
2034 our y axis is reversed, (0, 0) at the top left, it works as a
2035 clockwise rotation.
2036
2037 The full process of rotating an image is to move the origin to the
2038 centre of the image (width/2, height/2), perform the rotation, and
2039 finally move the origin back to the top left of the image, which
2040 may now be a different corner.
2041
2042 Cropping is easier as we just move the origin to the top left of
2043 where we want to crop and set the width and height accordingly.
2044 The matrices don’t know anything about width and height.
2045
2046 It's possible to pre-calculate the matrix multiplications and just
2047 generate one transform matrix that will do everything we need in a
2048 single step, but the maths for each element is much more complex
2049 and I thought it was better to perform the steps separately. */
2050
1970typedef double matrix3x3[3][3]; 2051typedef double matrix3x3[3][3];
1971 2052
1972static void 2053static void