First, get the dimensions of the base and watermark images:
basew=`identify -format '%w' "$infile"`
baseh=`identify -format '%h' "$infile"`
wmw=`identify -format '%w' "$wmfile"`
wmh=`identify -format '%h' "$wmfile"`
Then, calculate how many complete tiles we can fit over the base image:
tilew=$(($basew / $wmw * $wmw))
tileh=$(($baseh / $wmh * $wmh))
This uses integer arithmetic, so the multiply operation doesn't counteract the divide. Let's take an example. If the base image is 100x100 and the tile image 34x34, this will yield 68x68, since you can't quite fit a third tile in on either axis.
Note that we're using a Bash feature here to do arithmetic within the shell script proper. If you have to do this in another shell, you can call out to
dc to do the calculation externally.
Now that we know how large we can make it, create a tiled temporary version of the watermark image, centered within a frame equal to the size of the base image:
convert -background 'rgba(0,0,0,0)' -size "$tilew"x"$tileh" \
tile:"$wmfile" -gravity center -extent "$basew"x"$baseh" \
Notice that this forces the watermark image to RGBA format if it wasn't already. Also, it's important that the
-background 'rgba(0,0,0,0)' directive be before the input image, so it doesn't do the tiling operation over the default white background.
The real trick here, though, is that we're using different values for the
-extent directives. We're building up a potentially smaller tiled image, then padding it out if needed to match the size of the base image. If the tile image size divides evenly into the base image size, that's fine, it simply won't have to add any extra padding to center the tile set.
Finally, lay the temporary tiled watermark over the original image:
composite "$wmtemp" "$infile" "$outfile"