Page 1 of 1

Crop portrait/landscape to square without resizing or knowing the width/height

Posted: 2015-08-30T17:30:23-07:00
by weavermedia
I have portrait and landscape images of varying dimensions.

I'd like to crop them all to square, from the center, based on the shortest out of width and height.

In math terms I think of it like this: (Math.min(width, height)) x (Math.min(width,height))

For example:
500x1000 > crops to 500x500
1000x500 > crops to 500x500
500x500 > either goes unprocessed, or is cropped to 500x500

I've done a ton of reading and searching but I can't figure out how to reference the image width and height in a single-line command (Mac terminal).

I tried referencing %w and %h in -crop but can't get it to compare. I thought a ternary like this might work, but no luck:

Code: Select all

mogrify -gravity Center -crop "((%w>%h)?%h:%w)"x"((%w>%h)?%h:%w)"+0+0 +repage *.jpg
How do I do this in a single line?

Re: Crop portrait/landscape to square without resizing or knowing the width/height

Posted: 2015-08-30T17:58:19-07:00
by snibgo
Sadly, "-crop" can't take expressions. You can use one "identify" command to find the minimum of (width, height), then crop to that dimension in each direction. Bash syntax:

Code: Select all

#!/bin/bash

DD=`identify -format "%[fx:min(w,h)]" rose:`

convert rose: -gravity center -crop ${DD}x${DD}+0+0 +repage out.png

Re: Crop portrait/landscape to square without resizing or knowing the width/height

Posted: 2015-08-31T16:50:06-07:00
by weavermedia
Thanks again snibgo!

Is it possible to nest -identify inside a mogrify command so I can process a whole folder with a one-liner?

Or will I have to loop through all files with this bash script. No problem to do that, I just like one-liners :D

Re: Crop portrait/landscape to square without resizing or knowing the width/height

Posted: 2015-08-31T17:36:56-07:00
by snibgo
Sorry, I don't know mogrify. You'll have to RTFM.

Nesting commands is a feature of bash, not IM. It's a shortcut that avoids variables. My commands above can be written as:

Code: Select all

convert rose: -gravity center -crop `identify -format "%[fx:min(w,h)]x%[fx:min(w,h)]+0+0" rose:` +repage out.png
I have to mention the filename (the built-in "rose:") twice: one for identify, and once for convert. Nesting identify within mogrify wouldn't help because identify would be run once, and the same result used for all files that mogrify processes.

Re: Crop portrait/landscape to square without resizing or knowing the width/height

Posted: 2015-08-31T18:21:16-07:00
by fmw42
You can do it with viewport cropping and -distort SRT. See http://www.imagemagick.org/Usage/distor ... t_viewport.

Assume you have your images in test1 on the desktop. Create a new empty directory test2 also on the desktop, so that the output from mogrify does not overwrite you input images in test1

Code: Select all

cd desktop/test1
mogrify -path ../test2 -format jpg -set option:distort:viewport \
"%[fx:w>h?h:w]x%[fx:w>h?h:w]+%[fx:w>h?(w-h)/2:0]+%[fx:w>h?0:(h-w)/2]" \
-filter point -distort SRT 0 +repage *

With IM 7, you can do the same computations in -crop.