[Home] [Downloads] [Search] [Help/forum]

Gammon Forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  MUSHclient
. -> [Folder]  Miniwindows
. . -> [Subject]  New image manipulation feature: WindowTransformImage
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

New image manipulation feature: WindowTransformImage

This subject is now closed.     [Refresh] Refresh page


Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Fri 27 Aug 2010 02:52 AM (UTC)

Amended on Fri 27 Aug 2010 10:26 PM (UTC) by Nick Gammon

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
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Fri 27 Aug 2010 06:06 AM (UTC)
Message
For a discussion, see:

Template:post=10528 Please see the forum thread: http://gammon.com.au/forum/?id=10528.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (21,322 posts)  [Biography] bio   Forum Administrator
Date Reply #2 on Fri 27 Aug 2010 06:46 AM (UTC)

Amended on Fri 27 Aug 2010 07:28 AM (UTC) by Nick Gammon

Message
For a lengthier treatment on matrices (and indeed, why I am using the word) see this article:

http://en.wikipedia.org/wiki/Matrix_(mathematics)

A little way down the page, in the section "Linear transformations", it demonstrates the various ways that the matrix elements accomplish the various transformations described above.

In particular, the arguments would be represented as a matrix like this:



[ Mxx   Myx   0 ] 
[ Mxy   Myy   0 ] 
[ Left  Top   1 ] 



- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


3,971 views.

This subject is now closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( https://gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Hosted at FutureQuest]