Question

I have 200 jpgs that are the same size. I need to combine them in pairs, putting them side-by-side.

So

1.jpg
2.jpg
3.jpg
4.jpg

Should make 2 new jpgs, one containing 1 and 2, and the other containing 3 and 4. Side by side.

Think of each image as a page of a book.

Is there anyway to automate this using imageMagick montage?

Was it helpful?

Solution

I ended up using ImageMagick NuGet package in a .NET console application and did the following:

using (MagickImageCollection images = new MagickImageCollection())
            {                   
                for (var i = 2; i <= 210; i=i+2)
                {
                    var first =
                        new MagickImage(string.Format("PATH-TO-IMAGE-FOLDER_{0}.jpg", i.ToString().PadLeft(3, '0')));

                    var second =
                        new MagickImage(string.Format("PATH-TO-IMAGE-FOLDER_{0}.jpg", (i+1).ToString().PadLeft(3, '0')));

                    images.Add(first);
                    images.Add(second);


                    using (MagickImage result = images.SmushHorizontal(0))
                    {
                        result.Write(string.Format("{0}.png", i));
                    }

                    images.Clear();
                }  
            }

OTHER TIPS

You can quickly automate this by creating a script.

#!/bin/bash

for index in $(seq 1 2 200)
do
  left="$index.jpg"
  right="$((index + 1)).jpg"
  montage $left $right "page-$index.jpg"
done

The seq utility will generate a list of numbers skipping every-other from 1 to 200 (i.e. 1,3,5,7...199).

In ImageMagick montage, if you rename your images with leading zeroes so that they are alphabetically ordered and put them into one directory and cd to that directory, then you can do

montage *.jpg -tile 2x -background white -geometry +2+2 result.jpg

The -tile 2x will put them in pairs together sequentially horizontally 1_2, 3_4, etc with a 2 pixel gap of background color. You can adjust the spacing as desired. You can add labels if you want using -label "%f" for the file names. See http://www.imagemagick.org/Usage/montage/

This is a bit of a workaround but after hours of research I've determined this to be the best way to go.


You'll want to Create a backup working folder only containing the pictures that you want to merge. This technique will remove all previous filenames.
Then rename all of your files in the following way [1]:

Open file explorer and navigate into the folder with all your photos
Select all photos (using 'ctrl+a')
Find the very FIRST photo in the series and right click on it then click rename
Name it something like: Myphoto (101) or Myphoto (1001)
The 'space + (101)' or 'space + (1001)' is very important
Hit the enter key and watch as your files are all renamed automatically

Your photos should now be named in ascending order
Eg: [ Myphoto (1001), Myphoto (1002), Myphoto (1003), etc.]

You must do the above step because Imagemagick processes filenames differently from how windows file explorer presents them

>Windows sorts names like so: 1, 2, 3, 4, 5, 6, 7, 8 ,9, 10, 11 etc

>where Imagemagick sorts like: 1, 11, 2, 22, 3, 33, 4, 44 etc

After renaming and navigating to the (backup) folder with all your photos then you can run this command and imagemagick will work its magic!
magick montage -tile 2x1 -geometry +5+5 -border 5 *.png out@_%d.png

The border and geometry tags can be removed if you do not want any white space,
The 2x1 can be changed to whatever dimensions suit your needs! (Rows x Columns)

Here are some additional configurations you can use instead of 2x1!

One by two montage - (1x2)
One by three montage - (1x3)
Two by one montage - (2x1)
Two by two montage - (2x2)
Two by three montage - (2x3)
Three by one montage - (3x1)
Three by two montage - (3x2)
Three by three montage - (3x3)



Big thanks to [@fmw42] in this thread for pointing me in the right direction!

https://answers.microsoft.com/en-us/windows/forum/windows_xp-files/renaming-multiple-files-starting-with-001-not-1/26520ab1-823f-45b4-9661-65f17c25d4b9 [1]

I had this problem and my solution was to use the Bash script posted in emcconville's answer - but with enough tweaks that I've felt compelled to post my own script here, though my answer probably isn't ideal since I'm not skilled with Bash. Anyway, suppose your images are called "Magazine Issue 224 0001.jpg" through "Magazine Issue 224 0102.jpg". Then your script could be:

#!/bin/bash                                                                     

for index in $(seq -w 2 1 101)
do
    I=$(echo "$index" | bc)
    if [[ $((I%2)) -eq 0 ]]
    then
        IL=$index
    else
        IR=$index
#       echo "$IL-$IR"                                                          
        left="Magazine Issue 224 0$IL.jpg"
        right="Magazine Issue 224 0$IR.jpg"
        montage -mode concatenate "$left" "$right" "Magazine Issue 224 $IL-$IR.jpg"
    fi
done

The -w adds leading zeroes so that indices will all have the same width. The if-else stuff allows the indices to be arranged into pairs without loss of the leading zeroes. (I expect there was a better way to do this, but whatever.) The echoing into bc strips the leading zeroes just for the if-test, so that Bash won't interpret them as a sign of octal notation.

Note that the sequence begins at 2; this is because my images start with a magazine cover page that shouldn't be paired with anything. Obviously that could just as easily be 1. Note that the iteration ends with 101 for a similar reason: The final image pair is 100-101, with 102 being a back cover image that again should not be paired.

Of course it'd be nice to automate detection of the "Magazine Issue 224 0" string or some such, but I haven't bothered to go that far since I don't have the Bash skill to do it fast and my project doesn't require me to do it often (so I'll just edit that part of the script manually like a chump).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top