Search code examples
imagemagick

How to pass as variable a composite region?


I'm running this command (in ImageMagick 7.0.10-61 Q16 under cygwin)

convert input.png -crop 100x50+20+80 +repage \( -size 15x10 xc:white \) -geometry +20+0 -composite output.png

and works fine. Now I want to include the "white region" as variable since depends of a previous if control block. I'm doing in the way shown below, and even the output image is generated I get those errors. How to fix this? Thanks in advance

white_region=" \( -size 15x10 xc:white \) -geometry +20+0 -composite "

$ convert input.png -crop 100x50+20+80 +repage ${white_region} output.png
convert: unable to open image '\(': No such file or directory @ error/blob.c/OpenBlob/3537.
convert: no decode delegate for this image format `' @ error/constitute.c/ReadImage/572.
convert: unable to open image '\)': No such file or directory @ error/blob.c/OpenBlob/3537.
convert: unable to open image '\)': No such file or directory @ error/blob.c/OpenBlob/3537.
convert: no decode delegate for this image format `' @ error/constitute.c/ReadImage/572.

UPDATE 1

Having these 2 input images in a folder. One image with a width of 335px and the other with a width of 480px. For images with w=335px apply one white_region else apply another white_region

Input1.png Input2.png

If I run this script I get output correctly:

for image in *.png; do
    w=$(identify -ping -format '%w' $image)
    
    if [ $w == 335 ]; then
        h=192
        convert ${image} -crop ${w}x${h}+0+0 +repage \( -size 120x25 xc:white \) -geometry +0+0 -composite out_${image}
    else
        h=232
        convert ${image} -crop ${w}x${h}+0+0 +repage \( -size 130x15 xc:white \) -geometry +0+0 -composite \( -size 140x50 xc:white \) -geometry +340+0 -composite out_${image}
    fi
done

But if I use the white_region variable I get errors.

for image in *.png; do
    w=$(identify -ping -format '%w' $image)
    
    if [ $w == 335 ]; then
        white_region="\( -size 120x25 xc:white \) -geometry 0+0 -composite"
        h=192
    else
        white_region="\( -size 130x15 xc:white \) -geometry 0+0 -composite \( -size 140x50 xc:white \) -geometry +340+0 -composite "
        h=232
    fi
    
    convert ${image} -crop ${w}x${h}+0+0 +repage ${white_region} out_${image}
done

UPDATE 2

This is the way that worked for me without escaped parentheses. Thanks all for the help

for image in im*.png; do
    w=$(identify -ping -format '%w' $image)
    
    if [ $w == 335 ]; then
        white_region="-size 120x25 xc:white -geometry +0+0 -composite"
        h=192
    else
        white_region="-size 130x15 xc:white -geometry +0+0 -composite -size 140x50 xc:white -geometry +340+0 -composite"
        h=232
    fi
    
    convert ${image} -crop ${w}x${h}+0+0 ${white_region} out_${image}
done

Solution

  • The parentheses and backslash-escaping of them are unnecessary in your command. You only need parentheses when you want ImageMagick to only apply an "operator" to a single image, rather than all images in a stack.

    This loads "image1.png" and then "image2.png" and crops both:

    magick image1.png image2.png -crop 10x10+0+0 ....
    

    This loads the same two images, but only crops the first:

    magick image1.png -crop 10x10+0+0 image2.png ...
    

    And this loads the same two images, but crops only the second:

    magick image1.png \( image2.png -crop 10x10+0+0 \) ...
    

    However, you are not applying an "operator" like -crop but rather a "setting" of -size which doesn't operate on any images but just sets a parameter that may affect future operators. As such, you don't need parentheses.


    So you can use commands like this:

    partA="-size 80x80 xc:red +append"
    partB="-size 160x80 xc:lime +append"
    magick -size 80x80 xc:blue $partA $partB result.jpg