ImageMagick, set relative size in chain of convert operators

Viewed 92

I'd need to set the size relative to the size already set. I'd need it because my flow involves defining primitives inside other ones. Eg

convert -size 200x100 xc:black \( -size 30x40% xc:red \) -gravity West -composite out.png

That 30x40% is not working this way, it becomes pixels 30x40. I can achieve this specific goal in the first example by using resize

convert -size 200x100 xc:black \( xc:red -resize 30x40% \) -gravity West -composite out.png

In this second version, xc:red inherits the size 200x100, so -resize works as expected. Though the size of further/inner primitives are not reduced to 60x40, it remains 200x100, so in the third example, the green rectangle has orientation landscape and not portrait

convert -size 200x150 xc:blue \
  \( xc:red -resize 50x100% \
    \( xc:green -resize 40% \) \
    -gravity Center \
    -composite \
  \) \
  -gravity West \
  -composite \
  out.png

So green area is 80x60 pixels, 40% of 200x150. I'd like to somehow reset the size to the size of xc:red after resize by the time I'm introducing xc:green.

1 Answers

I think you are trying to create canvases whereby each one is a percentage of the the size of the previous one. There may be an easier way, but you could save each canvas (and implicitly its size) in a MPR "Magick Persistent Register" (named lump of RAM) as you create it, then recall the latest one and overwrite it each time you want to do something relative to that:

convert -gravity west -size 200x100 xc:black -write MPR:S                      \
   \( MPR:S -resize 30x40% -fill red  -colorize 100 -write MPR:S \) -composite \
   \( MPR:S -resize 50x50% -fill blue -colorize 100 -write MPR:S \) -composite \
   \( MPR:S -resize 50x50% -fill lime -colorize 100 \) -composite  result.png

enter image description here


Alternatively, you could let your bash/POSIX shell do it for you inside an "arithmetic expression":

W=200
H=100
convert -gravity west -size ${W}x${H} xc:black                    \
   \( -size $((W=W*30/100))x$((H=H*40/100)) xc:red  \) -composite \
   \( -size $((W=W*50/100))x$((H=H*50/100)) xc:blue \) -composite \
   result.png

enter image description here

Be aware that the shell only deals with integer maths, so it's not going to end well if you aim for 50% of 25 pixels...

Related