Image selection by aspect ratio and pixel count

"There are always two people in every picture: the photographer and the viewer."    — Ansel Adams.
On this page:

Aspect ratio

Here's a simple shell script that will display the aspect ratio of an image file, 100 being a square image. It can also be used to select and copy images that are within a certain range.

History:
v1.0 — 2010/11/24 — Original release
v1.1 — 2010/11/25 — Rewritten to use getopts


Pixel count

Here's a second similar shell script that will display the number of pixels of an image file. It can also be used to select and copy images that are within a certain range, and to make size conversions based on final number of pixels while maintaining aspect ratio.

History:
v1.0 — 2010/11/24 — Original release
v1.1 — 2010/11/25 — Rewritten to use getopts
v1.1 — 2019/07/03 — Published the source code on gitlab (find the MPix source code there).

Instructions:

$ MPix.sh -h
USAGE: MPix.sh [Options] File [Files...]
  Gives the pixel count of an image (10 for 10 million pixels).
OPTIONS:
  -n    Display filenames but not the pixel count (used for selecting images in a range of pixels)
  -x    Display pixel count but not the filenames
  -r    Display 'MPix Filename' instead of 'Filename MPix', allowing you to pipe to 'sort -n'
  -m    Pixel count is in megapixels (default)
  -k    Pixel count is in kilopixels
  -p    Pixel count is in pixels
  -g N  Only display/copy if the pixel count is greater than the value given (inclusive)
  -l N  Only display/copy if the pixel count is lower than the value given (inclusive)
  -c Dir        Copy images that are within requested -g/-l values to a specific directory
  -t Nb When used in addition to -c, will downsize the image to a given [mega][kilo]pixel count (or simply copied if too small)
EXAMPLES:
  MPix.sh -prg $((1024*768)) *.jpg | sort -n   to sort images bigger than 1024x768 pixels by number of pixels
  MPix.sh -c /tmp/tv -t 2 -g 10 -l 12 *.png   to copy and convert images in the 10~12 MPix range to 2 MPix in /tmp/tv


Getopts mini-tutorial

The bash shell built-in getopts is used to read command line parameters passed to a script. It can read single letter parameters, single letter parameters with a single argument, possibly repeated single letter parameters, possibly joined, but not long parameters. For instance, it can read: script -h -vv -f "my file" arg1 arg2, in that case the parameters are h, f and v (twice). But it can't read -long --long -f File1 File2... Here's how you can use it, with a simplified example:

#! /bin/bash
function usage {
cat << EOF
  USAGE: $0 [-v] [-h] [-f File] [args...]
EOF
}

while getopts vf:h opt; do
# 'opt' is the variable that will contain each letter in turn.
# 'vf:h' describes the list of single letter parameters, 
# with a : if there's an optional argument (which ends up in $OPTARG)

  case $opt in
	v) echo "parameter -v";;	 # the order of vgh doesn't matter
	f) echo "parameter -f with argument $OPTARG";;        # Here we make use of the argument passed along -f
	h) usage; exit 1;;
	?) echo "Invalid option: -$OPTARG" >&2; exit 1;;
  esac
done

shift $(($OPTIND - 1)) # This is necessary so that now the remaining arguments end up as $1, $2...

if [ $# -eq 0 ]; then usage; exit 1; fi		# No other arguments, may or may not be a good thing

while [ "$1" != "" ]; do
        echo "Argument: $1" # Now list all the remaining arguments
        shift           	# Next argument
done

There are a few other options. For more info you can try help getopts since man doesn't usually work for builtins. And here's the result:

$ ./tmp -v
parameter -v
  USAGE: ./tmp [-v] [-h] [-f File] [args...]
$ ./tmp -vv -fFile1 -v -f "Big File" Arg1 Arg2 Arg3
parameter -v
parameter -v
parameter -f with argument File1
parameter -v
parameter -f with argument Big File
Argument: Arg1
Argument: Arg2
Argument: Arg3