ign
ign

Reputation: 23

How can I automatically generate composite images by layering source images randomly?

I am working on a personal creative project and need help finding or creating a script that will randomly select 4 images from 4 different folders, stack them and create a series of png composite images as an output. Extra points if the images of each folder can be assigned to a fixed layer (so, for example, images from the "backgrounds" folder will always appear in the back). Note: I don't know how to code.

Upvotes: 2

Views: 4329

Answers (1)

Mark Setchell
Mark Setchell

Reputation: 207445

Updated

Ok, I have updated the script as follows:

  1. It produces 10 output files - you can change it by altering NFILES at the start
  2. The output files will not overwrite each other between runs, the next free name will be used starting with output-0.png then output-1.png and so on.
  3. I have corrected the alpha compositing to match your files.

Script follows...

#!/bin/bash

# Number of output files - edit freely :-)
NFILES=10

# Build arrays of filenames in each layer, assume directories are "Layer0", "Layer1" etc
IFS=$'\n' L0files=($(find "Layer 0" -name "*.png"))
IFS=$'\n' L1files=($(find "Layer 1" -name "*.png"))
IFS=$'\n' L2files=($(find "Layer 2" -name "*.png"))
IFS=$'\n' L3files=($(find "Layer 3" -name "*.png"))

# Produce NFILES output files
for i in `seq 1 $NFILES`; do

   # Choose random index into each array of filenames
   index0=$( jot -r 1  0 $((${#L0files[@]} - 1)) )
   index1=$( jot -r 1  0 $((${#L1files[@]} - 1)) )
   index2=$( jot -r 1  0 $((${#L2files[@]} - 1)) )
   index3=$( jot -r 1  0 $((${#L3files[@]} - 1)) )

   # Pick up files as specified by the random index
   f0=${L0files[index0]}
   f1=${L1files[index1]}
   f2=${L2files[index2]}
   f3=${L3files[index3]}

   # Generate output filename, "output-nnn.png" 
   # ... where nnn starts at 0 and goes up till no clash
   i=0
   while :; do
      out="output-$i.png"
      [ ! -f "$out" ] && break
      ((i++))
   done

   echo $f0, $f1, $f2, $f3 "=> $out"
   convert "$f0" "$f1" -composite "$f2" -composite "$f3" -composite "$out"
done

Starting with the following images in your Layer[0-3] directories:

Layer 0

enter image description here

Layer 1

enter image description here

Layer 2

enter image description here

Layer 3

enter image description here

Output files like the following are produced:

enter image description here

Original Answer

I would install ImageMagick to do this - it is free and easily installed on OSX if you install homebrew first by going here. Then type the following in Terminal.

brew install imagemagick

The script would then look like this:

#!/bin/bash
# Build arrays of filenames in each layer, assume directories are "Layer0", "Layer1" etc
IFS=$'\n' L0files=($(find "Layer0" -name "*.png"))
IFS=$'\n' L1files=($(find "Layer1" -name "*.png"))
IFS=$'\n' L2files=($(find "Layer2" -name "*.png"))
IFS=$'\n' L3files=($(find "Layer3" -name "*.png"))

# Choose random index into each array of filenames
index0=$( jot -r 1  0 $((${#L0files[@]} - 1)) )
index1=$( jot -r 1  0 $((${#L1files[@]} - 1)) )
index2=$( jot -r 1  0 $((${#L2files[@]} - 1)) )
index3=$( jot -r 1  0 $((${#L3files[@]} - 1)) )

# Pick up files as specified by the random index
f0=${L0files[index0]}
f1=${L1files[index1]}
f2=${L2files[index2]}
f3=${L3files[index3]}

echo Overlaying $f0, $f1, $f2, $f3 to produce "result.png"
convert "$f0" "$f1" "$f2" "$f3" -compose over -composite result.png

So, you would save the above as generate and then go to Terminal and do the following one time to make it executable

chmod +x generate

Then you can run it by double-clicking on its icon in Finder, or typing:

./generate

in Terminal. It will then produce a random overlay of 4 images, one from each folder and save the result as result.png.

You will need to edit the first 4 lines according to where your images are for the various layers - basically I am assuming the images are in directories called Layer0-4, but yours may be in /Users/FreddyFrog/pictures/backgrounds or somesuch, in which case you would edit

    IFS=$'\n' L0files=($(find "/Users/FreddyFrog/pictures/backgrounds" -name "*.png"))

When I run it a few times on my Mac, I get:

Overlaying Layer0/l0-5.png, Layer1/l1-0.png, Layer2/l2-3.png, Layer3/l3-3.png to produce result.png
Overlaying Layer0/l0-3.png, Layer1/l1-4.png, Layer2/l2-3.png, Layer3/l3-3.png to produce result.png

Upvotes: 4

Related Questions