analogue dial/clock effect

Questions and postings pertaining to the usage of ImageMagick regardless of the interface. This includes the command-line utilities, as well as the C and C++ APIs. Usage questions are like "How do I use ImageMagick to create drop shadows?".
Post Reply
dj_bung

analogue dial/clock effect

Post by dj_bung »

Hi.

I am trying to create an analogue dial/clock effect out of these two images.

Image
Image

I can get reasonably close by first rotating the arrow to any given angle, then using compose to combine the with gravity set to south, however I am unable to work out how to centre the arrow at the base of the dial pictured.

Code: Select all

convert -rotate 45 arrow.gif r_arrow.gif && composite -gravity south r_arrow.gif dial.gif complete.gif
Can anyone offer some tips on how to do this? Or how this might be done better in one command?

Regards,
Michael
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: analogue dial/clock effect

Post by fmw42 »

For 30 degrees:

convert dial.gif \( arrow.gif -virtual-pixel transparent +distort SRT "22,391 30" \) \
-geometry +328+0 -composite arrow_dial_30.gif

Image

see -distort SRT at http://www.imagemagick.org/Usage/distorts/#srt

I rotated about the bottom center of the arrow by 30 degrees, then composited at the bottom center of the dial, offset by the "half-width" of the arrow (actually 22 pixels rather than 25 as the bottom of middle of the arrow was not truly centered)
dj_bung

Re: analogue dial/clock effect

Post by dj_bung »

Thanks for that, sent me in the right direction for sure!

Is there are way to automate the calculate of the geometry coordinates? I have been unable to find a way. I have come up with

convert dial.gif \( arrow.gif -virtual-pixel transparent +distort SRT "22,391 80" \) -gravity south -composite test.gif

Which will center the arrow at the base of the dial, but using the actual center of the arrow as the point that is centered. If there is a way to specify a point in that arrow that the center operation is based on, that would be all I need.

Any ideas?

Thanks.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: analogue dial/clock effect

Post by fmw42 »

see -distort SRT, you can specify the origin of the rotation. That is what the 22,391 is doing. You can also specify an offset (translation) after the rotation by specifying the location where the center is to be moved. But that was why I put in the -geometry to set the place where to composite the rotated arrow. You can add a small y offset to make the arrow insert a bit lower. The amount can be calculated from the width of the arrow base (not the image width) and the angle of rotation, something like arrowwidth*sin(rotationangle).

See http://www.imagemagick.org/Usage/distorts/#srt

You can do math calculation in IM to set variables using -fx escapes. See http://www.imagemagick.org/Usage/transform/#fx_escapes

for example to find the middle of the image:

xcenter=`convert image -format "%[fx:w/2]" info:`
ycenter=`convert image -format "%[fx:h/2]" info:`

Then you can use those in specifying coordinates in IM by substituting $xcenter and/or $ycenter for actual numbers, but you need to put them in double quotes.
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: analogue dial/clock effect

Post by anthony »

fmw42 wrote:For 30 degrees:

convert dial.gif \( arrow.gif -virtual-pixel transparent +distort SRT "22,391 30" \) \
-geometry +328+0 -composite arrow_dial_30.gif

see -distort SRT at http://www.imagemagick.org/Usage/distorts/#srt

I rotated about the bottom center of the arrow by 30 degrees, then composited at the bottom center of the dial, offset by the "half-width" of the arrow (actually 22 pixels rather than 25 as the bottom of middle of the arrow was not truly centered)

WARNING; Error Error.
+distort will generate a 'layer' image with offsets so as to keep the 'center of rotation' fixed on the virtual canvas. That is at 22,391. However -composite only uses geometry offsets!!! and ignore virtual canvas information completely!! See Composite Geometry vs Layer Offsets.

basically if you try a rotate of say -30 you would have got a very wrong result!

In summery DO NOT MIX THE TWO.
Either compose non-layer images with geometryt, or use layering methods to preserve virtual canvas offsets.


So lets modify the SRT distort to transplate the arrow to the correct 'center' of the half-circle. And layer the image together correctly...

Code: Select all

convert   arrow.gif -virtual-pixel transparent  \
       +distort SRT "24.5,391  1.0  -30.0  350,350"  -trim  \
       dial.gif +swap         -background none  -layers merge +repage  \
       arrow_dial-30.gif
The first coordinate 24.5,391 is the point in the arrow to rotate, while the 350,350 sets the position on the virtual canvas to position that 'center of rotation' (relative to the 'dial' image). The use of +distort ensures the output image is the 'best fit' offset layer image needed to hold the ALL of the arrow image (including the transparent corner pixels ;-)

The 1.0 is the scale factor (needed when setting a destination coordinate for the 'center')
while the -30.0 is the angle (rotate left this time) -trim is used to cut off excess corners in the rotated arrow. The dial is inserted before it and the two images 'layer merged' together.

Note as the 'arrow' does not always 'fit' into the 'dial' image (especially at -90, 0, and +90 angles, and along the bottom) the 'merge' will enlarge the resulting image appropriately to ensure none of the layered images are 'clipped'. You may not want the resulting image to change size, so you may want to 'scale' the arrow (adjusting the 1.0 in the above, or use -flatten instead of -layers merge to 'clip' the overlay to the base 'dial' image.

You may like to read up on distort coordinates...
http://www.imagemagick.org/Usage/distor ... oordinates
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
User avatar
anthony
Posts: 8883
Joined: 2004-05-31T19:27:03-07:00
Authentication code: 8675308
Location: Brisbane, Australia

Re: analogue dial/clock effect

Post by anthony »

The better AND FASTER way to do this is nto to use a arrow image at all!

Instead draw the arrow on the dial.

By reading in the dial image, then drawing the arrows (relative to the point of rotation) you can then rotate and translate the arrow using 'canvas warping'

http://www.imagemagick.org/Usage/draw/#transform

this is faster as IM only has to do position calculations for just a few points to then directly draw the arrow in its final position. It does not have to convert EVERY PIXEL in the arrow image.
that will make it VERY fast! By comparision.
Anthony Thyssen -- Webmaster for ImageMagick Example Pages
https://imagemagick.org/Usage/
Post Reply