How to append vertically 2 images with imagemagick? - imagemagick

I am trying to make vertical my multiple images as expected with following code.
convert 1.jpg 2.jpg -gravity North -append out.jpg
But I want 2.png as first file and 1.png as second. I know I can make it with convert 2.jpg 1.jpg -gravity North -append out.jpg command but actually I want to create them wiht convert 1.jpg 2.jpg -gravity North -append out.jpg command.
How can I do that?

The images are read into a list. Use -clone to copy an image at index to the end of the image list, and -delete to remove an image at index.
So to swap 1.jpg with 2.jpg the following would work.
convert 1.jpg 2.jpg -clone 0 -delete 0 -gravity North -append out.jpg
A visual breakdown...
# Image list
[ "1.jpg", "2.jpg" ]
# After -clone 0
[ "1.jpg", "2.jpg", "1.jpg" ]
# After -delete 0
[ "2.jpg", "1.jpg"]
EDIT
From a note in the Usage Layers article.
As only two images were involved we could have just used "+swap" or "-reverse" instead of [...].
So you can simplify the above with one of the two options.
convert 1.jpg 2.jpg +swap -gravity North -append out.jpg
convert 1.jpg 2.jpg -reverse -gravity North -append out.jpg

Related

Imagemagick: compose 2 images where 1 wraps the other

I want to make a wrapping image or gif that when composed with a different image will wrap it like the wrapping image.
For example combining these two images:
Would yield this image
I don't want an imagemagick command that does this specific movement of pixels because then it wouldn't be modular.
Here is one way in Imagemagick using the -roll function. But unfortunately it does not use percent. So I have to do a separate computation in IM 6 to convert percent to pixels. In IM 7 it could be done in one command apart from setting the pct overlap and split.
Here I cut the image into 3 sections (33% each, though different amounts could be used). And then roll the middle sections by 33% to the right with wrap around.
IM 6
pct=33
rollx=`convert palmtree.png -format "%[fx:round($pct*w/100)]" info:`
convert palmtree.png \( -clone 0 -gravity north -crop 100%x$pct%+0+0 +repage \) \( -clone 0 -gravity center -crop 100%x$pct%+0+0 +repage -roll +${rollx}+0 \) \( -clone 0 -gravity south -crop 100%x$pct%+0+0 +repage \) -delete 0 -append result.png
IM 7
pct=33
magick palmtree.png -set option:rollx "%[fx:round($pct*w/100)]" \( -clone 0 -gravity north -crop 100%x$pct%+0+0 +repage \) \( -clone 0 -gravity center -crop 100%x$pct%+0+0 +repage -roll +[rollx]+0 \) \( -clone 0 -gravity south -crop 100%x$pct%+0+0 +repage \) -delete 0 -append result.png
If you do not want 33% for all, then change the pct to whatever percent you want for each part and for the roll as desired. If you want to use multiple images, then replace each -clone with the actual image you want.

Multiple Commands with ImageMagick

I have the following files:
background.jpg
element1.jpg
element2.jpg
I would like to take element1.jpg, resize it to 300x300, place it on background.jpg, and then take element2.jpg, resize it to 400x400 and place it on the background. I would NOT like the background to be resized.
This is my current command. It appears that resize 400x400! is applied to all the previous images in memory (background.jpg and element1.jpg), instead of one specific image.
convert background.jpg -page +0+0 -resize 300x300! element1.jpg -page +0+0 -resize 400x400! element2.jpg -layers flatten output.jpg
Is there a way to accomplish this without creating a tmp folder to save "middle steps" and have it done all in one command? Or, is there a way to use "brackets" to specify which commands to run first?
You can use parentheses to ensure operators only apply to specific images, like this:
convert background.jpg \
\( element1.jpg -resize NNN \) -composite \
\( element2.jpg -resize MMM \) -composite result.jpg
So, if we create 3 test images, all the same size at 600x400 pixels:
convert -size 600x400 xc:red red.png
convert -size 600x400 xc:yellow yellow.png
convert -size 600x400 xc:blue blue.png
We can now individually resize and position them:
convert blue.png \
\( red.png -resize 80x50! \) -geometry +20+100 -composite \
\( yellow.png -resize 200x200! \) -geometry +200+150 -composite result.png

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

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

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