Trying to add a stroke around a PNG, can it be improved? - image-processing

I'm trying to find a good way to add a 3px white stroke to a ton of png files, effectively to make them look like "stickers." I've got some sample code that does a decent job, but I can't seem to get the cropping right. Also, the stroke looks a bit pixelated and I wanted to know if it's possible to get cleaner edges!
I did a bunch of internet scouring, found some sample code, tweaked it around, and came to something that almost resembles what I'm looking for. The images are always going to be PNGs, so I looked into things like inkscape/gimp from the command line but realized I should be able to do this just using convert from the terminal.
convert in.png \
\( -clone 0 -alpha extract -threshold 0 \) \
\( -clone 1 -blur 10x65000 -threshold 0 \) \
\( -clone 2 -fill red -opaque white \) \
\( -clone 3 -clone 0 -clone 1 -alpha off -compose over -composite \) \
-delete 0,1,3 +swap -alpha off -compose copy_opacity -composite \
out.png
in:
out:
ideally:

Your main problem is it is that you do not have enough space bettween your object and the sides of the image. You just need to add your image with transparency and then remove any excess later.
In ImageMagick 6, this should do what you want.
1) read the input
2) add a larger border than you need to add
3) extract the alpha channel from the input and dilate it by the amount of border (in this case 10)
4) copy the previous image and color the white as red and the black as transparent
5) composite the original over the red/transparent image
6) delete the original and the red/transparent image
7) swap the composite with the dilated alpha channel and put the dilated alpha channel into the alpha channel of the previous image
8) trim the excess transparency from the border padding
9) save to output
convert img.png \
-bordercolor none -border 20 \
\( -clone 0 -alpha extract -morphology dilate diamond:10 \) \
\( -clone 1 -fuzz 30% -fill red -opaque white -fill none -opaque black \) \
\( -clone 2,0 -compose over -composite \) \
-delete 0,2 \
+swap -alpha off -compose copy_opacity -composite \
-trim +repage \
result.png
For ImageMagick 7, replace convert with magick.
If on a Unix-like system, you might be interested in my bash ImageMagick script, contour, at http://www.fmwconcepts.com/imagemagick/index.php
A better result can be achieved by replacing diamond:10 with disk:10

Related

Gradient over transparent png image with sparse-color has background color

I have this face source image. I'm tyring to add a gradient to the bottom of the picture so it fades out alpha transparent.
Problem is that the transparent source image is not transparent anymore after sparse-color transformation - the transparent area is now black.
This is my cmd so far:
magick convert face.png -alpha set -background none -channel A -sparse-color barycentric "0,%[fx:h*0.90] white 0,%[h] none" +channel face-gradient.png
Here is how you have to do that in Imagemagick. Your image already has an alpha channel. So you have to create a new grayscale gradient image as a mask and combine that with the existing alpha channel. (The -sparse-color is going to write over your existing alpha channel.)
magick face.png \
\( -clone 0 -alpha extract \) \
\( -clone 0 -sparse-color barycentric "0,%[fx:h*0.90] white 0,%[h] black" \) \
\( -clone 1,2 -compose multiply -composite \) \
-delete 1,2 \
-alpha off -compose copy_opacity -composite face-gradient.png

How to colorize an image with multiply to add transparency to the colour with Image Magick

I would like to colorize an image with two colours, red on the left half and green on the right half but the colorize function just adds a coloured overlay to the image rather than multiplying it on. So I would like my image to look like this but it is currently looking like this. Here is the original image
My code at the moment is this:
convert normal.png \
\( -clone 0 -crop 50x100% -fill red -colorize 60% \) \
\( -clone 0 -crop 50x100%+64 -fill green -colorize 60% \) \
-delete 0 -background none -flatten result.png
I have tried adding -compose multiply -composite to the code but I just get this which has the right effect but I cannot get it to the position that I want, heres the code for that:
convert normal.png \
\( -clone 0 -crop 50x100% -fill red -colorize 70% \) \
\( -clone 0 -crop 50x100%+64 -fill green -colorize 70% \) \
-background none -compose multiply -composite result.png
One simple approach would be to assemble the red-green overlay inside parentheses, then do a multiply composite over the input image.
magick lena_circ.png -size %wx%h \
\( xc:red xc:green +append -scale 50x100% \) \
-compose multiply -channel rgb -composite result.png
That command give me this result...

ImageMagick: How to create torn page effect for specifc edges?

The ImageMagick documentation provides guidance on how to create torn page effects (https://www.imagemagick.org/Usage/thumbnails/#torn). However, in their implementation, all edges are torn. Suppose I wish to tear off only the bottom or top part of the image. How can I achieve such a thing using ImageMagick?
Simply grow the top & sides by using -extent operator.
convert zelda.png -background pink -extent 148x138-10-10 extent.png
(Adding pink background for visibility on stack)
Apply the effect from the Usage documentation.
convert extent.png \( +clone -alpha extract -virtual-pixel black \
-spread 10 -blur 0x3 -threshold 50% -spread 1 -blur 0x.7 \) \
-alpha off -compose Copy_Opacity -composite torn.png
Then crop back to original image size.
convert torn.png -crop 128x129+10+10 output.png
Update
If you do not want to use geometry, you can use a combination of -border, -shave & -chop.
convert zelda.png -bordercolor pink -border 10x10 -gravity South -chop 0x10 extent.png
convert extent.png \( +clone -alpha extract -virtual-pixel black \
-spread 10 -blur 0x3 -threshold 50% -spread 1 -blur 0x.7 \) \
-alpha off -compose Copy_Opacity -composite torn.png
convert torn.png -shave 10x -chop 0x10 output.png
.. And of course, this all can be done with one command.
convert zelda.png -bordercolor pink -border 10x10 -gravity South -chop 0x10 \
\( +clone -alpha extract -virtual-pixel black -spread 10 -blur 0x3 -threshold 50% \
-spread 1 -blur 0x.7 \) -gravity Forget -alpha off -compose Copy_Opacity -composite \
-shave 10x -chop 0x10 output.png
There are several ways to create a torn edge effect using ImageMagick. Here is another example command using IM version 6 and *nix syntax. This should apply a torn effect to just the top edge of any input image while keeping the original dimensions of the image.
convert input.png -alpha set -background black -fill white \
\( +clone -colorize 100 -gravity south -chop 0x6 -splice 0x6 \
-spread 6 -paint 2 +transparent white -blur 0x0.5 \) \
-background none -compose dstin -composite torn.png
That creates a white mask inside the parentheses. Then a small amount of the "torn" edge is chopped off and a black strip is spliced on to replace it. The random-ish torn edge is created using "-spread" and "-paint" between the white and black areas of the mask. After that, outside the parentheses, that mask is used to apply the transparent torn area to the input image.
To apply the effect to the bottom edge, just change the "-gravity north" to "-gravity south".
To make the torn edge on the left or right, change the gravity setting to "west" or "east", and change the values of the "-chop" and "-splice" operations from "0x6" to "6x0".
This should work the same way using ImageMagick version 7 by changing the "convert" command to "magick".
To use it in Windows, remove the backslashes that escape the parentheses from "\(...\)" to "(...)", and change the continued line backslashes "\" to carets "^".

ImageMagick: Remove 2 pixels wide lines

How can I remove two pixels wide lines (like the three lines in the image below) without altering the rest of the image, and repage it to its new minimum border ?
What you want to do is extract the alpha channel. Then use morphology close. Then put the result back into the alpha channel, then trim and save the result. In Imagemagick, that would be:
Input:
convert image.png \
\( -clone 0 -alpha extract -morphology open octagon:2 \) \
-alpha off -compose copy_opacity -composite \
-trim +repage \
result.png
Something like this maybe:
convert captcha.png -morphology erode disk:2 -trim +repage result.png

"Diff" an image using ImageMagick with emphasis

Follow up on “Diff” an image using ImageMagick
When you are working with forms (as opposed to images), the changes are very hard to see with this technique. I wanted to show some type of yellow highlight maybe 10-20 pixels "bigger" (padding) around the actual pixels that changed.
So instead of just this
Something more like this
It seems like I am just missing something here in the stack that can make this work.
convert '(' file1.png -flatten -grayscale Rec709Luminance ')' \
'(' file2.png -flatten -grayscale Rec709Luminance ')' \
... here ? ...
'(' -clone 0-1 -compose darken -composite ')' \
... or here ? ...
-channel RGB -combine diff.png
I can also run this as separate commands and does not need to be fast, most of this is going to be run offline.
I also tried studying the technique here (specifically how the thumbnail scaling gives you the effect I want as the pixels get expanded) but this code is using the library instead of the ImageMagick command line tools. Line 248 => "make the red as visible as possible"
https://github.com/vslavik/diff-pdf/blob/master/diff-pdf.cpp#L218
An example form is the standard W-9. I made 2 subtle changes
PART II .. moved the 2. left about 2 pixels
PART II .. on 4., moved word is to the right 2 pixels
and the compare pumps out this (changes in red that you can barely see)
Thank you for any help
You can use -morphology dilate in Imagemagick to increase the size of the red areas. For example, using your two forms:
convert JW0wZ.png 1nHWT.png -compose difference -composite -morphology dilate disk:10 +level-colors black,red result.gif
UPDATE:
If you want the background transparent, then try
convert JW0wZ.png 1nHWT.png -compose difference -composite -morphology dilate disk:10 +level-colors "black,red" -fuzz 20% -transparent black result.png
Or better
convert JW0wZ.png 1nHWT.png -compose difference -composite -morphology dilate disk:10 -alpha copy -background red -alpha shape result2.png
Update 2: Here is how to overlay a 50% yellow marking onto you two originals. Change the value as desired. I create a difference image and dilate the white. Then I create a 50% yellow image. Then I composite each of the originals with the yellow using the difference image as a mask. See https://www.imagemagick.org/Usage/compose/#compose
convert JW0wZ.png 1nHWT.png \
\( -clone 0,1 -compose difference -composite -morphology dilate disk:10 \) \
\( -clone 0 -fill yellow -colorize 100 -channel a -evaluate set 50% +channel \) \
\( -clone 0,3,2 -compose over -composite +write 1.png \) \
\( -clone 1,3,2 -compose over -composite +write 2.png \) \
null:
To view this, if on Unix and have X11 installed, you can do
animate -delay 20 -resize 50% 1.png 2.png

Resources