ImageMagick: Remove 2 pixels wide lines - imagemagick

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

Related

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 "^".

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

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

"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

How to blend + translate simultaneously with Imagemagick (or some other scriptable software like Photoshop)?

How can I blend AND translate at the same time ?
Something like this : http://www.imagemagick.org/Usage/layers/#flatten but in such a way that the images are transparent.
I was trying :
composite -blend 90 -page +0+0 input01.jpg -page +500+0 input02.jpg -resize x400 outputSimpleMosaicBlend01.
but this did not work.
So if I have two input images:
Then how can I get an image that looks like the composite image below ?
Any suggestions how to do this programatically (not manually) with ImageMagick ? Or some other tools ?
I would like to create several thousands of composite images like that (for an animation) and I would like to automate the process.
The problem is that I can find examples that overlay images and that translate images but I cannot find examples that do these two operations simultaneously.
This is the main goal of this question, to give such code/script examples, how to do that with image manipulation tools like ImageMagick programmatically.
EDIT:
Things that I tried and did not work:
convert a.jpg -geometry +100+0 b.jpg -compose blend -composite result.jpg
gives:
I tried
convert -background none a.jpg -geometry +100+0 b.jpg -compose blend -composite result.jpg
too which gives the same result.
I got this :
with this
convert -background none input01.jpg input02.jpg -geometry +1200+0 -compose blend -define compose:args=50 -composite result.jpg
command.
It's getting close ! Thanks Mark!
A slightly different way of doing this is to set the width of the output image using -extent and then to overlay the right hand image using -gravity East to align it to the right edge - seems a fraction more intuitive to me - but go with whatever works for you!
convert a.jpg -background white -extent 2800x \
\( b.jpg -resize 150% -alpha on -channel A -evaluate set 50% +channel \) \
-gravity east -composite result.jpg
Thanks to Snigbo, the following command :
convert input02.jpg \( input01.jpg -resize 150% -alpha Opaque -channel A -evaluate Multiply 0.5 +channel -set page +1200+30 \) -background White -layers merge a.jpg
produces:

Image magick to put images in row and then generate reflection

I was wondering if I can use imagemagick to produce a result image like this
My initial image will be like this
I am able to create the dark image to be put in the background like this -
convert -brightness-contrast -20x10 GARDENS-ILLUSTRATED_JAN-14.jpg out_lighter2.jpg
But I do not know how to put them in line like that and then generate a reflection.
I have got something close, but have no more time, so maybe you can fiddle with it and get it to what you want:
#!/bin/bash
input=input.png
# Calculate width and height
w=$(convert $input -ping -format "%w" info:)
h=$(convert $input -ping -format "%h" info:)
# Calculate how much to chop off bottom and height of reflection
chop=$(echo $h*60/100|bc)
refl=$(echo $h*20/100|bc)
convert $input -alpha on \
\( +clone -flip -size ${w}x${refl} gradient:gray40-black -alpha off -compose CopyOpacity -composite \) \
-append -background white -compose Over -flatten -gravity South -chop 0x${chop} output1.png
# Darken and reduce for second layer
convert output1.png -brightness-contrast -25x8 -resize 90% output2.png
# Darken and reduce for third layer
convert output2.png -brightness-contrast -25x8 -resize 90% output3.png
# Make big new output canvas
neww=$(echo $w*1.6|bc)
newh=$(echo $h*1.6|bc)
# Splat images onto it with offsets
convert -size ${neww}x${newh} xc:transparent -page +0+80 output3.png \
-page +40+40 output2.png \
-page +80+0 output1.png -flatten output.png
My basic idea is to generate the bright, frontmost image first in output1.png, then darken and reduce it into output2.png and again into output3.png. Then composite them all together into output.png with a little offset.

Resources