Off the top of my head, mathematically you should be dealing with coordinates that are starting at the top left 0,0
(aka: NorthWest
in ImageMagick terminology) so you would want to position the crop box area to be something like this:
(width of image - width of crop area) / 2
So you could then conceptually do something like this with your example mogrify
command:
mogrify -crop 250x250+[(width of image - 250)/2]+0 -gravity NorthWest cat.jpg
Which is fairly a nice concept, but is not a useful reality. But I just experimented a bit and got this to work for a single test image:
CROP_W=250
CROP_H=250
IMG_W=$(identify -format %w test.jpg)
X_OFFSET=$((($IMG_W-$CROP_W)/2))
mogrify -crop ${CROP_W}x${CROP_H}+${X_OFFSET}+0 -gravity NorthWest test.jpg
Since ImageMagick’s -gravity
default is NorthWest
anyway, you can simplify it by removing the -gravity
option altogether like this:
CROP_W=250
CROP_H=250
IMG_W=$(identify -format %w test.jpg)
X_OFFSET=$((($IMG_W-$CROP_W)/2))
mogrify -crop ${CROP_W}x${CROP_H}+${X_OFFSET}+0 test.jpg
And after testing that concept out, I whipped up this Bash script and it works as expected. Just change the DIRECTORY
value to match the actual directory you plan on acting on. And that echo mogrify
allows you to see exactly what would be happening if the command were run; remove that echo
and then let the script go at it if you are happy with the results:
#!/bin/bash
# Set the crop width and height.
CROP_W=250
CROP_H=250
# Set the directory to act on.
DIRECTORY='/path/to/images'
# Use find to find all of the images; in this case JPEG images.
find ${DIRECTORY} -type f \( -name "*.jpg" -o -name "*.JPG" \) |\
while read FULL_IMAGE_PATH
do
# Get the image width with identify.
IMG_W=$(identify -format %w ${FULL_IMAGE_PATH})
# Calculate the X offset for the crop.
X_OFFSET=$((($IMG_W-$CROP_W)/2))
# Run the actual mogrify command.
# mogrify -crop ${CROP_W}x${CROP_H}+${X_OFFSET}+0 ${FULL_IMAGE_PATH}
echo mogrify -crop ${CROP_W}x${CROP_H}+${X_OFFSET}+0 ${FULL_IMAGE_PATH}
done
You need to update ImageMagick to version 6.9.1-3 or above, and then all of the commands from your question will create reproducible images.
I found the following in the changelog:
2015-04-20 6.9.1-3 Cristy <quetzlzacatenango@image...>
* Support -define compose:clamp=false option (reference
https://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=26946).
* Don't extend any user supplied image buffer in SeekBlob() (bug report
from a.chernij@corp...).
* Improved reproducible builds (reference
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=783933).
* Draw a rectangle of width & height of 1 (reference
https://www.imagemagick.org/discourse-server/viewtopic.php?f=3&t=24874).
I found the changelog entry after discovering that ImageMagick on ArchLinux works fine, contrary to ImageMagick on Ubuntu 16.04.
ArchLinux (good, reproducible images):
$ convert --version
Version: ImageMagick 6.9.8-8 Q16 x86_64 2017-05-30 http://www.imagemagick.org
Ubuntu 16.04 (bad, different images every time):
$ convert --version
Version: ImageMagick 6.8.9-9 Q16 x86_64 2017-05-26 http://www.imagemagick.org
Best Answer
Use the ImageMagick "montage" command, specifically the "-tile" option. See http://www.imagemagick.org/Usage/montage/ for details.