skip to Main Content

I’m currently using Photoshop to resize, rotate randomly, and wrap images randomly to create this type of montage….

Comic Covers

I got to thinking that kind of thing should be doable in Imagemagick. I know how to use all of the commands separately, and I can do random rotations and wraps using BASH, but getting a single image out of individual images is eluding me.

Assume that the source pictures are different sizes but should be resized to 250px wide. The images will be named image1.jpg, image2.jpg, etc. Also assume that the destination should be 1000x1000px. Depending on how many pictures I have, the whole 1000×1000 image may not be covered – I understand this. I mainly use BASH, but I have several different environments and shells available to me.

3

Answers


  1. Chosen as BEST ANSWER

    Cool, I'll try fmw42's script, but this is a script I came up with. It generates temporary files (which it deletes) and several convert commands, but it does work....

    # Create blank montage...
    convert -size 750x750 xc:black montage.jpg
    
    
    for file in $(ls hall*.jpg | grep -v halloweencovers.jpg); do
        echo $file
    
        angle=$RANDOM; let "angle %= 32"; let "angle = angle - 16"; let "angle = angle * 5"
        offsetx=$RANDOM; let "offsetx %= 75";let "offsetx = offsetx * 10"; offsetx="+$offsetx"
        offsety=$RANDOM; let "offsety %= 75";let "offsety = offsety * 10"; offsety="+$offsety"
    
        # Create blank image...
        convert -size 750x750 xc:transparent blank.png
    
        # create 250px image and rotate....
        convert $file -resize 250x -alpha set -background none -rotate $angle out.png
    
        # add 250px image to blank 750x750 canvas
        convert blank.png out.png -composite output.png
    
        # offset and wrap blank canvas with output image
        convert output.png -roll ${offsetx}${offsety} output2.png
    
        # merge montage with offset image
        convert montage.jpg output2.png -composite montage.jpg
    
        # clean up
        rm -f out.png output.png output2.png blank.png
    done
    

  2. Here is a bash Imagemagick 6 script that takes a list of images. You can replace it with your images. It uses subshell processing to avoid needing to write temporary images to disk. It saves the images in a miff: format as one file from the loop. Then it pipes the multipage miff: file to -layers merge, which overlays the images onto the 1000×1000 transparent base image. For Imagemagick 7, replace convert with magick.

    list="lena.jpg barn.jpg mandril3.jpg zelda1.jpg"
    convert -size 1000x1000 xc:none result.png
    (
    for img in $list; do
    angle=`convert xc: -format "%[fx:round(-22.5+45*(rand()))]" info:`
    xoff=`convert xc: -format "%[fx:round(1000*rand())]" info:`
    yoff=`convert xc: -format "%[fx:round(1000*rand())]" info:`
    #echo >&2 "angle=$angle; xoff=$xoff; yoff=$yoff"
    convert "$img" -resize 250x -background none -rotate $angle -set page +${xoff}+${yoff} miff:-
    done
    ) | convert result.png - -layers merge +repage result.png
    

    enter image description here

    If you have enough resources to hold all the images at once, then you can also do it in one command line as follows:

    convert -size 1000x1000 xc:none 
    ( lena.jpg barn.jpg mandril3.jpg zelda1.jpg -virtual-pixel none -background none 
    +distort SRT "0,0 %[fx:250/w] %[fx:-22.5+45*rand()] %[fx:rand()*1000],%[fx:rand()*1000]" ) 
    -layers merge +repage result.png
    

    Login or Signup to reply.
  3. Using ImageMagick 6 or 7, if you have enough memory to read in all your images at once you can resize them, randomly rotate them, and place them all in random locations on a 1000×1000 canvas with a command like this…

    convert granite: -duplicate 11 -resize 250x 
       -background none -gravity center -extent 1000x1000 
       -distort SRT "%[fx:rand()*45-22.5]" -virtual-pixel tile 
       -distort affine "%[fx:w/2],%[fx:h/2] %[fx:rand()*w],%[fx:rand()*h]" 
       -flatten result.png
    

    That uses the ImageMagick built-in image “granite:” duplicated 11 more times. Replace “granite: -duplicate 11” with a list of your input files.

    It starts by resizing them all to 250 pixels wide, then placing them each in the center of a 1000×1000 transparent canvas.

    The real work is done in the distort operations. First “-distort SRT” rotates each image a random amount between -22.5 and +22.5 degrees. Then the “-distort affine” relocates each image to a random location within the canvas. Any part of an image going beyond the canvas will be rolled back into the opposite side. That makes the result suitable for tiling.

    This command flattens everything onto a transparent background wherever it might show between the images. Add “-background blue” just before the “-flatten” operation to change the background to blue, for example.

    This works on my IM 6 in bash. For IM 6 in Windows change the continued line backslashes “” to carets “^”. For IM version 7 change “convert” to “magick”.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search