Reputation: 157
I'd like to outline an object in a transparent background with a 20px border. But, I want to fill in the closed regions with the border color.
$image = new Imagick('./img/hinata.png');
$mask = clone $image;
$mask->separateImageChannel(Imagick::CHANNEL_ALPHA);
$mask->negateImage(true);
$mask->edgeImage(20);
$mask->opaquePaintImage("white","blue",65000,false);
//// TODO: I don't know how to fill the holes
$mask->transparentPaintImage("black",0.0,0,false);
$image->compositeImage($mask,Imagick::COMPOSITE_DEFAULT,0,0);
I referenced this question: Outline a transparent image using imagick PHP
This is what I want to achieve:
This is not what I want to achieve:
Upvotes: 3
Views: 1147
Reputation: 53071
This is how I would do it in ImageMagick command line.
Make the background under the transparency blue.
Extract the alpha channel.
Dilate the alpha channel.
Use connected components to fill in any "holes" smaller than some threshold in area.
Replace the old alpha channel with the new one
Input: from here
convert cartoon_girl.png -background blue -alpha background \
\( -clone 0 -alpha extract \
-morphology dilate diamond:12 \
-define connected-components:mean-color=true \
-define connected-components:area-threshold=500 \
-connected-components 8 \) \
-alpha off -compose copy_opacity -composite \
result.png
Unfortunately, Imagick does not support connected components as far as I know. So the only other way would be to use flood fill at some point inside each "hole". That means you have to pick x,y coordinate inside each hole to use for doing the flood fill after doing the dilate. See https://www.php.net/manual/en/imagick.floodfillpaintimage.php
convert cartoon_girl.png -background blue -alpha background \
\( -clone 0 -alpha extract \
-morphology dilate diamond:12 \
-fuzz 80% -fill white \
-draw "color 100,310 floodfill" \
-draw "color 200,235 floodfill" -alpha off \) \
-alpha off -compose copy_opacity -composite \
result2.png
Upvotes: 2