geometry calculations

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
User avatar
Draoidh
Posts: 69
Joined: 2012-07-03T11:29:44-07:00
Authentication code: 13
Location: soon to be independent Scotland

geometry calculations

Post by Draoidh »

I am creating the following image by appending two canvases:
In real life, the geometry of the canvases is derived from two existing image files.

Code: Select all

convert -bordercolor black    \( -size 200x100 "xc:#080" \)  \( -size 200x30 "xc:#800" -gravity South -extent x200% \)  -append -border 5% fg.png
Image

Now I would like to create the following image based on the same geometry information:
As I really don't know how to express this with ImageMagick, I'll describe it in plain English:

The image below has the same dimensions as the one created above. The green block extends down to the MIDDLE of the white gap.

Image

I am at my wits end. If anyone can give me an idea how to calculate these two areas, I'd be very grateful
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: geometry calculations

Post by fmw42 »

You have made things very hard by using mixed pixels and percents and by using -gravity south to pad the middle with white in your first image. It would have been better to have spoecified 3 sections to append: green, white, red

Your output image will be 200*1.10=220 wide (the 1.10 comes from 5% additional on each side).
It will also be (100+60)*1.10=176 (though your output is actually 180?). The 60 comes from 200% x 30 for the second part. So adding in the first part of 100 and padding by 5% on both sides gives 176.

Since the green is 100 pixels tall, the white is 30 pixels and red is 30 pixels. Half way down to the middle of the white would be 115 pixels before padding. So the remainder before padding will be 160-45=115. With the padding it will be 45+180*.05=54

Thus the easiest way is to do:

convert \( -size 220x180 xc:"green1" \) \( -size 220x54 xc:"red" \) -gravity south -compose over -composite 1result.png
User avatar
Draoidh
Posts: 69
Joined: 2012-07-03T11:29:44-07:00
Authentication code: 13
Location: soon to be independent Scotland

Re: geometry calculations

Post by Draoidh »

Many thanks for your reply.

The code I posted is a simplified snippet from a parameter driven shell script. The geometry info is in shell variables, derived from varying input pictures:

Code: Select all

DIM1=$(identify -format %wx%h $PIC1)
DIM2=$(identify -format %wx%h $PIC2)
convert ... \( -size$DIM1 "xc:#080" \) \( -size$DIM2 ...
PIC1 and PIC2 have the same width.

Your solution was to create a full-size green box and overlap it with the smaller red one. I would prefer not to do that because the green box might be a gradient rather than a solid colour in which case I'd need to specify the exact height of both the green and the red box.

Like you, I had worked out the figures for this example to produce the second image. However, my problem is whether this can be done programmatically.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: geometry calculations

Post by fmw42 »

If you can compute the parameters as I did above, then you should be able to program it.

This works for me

width=200
height1=100
height2=30
border=5 #percent
ww=$(convert xc: -format "%[fx:$width*(1+2*$border/100)]" info:)
pad=$(convert xc: -format "%[fx:($height1+2*$height2)*($border/100)]" info:)
hh1=$(convert xc: -format "%[fx:$height1+($height2/2)+$pad)]" info:)
hh2=$(convert xc: -format "%[fx:(3/2)*$height2+$pad]" info:)
echo "ww=$ww; pad=$pad; hh1=$hh1; hh2=$hh2;"
convert \( -size ${ww}x${hh1} xc:"green1" \) \( -size ${ww}x${hh2} xc:"red" \) -append 1result.png


But the result is 176 high and not 180. The problem is that -border 5% is not working correctly.

The base image height before the border is 100+2*30=160.

Adding the padding of 5% should give 160*(1+2*.05)=160*1.1=176

When I do the following:

convert -size 200x160 xc:white -bordercolor black -border 5% -format "%h" info:
180


Thus -border specified as 5% is not computing correctly. It seems to be using something like 6.25% as 160*1.125=180

Seems like a bug to me. I have reported it at viewtopic.php?f=3&t=21537
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: geometry calculations

Post by fmw42 »

I got a reply back from Magick. Seems that IM will compute the pixels from the percent value. If only one percent value is supplied, then the pixel value will be used for both dimensions. That means if the image is not square and you specify 5%, that will convert to 5% * width to compute the pad in pixels and use it for both the padding in the width and height. If you really want 5% for both width and height, you need to specify -border 5%x5% or -border 5x5%. This is what I had computed above (thinking incorrectly that the 5% would apply to both dimensions).

Thus if you want to continue to use -border 5%, then my computations above should be modified to:


width=200
height1=100
height2=30
border=5 #percent
pad=$(convert xc: -format "%[fx:($width)*($border/100)]" info:)
ww=$(convert xc: -format "%[fx:$width+2*$pad)]" info:)
hh1=$(convert xc: -format "%[fx:$height1+($height2/2)+$pad)]" info:)
hh2=$(convert xc: -format "%[fx:(3/2)*$height2+$pad]" info:)
echo "ww=$ww; pad=$pad; hh1=$hh1; hh2=$hh2;"
convert \( -size ${ww}x${hh1} xc:"green1" \) \( -size ${ww}x${hh2} xc:"red" \) -append result.png
User avatar
Draoidh
Posts: 69
Joined: 2012-07-03T11:29:44-07:00
Authentication code: 13
Location: soon to be independent Scotland

Re: geometry calculations

Post by Draoidh »

Fred, thanks so much for working through this example for me. I thought fx could do the job but had a few missing links such as info:.
User avatar
Draoidh
Posts: 69
Joined: 2012-07-03T11:29:44-07:00
Authentication code: 13
Location: soon to be independent Scotland

Re: geometry calculations

Post by Draoidh »

Before I gave up and posted my question, I had tried to do the calculations inline:

Code: Select all

convert \( -size 200x100 xc:"green1" \) -extent "%[fx:w*2]" x.png
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: geometry calculations

Post by fmw42 »

Draoidh wrote:Before I gave up and posted my question, I had tried to do the calculations inline:

Code: Select all

convert \( -size 200x100 xc:"green1" \) -extent "%[fx:w*2]" x.png
IM 6 does not allow that in most cases, only a few commands such as -distort, -sparse-color ... allow such. But IM 7 will have much more ability to do that sort of thing. It was one of the major issue that are being worked on by Anthony at this time. You can try IM 7 if you want to experiment, but it is only in alpha development.
User avatar
Draoidh
Posts: 69
Joined: 2012-07-03T11:29:44-07:00
Authentication code: 13
Location: soon to be independent Scotland

Re: geometry calculations

Post by Draoidh »

After all this, I have realized that I can achieve my objective in a much simpler way, which is not to say that I am not interested in the fx stuff at some point.

Making use of the fact that -border <width> gives me an equal-sized border, I create the gap with -border rather than -extent:

Code: Select all

convert -bordercolor black    \( -size 200x100 "xc:#080" \)  \( -size 200x30 "xc:#800"  \)  -border 5% -append fg.png
The gap has a slightly different height but still looks good in my context.

For the second file, it's then going to be easier to split the gap in the middle.

I only take updates from the latest Debian release. It's not always healthy to be at the bleeding edge.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: geometry calculations

Post by fmw42 »

You can always add a white gap by just including a middle section of xc:white of the desired size. That is much more direct that trying to use gravity and -extent or anything else. And you can always use -border in pixels to have the same amount all around. Just compute the border from from the sizes of the images that you put together, if you want percent in width or height. This is the first time I have ever seen or tried using -border in %.
User avatar
Draoidh
Posts: 69
Joined: 2012-07-03T11:29:44-07:00
Authentication code: 13
Location: soon to be independent Scotland

Re: geometry calculations

Post by Draoidh »

fmw42 wrote: This is the first time I have ever seen or tried using -border in %.
That's amazing considering the wealth of scripts you are providing on your site. That's a fantastic piece of work, by the way. I appreciate the amount of work that went into the documentation and examples alone.
User avatar
fmw42
Posts: 25562
Joined: 2007-07-02T17:14:51-07:00
Authentication code: 1152
Location: Sunnyvale, California, USA

Re: geometry calculations

Post by fmw42 »

There is so much to IM, that even I still learn new things often.
Post Reply