Chris
Chris

Reputation: 3817

Drawing to alpha channel using ImageMagick to "cut" a hole into an image

I'm using convert version Version: ImageMagick 7.0.10-24 Q16 x86_64 2020-07-18 on macOS.

I'm attempting to use ImageMagick to create an image comprising simply a coloured circle with a transparent cut-away of a check-mark in the centre. I can create those two elements, but I am having no success in combining them.

This produces a suitably coloured, centred, filled circle on a transparent background, which is exactly what I want:

convert -size 44x44 xc:none \
    -fill '#e9473e' \
    -strokewidth 0 \
    -draw 'translate 21.5,21.5 circle 0,0 21.5,0' \
    circle.png

This produces a checkmark:

convert -size 44x44 xc:'#ffffff00' \
    -stroke '#ffffffff' \
    -strokewidth 3 \
    -draw 'stroke-linecap round  line 13,24 19,30 line 19,30 34,15' \
    tick.png

NOTE: That is just the latest incarnation - I've tried writing only to the alpha channel, starting with an all-transparent image, negating the result etc. The closest I've managed did result in a cut-away, but with an unintentional and un-wanted black halo in the anti-aliased region around the edge.

My current goal/intention is that the final step will be:

convert circle.png tick.png -compose multiply -composite final.png

... but I fully expect somebody more familiar with ImageMagick to combine all of the above into a one-liner, eliminating the repetition of the image size.

Upvotes: 0

Views: 488

Answers (2)

GeeMack
GeeMack

Reputation: 5385

Here's a way to do this with ImageMagick, same concept as your very good answer above, and simplified just a bit.

convert \
    -size 44x44 \
    xc:black \
    -fill white \
    -strokewidth 0 \
    -draw 'translate 21.5,21.5 circle 0,0 21.5,0' \
    -stroke black \
    -strokewidth 3 \
    -draw 'stroke-linecap round line 13,24 19,30 line 19,30 34,15' \
    xc:'#e9473e' \
    +swap \
    -alpha Off \
    -compose copyopacity \
    -composite \
    -depth 8 \
        check.png

That starts by making a black square, drawing a white circle on it, then drawing a black check mark on that circle. That will be the alpha mask.

Then it creates a red square same size as the mask, and that is moved ahead of the mask by switching places with "+swap". So now there are two images in the list, a red square, and the black and white mask.

Setting the the alpha to "off" and compose method to "copyopacity", and doing a "-composite" operation, IM will make the red square transparent where the mask is black, and leave it red where the mask is white. After the composite operation, you're left with the red circle on a transparent background with a check-mark shaped "hole" in the middle.

I added "-depth 8" to the command because some of my image viewing software wasn't real good about rendering the transparencies without it.

Upvotes: 3

Chris
Chris

Reputation: 3817

This is probably far from the minimal solution, but once I realised that the key to this was to separate the colouring and the masking until the final stage, I came up with this solution:

convert -size 44x44 xc:'#e9473e' \
    \( \
        -clone 0 \
        -fill black \
        -colorize 100 \
        -fill white \
        -strokewidth 0 \
        -draw 'translate 21.5,21.5 circle 0,0 21.5,0' \
        -stroke black \
        -strokewidth 3 \
        -draw 'stroke-linecap round  line 13,24 19,30 line 19,30 34,15' \
    \) \
    -alpha Off \
    -compose CopyOpacity \
    -composite \
    checkmark.png

Upvotes: 1

Related Questions