Message
| There is a new miniwindows function in version 4.59 of MUSHclient, called WindowTransformImage.
This lets you copy a loaded image onto any miniwindow (similar to WindowDrawImage) however it lets you:
- Translate
- Scale
- Rotate
- Shear
- Reflect
These operations can be combined by judicious choices of parameters. In particular you would need to do a matrix multiplication (eg. multiply the rotate matrix by the reflect matrix).
For details on matrix multiplication:
http://en.wikipedia.org/wiki/Matrix_multiplication
The translation is done by applying a mathematical operation to the location of each pixel during the copy operation. For each original x and y pixel, the new location x' and y' is determined as follows:
x' = (x * Mxx) + (y * Mxy) + Left
y' = (x * Myx) + (y * Myy) + Top
The function prototype for WindowTransformImage is:
long WindowTransformImage(WindowName, ImageId, Left, Top, Mode, Mxx, Mxy, Myx, Myy);
The Mode parameter can be:
- miniwin.image_copy (1) which does a straight copy
- miniwin.image_transparent_copy (3) which does a transparent copy, where the colour of the pixel in the top left corner (pixel location 0,0) is the transparent colour.
To illustrate, I will use this image:
Image courtesy of Isobel Gammon.
The examples below will all start with a basic miniwindow like this (you can do this in the Immediate scripting window):
-- make window
win = "test" -- window name
WindowCreate (win, 0, 0, 200, 250,
miniwin.pos_top_center, 0, ColourNameToRGB("saddlebrown")) -- create window
WindowShow (win, true) -- show it
-- draw grid
for i = 1, math.max (WindowInfo (win, 3), WindowInfo (win, 4)) / 25 do
WindowLine (win, i * 25, 0, i * 25, WindowInfo (win, 4), 0xC0C0C0, 0, 1)
WindowLine (win, 0, i * 25, WindowInfo (win, 3), i * 25, 0xC0C0C0, 0, 1)
end -- for
-- load image
imageid = "im"
WindowLoadImage (win, imageid, GetInfo (66) .. "may2010.png")
-- get image dimensions
imageWidth = WindowImageInfo (win, imageid, 2)
imageHeight = WindowImageInfo (win, imageid, 3)
That gives this result:
Straight copy
-- straight copy
WindowDrawImage (win, imageid, 50, 50, 0, 0, miniwin.image_copy)
This is the "reference image" which we will be translating, rotating etc.
Identity translation
-- identity matrix (with translation)
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, 1, 0, 0, 1)
The code above produces identical results to the straight copy because it uses the "identity" operation, that is, effectively "itself".
You can see that by substituting in the original formula above:
x' = (x * Mxx) + (y * Mxy) + Left
y' = (x * Myx) + (y * Myy) + Top
Where Mxx = 1, Mxy = 0, Myx = 0, and Myy = 1 we will get:
x' = (x * 1) + (y * 0) + 50
y' = (x * 0) + (y * 1) + 50
That is:
x' = x + 50
y' = y + 50
The Left and Top values are merely added and therefore translate (move sideways) the final pixel.
Reflection
To reflect on the X axis we negate the X values, like this:
-- reflection on X axis
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, -1, 0, 0, 1)
Note that the reflection has effectively moved the image sideways (because the x values are now negative). To compensate we need to add back in the image width.
-- reflection on X axis
WindowTransformImage (win, imageid, 50 + imageWidth, 50, miniwin.image_copy, -1, 0, 0, 1)
Now the image is back where it started, but just reflected on the X axis.
To reflect on the Y axis we negate the Y values, like this:
-- reflection on Y axis
WindowTransformImage (win, imageid, 50, 50 + imageHeight, miniwin.image_copy, 1, 0, 0, -1)
In this case we added back in the image height (which you obtain with WindowImageInfo) to compensate for the negation.
To reflect on both axes, we negate both x and y multipliers, and add back in the width and height. Notice that this looks identical to rotating the image 180 degrees.
-- reflection on both axes
WindowTransformImage (win, imageid, 50 + imageWidth, 50 + imageHeight, miniwin.image_copy, -1, 0, 0, -1)
Rotation
First we need to convert our degrees into radians (if we are using degrees) and then work out the sine and cosine. Finally we substitute into the WindowTransformImage as appropriate:
-- rotation angle in degrees
angle = 30
-- angle converted to radians
radians = math.rad (angle)
-- calculate sine and cosine
sine = math.sin (radians)
cosine = math.cos (radians)
-- rotate counterclockwise
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, cosine, sine, -sine, cosine)
Note that this rotated the image 30 degrees counter-clockwise. To rotate clockwise, reverse the sign of the sines:
-- rotate clockwise
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, cosine, -sine, sine, cosine)
Note also that this rotated about the origin (the top-left corner). You may need to translate (change Top and Left) if you wanted to rotate about some other point.
Shear
To shear vertically you borrow part of the X coordinate and add into the Y direction, like this:
-- shear vertically right side downwards
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, 1, 0, 1, 1)
To shear horizontally you add some of the Y component into the X direction:
-- shear horizontally, bottom to the right
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, 1, 0.5, 0, 1)
You can shear the other way by negating the extra value (that is, change 0.5 to -0.5).
Scale
To scale, take the identity matrix and simply multiply by a factor. For example, 1.5 larger:
-- Scale by 1.5 times
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, 1.5, 0, 0, 1.5)
And to make smaller:
-- Scale to half
WindowTransformImage (win, imageid, 50, 50, miniwin.image_copy, 0.5, 0, 0, 0.5)
Notes
- The entire image is copied to the miniwindow when you used WindowTransformImage. If you want to use a smaller image (a sub-image) you would need to copy that first into a non-visible miniwindow, and then use WindowImageFromWindow to turn that into an image.
- The function is only available in Windows 98 onwards. If it cannot set the "advanced" graphics mode necessary an error code (eBadParameter) will be returned.
- You can also use the copy mode miniwin.image_transparent_copy (3). This make the translated image transparent at any place it matches the pixel at 0,0 location.
Example of transparent translation. Source image:
Code:
-- load image
imageid = "im"
WindowLoadImage (win, imageid, GetInfo (66) .. "may2010_transparent.png")
-- get image dimensions
imageWidth = WindowImageInfo (win, imageid, 2)
imageHeight = WindowImageInfo (win, imageid, 3)
-- rotation angle in degrees
angle = 90
-- angle converted to radians
radians = math.rad (angle)
-- calculate sine and cosine
sine = math.sin (radians)
cosine = math.cos (radians)
-- rotate counterclockwise
WindowTransformImage (win, imageid, 50, 50 + imageHeight, miniwin.image_transparent_copy, cosine, sine, -sine, cosine)
Result:
[EDIT] Renamed WindowTranslateImage to WindowTransformImage. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|