How do I make the images equidistant using imagemagick/montage? - imagemagick

Currently I'm using this command:
montage IMG*.JPG -tile 3x1 -geometry 150x100+40+40 -background '#000000' triptych.jpg
And it produces an output like this (red lines added):
The problem (as indicated) is that my images have too much space between them, and that makes me sad.
I'm looking to create something that looks more like this, with the border equal all the way around:
I checked the manpage and several online guides, but none of the options that I tried (-mode concatenate, changing the geometry to +40+20) did what I wanted.
How do I get the output that I want using imagemagick?

If you are just making a triptych, you may get on better with convert +append to lay out images in a row with spacers. So, if your images are 1.png, 2.png and 3.png:
convert -background black \
1.png xc:black[10x] 2.png xc:black[10x] 3.png +append \
-bordercolor black -border 10 result.png
The xc:black[10] are just the two spacers that you can set the width of explicitly. Then the three images with spacers are set in a horizontal row, using +append. Finally, at the end, I put a border around the whole lot with -border.
Or, showing how you have full control over all aspects:
convert -background black \
1.png xc:black[15x] 2.png xc:black[5x] 3.png +append \
-bordercolor black -border 40 result.png
As Wayne says in the comments, you can resize all the images to a uniform size too, while they are still separate before the -append, so you can do this to make sure no image is wider than 400 pixels.
convert -background black \
1.png xc:black[10x] 2.png xc:black[10x] 3.png -resize 400x\> +append \
-bordercolor black -border 10 result.png
If you want even more control, you can individually resize the images like this:
convert -background black \
\( 1.png -resize WxH \) xc:black[10x] \
\( 2.png -resize AxB \) xc:black[10x] \
\( 3.png -resize MxN \) +append \
-bordercolor black -border 10 result.png
If you want a vertical triptych, use -append in place of +append and set the spacer height with xc:black[x10] rather than xc:black[10x].
convert -background black \
1.png xc:black[x10] 2.png xc:black[x10] 3.png -append \
-bordercolor black -border 10 result.png
Keywords: triptych, diptych, montage, photographer, photography, photo, spacing, spacer, padding

Another method is doing it in two steps.
montage img-*.png -background '#000' -geometry +20+20 step-1.png # step 1
convert step-1.png -bordercolor '#000' -border 20 step-2.png # step 2
With step 1, you got the green spacing. And with step 2, you got the red spacing

Related

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

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

Montage 3 images in a 2x2 grid, first in top center (like "triforce")?

Not sure how to put this question otherwise - but let's assume I have three square images. I'd like to arrange them in a sort of a square 2x2 grid, such that image 2 is bottom left, image 3 is bottom right - and image 1 is top center (so image 1 is not in the cells of the grid on top; neither left cell, nor right cell, but in center of the row delimited by them).
Closest I could get was with this test, done on Ubuntu 14.04, montage --version ImageMagick 6.7.7-10 2017-07-31 Q16:
montage \
<(convert -size 100x100 xc:green bmp:-) \
<(montage \
<(convert -size 100x100 xc:blue bmp:-) \
<(convert -size 100x100 xc:red bmp:-) \
-geometry +5+5 bmp:- \
) \
-geometry +5+5 -tile 1x2 bmp3:- | display
... or as one-liner:
montage <(convert -size 100x100 xc:green bmp:-) <(montage <(convert -size 100x100 xc:blue bmp:-) <(convert -size 100x100 xc:red bmp:-) -geometry +5+5 bmp:- ) -geometry +5+5 -tile 1x2 bmp3:- | display
The image produced is:
What I want instead is something like this (I edited this manually in an image editor):
... that is, somewhat like that old meme Triforce (Wikipedia)
How could I achieve that with ImageMagick's montage?
This might be a case where ImageMagick's "convert" command would serve you better than "montage". Here is an example that should get you pretty much the same result...
convert -size 100x100 xc:green xc:blue xc:red -bordercolor white -border 5 \
\( -clone 1,2 +append \) -delete 1,2 -gravity center -append -border 5 out.bmp
Using "convert" can give you more freedom to arrange the images using "+append" and "-append" to attach them, "-gravity" for alignment, and "-border" for spacing.

Combine and resize multiple images in a square using ImageMagick

So I want to create one large image of size 3600x2280 composed of three smaller images. The first should be resized to 1680x1050 and placed in the top left corner. The 2nd needs to be reiszed to 1920x1200 and placed immediately to the right of it (+1680 over). The 3rd image should be resized to 1920x1080 and placed on the bottom right (+1680+1200). The bottom left will just be blank/transparent.
I've tried various commands I've searched for online and think I'm getting somewhat close with something like the following for just two of the three images:
convert -define png:size=3600x2280 \( Photos/DSC05525-original.jpg -resize 1680x1050 \) -geometry +0+0 -composite \( Photos/Sydney-Loftus-Train-Station-original.jpg -resize 1920x1200 \) -geometry +1680+0 -extent 3600x2280 test.png
...but that places the 2nd image over the first (I think because it doesn't know to extend until the very end?). I've tried various combinations of -composite, -gravity and +repage, but can't seem to find a solution.
There are lots of ways of doing this. Choose the one that corresponds best to the way your mind works! I used test images like this:
1.jpg => red
2.jpg => green (lime actually)
3.jpg => blue
Method 1
convert -background none \
1.jpg -resize 1680x1050! \
\( 2.jpg -resize 1920x1200! \) +append \
\( 3.jpg -resize 1920x1080! -gravity east \) -append \
result.png
That says... "Leave all unpainted areas transparent. Resize image 1. Resize image 2 and place it to the right of image 1 (+append). Resize image 3 and align it East. Append that underneath images 1 and 2 (-append)."
Method 2
convert -background none \
\( 2.jpg -resize 1920x1200! \) \
\( 3.jpg -resize 1920x1080! \) -append \
\( 1.jpg -resize 1680x1050! \) +swap +append result.png
That says... "Load and resize image 2. Load and resize image 3. Place image 3 underneath image 2 (-append). Load and resize image 1. Place image 1 before (+swap) image 2 in the image list. Now append the second image in the list to the right of the first (+append)."
Method 3
convert -background none \
1.jpg -resize 1680x1050! -extent 3600x2280 \
\( 2.jpg -resize 1920x1200! -geometry +1680 \) -composite \
\( 3.jpg -resize 1920x1080! -geometry +1680+1200 \) -composite result.png
That says... "Leave any unpainted areas transparent. Load image 1 resize it then extend the canvas to the full output size to accommodate subsequent images. Load image 2, resize, position and splat onto canvas. Load image 3, resize and splat onto canvas."
Method 4
Just for fun, here's a totally different way of thinking about it:
{ convert 1.jpg -resize 1680x1050! miff:- ; \
convert 2.jpg -resize 1920x1200! miff:- ; \
convert -size 1680x1 xc:none miff:- ; \
convert 3.jpg -resize 1920x1080! miff:- ; } |
montage -background none -geometry +0+0 -tile 2x2 miff:- result.png
That says... "Start a compound statement that will load and resize 4 images and send each of them as a MIFF (Magick Image File Format) to a montage command that will put them all together in 2x2 grid (-tile 2x2) with no spaces between them (-geometry +0+0)."

ImageMagick : make images of different sizes float to top

I have 7 images that I'm trying to concatenate in a 4x2 tiling. They are all the same width, and have roughly the same height, except one that is about twice higher than the others (4th image). I'm trying to make them tile so that the 4th image covers the space of 2 images in the tiling, but what I get is this :
How can I get rid of the whitespace, and make all the images "float" to the top? I don't mind if the bottom images aren't aligned.
Personally, I would favour convert over montage for this. All you need to know is that -append appends the second picture below the first and that +append appends the second picture to the right of the first.
So, I effectively put 5 below 1 to make a single taller picture, 6 below 2 to make another single taller picture and then 6 & 2 to the right of 1 & 5 etc and then finally stuff 4 at the end on the right:
convert -background none \
\( 1.png 5.png -append \) \
\( 2.png 6.png -append \) +append \
\( 3.png 7.png -append \) +append \
4.png +append result.png
If you want spacers between your images you can add them in like this:
convert -background none \( 1.png 5.png -append \) xc:none[10x10] +append \( 2.png 6.png -append \) xc:none[10x10] +append \( 3.png 7.png -append \) xc:none[10x10] +append 4.png +append result.png

Resources