Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- #
- # Developed by Fred Weinhaus revised 6/9/2012 .......... revised 4/25/2015
- #
- # ------------------------------------------------------------------------------
- #
- # Licensing:
- #
- # Copyright © Fred Weinhaus
- #
- # My scripts are available free of charge for non-commercial use, ONLY.
- #
- # For use of my scripts in commercial (for-profit) environments or
- # non-free applications, please contact me (Fred Weinhaus) for
- # licensing arrangements. My email address is fmw at alink dot net.
- #
- # If you: 1) redistribute, 2) incorporate any of these scripts into other
- # free applications or 3) reprogram them in another scripting language,
- # then you must contact me for permission, especially if the result might
- # be used in a commercial or for-profit environment.
- #
- # My scripts are also subject, in a subordinate manner, to the ImageMagick
- # license, which can be found at: http://www.imagemagick.org/script/license.php
- #
- # ------------------------------------------------------------------------------
- #
- ####
- #
- # USAGE: overlapcrop [-s size] [-o overlap] [-m mode] [-u]
- # [-i initnum] [-z zeropad] [-d delay] [-l loop] [-c canvas]
- # [-M] [-L] [-F frame] [-S spacing] [-R] infile outfile
- # USAGE: overlapcrop [-h or -help]
- #
- # OPTIONS:
- #
- # -s size crop subsection dimensions in pixels; one or two
- # integers>0 with "x" separator; default=128x128
- # -o overlap overlap of subsections; pixels or percent
- # as one or two integers with "x" separator;
- # if percent sign included, then it will be converted to
- # pixels in range 0<=integer<subsection size;
- # default="50%x50%"
- # -m mode mode of output; choices are matrix (numbered),
- # sequential (numbered), frames or animation;
- # default=matrix
- # -u (uniform) flag to keep only same size crop sections and discard
- # smaller pieces on the right and bottom; default is to
- # keep all crop pieces
- # -i initnum initial number for output naming; integer>=0; default=1
- # -z zeropad number of digits with zero padding for sequential mode;
- # integer>=0; default=0 (no zero padding)
- # -d delay delay for animation mode; integer>=0; default=50
- # -l loop number of loops for animation mode; integer>=0;
- # default=0 (endless looping)
- # -c (canvas) leave the virtual canvas in the meta data for the images;
- # default is to remove the virtual canvas
- # -M (montage) create single montage image; applicable only to matrix
- # or sequential mode; default is no montage
- # -L (label) flag to add filename labels to each image in the montage;
- # default is no filename labels
- # -F frame frame size around each image in the montage; integers>=0;
- # default=5
- # -S spacing spacing between images in the montage; integers>=0;
- # default=0
- # -R (remove) flag to remove/delete all individual images generated
- # prior to creating the montage. Default is leave
- # all individual images.
- #
- ###
- #
- # NAME: OVERLAPCROP
- #
- # PURPOSE: To create a sequence of cropped subsections permitting optional
- # overlap of the subsections.
- #
- # DESCRIPTION: OVERLAPCROP creates a sequence of cropped subsections permitting
- # optional overlap of the subsections. The output images may be numbered either
- # sequentially or in matrix mode (column and row). The images may also be
- # output to a single file with multiple frames, to an animation or to a
- # montage.
- #
- # OPTIONS:
- #
- # -s size ... SIZE is the crop subsection WidthxHeight dimensions in pixels.
- # Either one or two non-negative integers may be used with "x" separator if two.
- # If only one is provided (with no separator), then it will be used for both
- # width and height. The default="128x128".
- #
- # -o overlap ... OVERLAP is the amount of overlap of subsections. Overlap may
- # be specified as pixels or percent of subsection size. Values are either one
- # or two non-negative integers with "x" separator. If a percent sign is
- # included, then the overlap will be converted to pixels. Values must be
- # specified (or convert) in the range of zero to the subsection size. The
- # default="50%x50%".
- #
- # -m mode ... MODE of the output. Choices are matrix (numbered) or m,
- # sequential (numbered) or s, frames (mode) or f and animation (mode) or a.
- # The default=matrix.
- #
- # -u (uniform) ... Flag to keep only same size crop sections and discard
- # smaller pieces on the right and bottom. The default is to keep all pieces.
- #
- # -i initnum ... INITNUM is the initial (starting) number for output naming.
- # Values are non-negative integers. The default=1.
- #
- # -z zeropad ... ZEROPAD is the number of digits with zero padding for
- # numbering the output images in sequential mode. Values are non-negative
- # integers. The default=0 (no zero padding).
- #
- # -d delay ... DELAY for animation mode. Values are non-negative integers. The
- # default=50.
- #
- # -l loop ... LOOP is the number of times to loop the animation. Values are
- # non-negative integers. The default=0 (endless looping).
- #
- # -c (canvas) ... Flag to leave the virtual canvas in the meta data for the
- # images. This is useful when making an animation so that the subsections keep
- # their position relative to the original image. The default is to remove the
- # virtual canvas, which then just has each frame of the animation replacing the
- # previous one.
- #
- # -M (montage) ... Flag to create a single montage image for matrix or
- # sequential modes only. The default is no montage.
- #
- # -L (label) ... Flag to add filename labels to each image in the montage.
- # The default is no filename labels.
- #
- # -F frame ... FRAME is the size of the frame-like border in pixels placed
- # around each image in the montage. Values are non-negative integers.
- # The default=5.
- #
- # -S spacing ... SPACING is the amount of space in pixels to put between each
- # images in the montage. Values are non-negative integers. The default=0.
- #
- # -R (remove) ... Flag to remove/delete all individual images generated
- # prior to creating the montage. Th default is to leave all individual images,
- # i.e, no deletion.
- #
- # CAVEAT: No guarantee that this script will work on all platforms,
- # nor that trapping of inconsistent parameters is complete and
- # foolproof. Use At Your Own Risk.
- #
- ######
- #
- # set default values
- size="128x128"
- overlap="50%x50%" # percent or pixels, must not be 100% or size of subsection
- mode="matrix" # matrix or sequential or frames or animation
- uniform="no" # uniform size only, skip small sections at right and bottom; yes or no
- initnum=1 # initial number for sequential or matrix mode; integer>=0
- zeropad=0 # number of digits with zero padding for sequential mode; integer>=0
- delay=50 # delay for animation mode; integer>=0
- loop=0 # looping for animation mode; integer>=0
- canvas="off" # on or off to keep virtual canvas; on is useful for animation
- montage="no" # montage images, applicable only to matrix or sequential mode
- label="no" # montage label with filename; yes or no
- frame=5 # montage frame size in pixels; integer>=0
- spacing=0 # montage spacing in pixels; integer>=0
- remove="no" # remove individual images if montage
- echo "1"
- # set directory for temporary files
- dir="." # suggestions are dir="." or dir="/tmp"
- echo "2"
- # set up functions to report Usage and Usage with Description
- PROGNAME=`type $0 | awk '{print $3}'` # search for executable on path
- PROGDIR=`dirname $PROGNAME` # extract directory of program
- PROGNAME=`basename $PROGNAME` # base name of program
- usage1()
- {
- echo >&2 ""
- echo >&2 "$PROGNAME:" "$@"
- sed >&2 -e '1,/^####/d; /^###/g; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
- }
- usage2()
- {
- echo >&2 ""
- echo >&2 "$PROGNAME:" "$@"
- sed >&2 -e '1,/^####/d; /^######/g; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
- }
- echo "3"
- # function to report error messages
- errMsg()
- {
- echo ""
- echo $1
- echo ""
- usage1
- exit 1
- }
- echo "4"
- # function to test for minus at start of value of second part of option 1 or 2
- checkMinus()
- {
- test=`echo "$1" | grep -c '^-.*$'` # returns 1 if match; 0 otherwise
- [ $test -eq 1 ] && errMsg "$errorMsg"
- }
- echo "5"
- # test for correct number of arguments and get values
- if [ $# -eq 0 ]
- then
- # help information
- echo ""
- usage2
- exit 0
- elif [ $# -gt 24 ]
- then
- errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---"
- else
- while [ $# -gt 0 ]
- do
- # get parameter values
- case "$1" in
- -h|-help) # help information
- echo ""
- usage2
- exit 0
- ;;
- -s) # get size
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID SIZE SPECIFICATION ---"
- checkMinus "$1"
- size=`expr "$1" : '\([0-9]*x*[0-9]*\)'`
- [ "$size" = "" ] && errMsg "--- SIZE=$size MUST BE ONE OR TWO x SEPARATED NON-NEGATIVE INTEGERS ---"
- ;;
- -o) # get overlap
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID OVERLAP SPECIFICATION ---"
- checkMinus "$1"
- overlap=`expr "$1" : '\([0-9]*%*x*[0-9]*%*\)'`
- [ "$overlap" = "" ] && errMsg "--- OVERLAP=$overlap MUST BE ONE OR TWO x SEPARATED NON-NEGATIVE INTEGERS ---"
- ;;
- -m) # get mode
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID MODE SPECIFICATION ---"
- checkMinus "$1"
- mode=`echo "$1" | tr "[:upper:]" "[:lower:]"`
- case "$mode" in
- matrix|m) mode="matrix" ;;
- sequential|s) mode="sequential" ;;
- frames|f) mode="frames" ;;
- animation|a) mode="animation" ;;
- *) errMsg "--- MODE=$mode IS AN INVALID VALUE ---"
- esac
- ;;
- -u) # set uniform
- uniform="yes"
- ;;
- -i) # get initnum
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID INITNUM SPECIFICATION ---"
- checkMinus "$1"
- initnum=`expr "$1" : '\([0-9]*\)'`
- [ "$initnum" = "" ] && errMsg "--- INITNUM=$initnum MUST BE A NON-NEGATIVE INTEGER ---"
- ;;
- -z) # get zeropad
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID ZEROPAD SPECIFICATION ---"
- checkMinus "$1"
- zeropad=`expr "$1" : '\([0-9]*\)'`
- [ "$zeropad" = "" ] && errMsg "--- ZEROPAD=$zeropad MUST BE A NON-NEGATIVE INTEGER ---"
- ;;
- -d) # get delay
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID DELAY SPECIFICATION ---"
- checkMinus "$1"
- delay=`expr "$1" : '\([0-9]*\)'`
- [ "$delay" = "" ] && errMsg "--- DELAY=$delay MUST BE A NON-NEGATIVE INTEGER ---"
- ;;
- -l) # get loop
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID LOOP SPECIFICATION ---"
- checkMinus "$1"
- loop=`expr "$1" : '\([0-9]*\)'`
- [ "$loop" = "" ] && errMsg "--- LOOP=$loop MUST BE A NON-NEGATIVE INTEGER ---"
- ;;
- -c) # set canvas
- canvas="on"
- ;;
- -M) # set montage
- montage="yes"
- ;;
- -L) # set label
- label="yes"
- ;;
- -F) # get frame
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID FRAME SPECIFICATION ---"
- checkMinus "$1"
- frame=`expr "$1" : '\([0-9]*\)'`
- [ "$frame" = "" ] && errMsg "--- FRAME=$frame MUST BE A NON-NEGATIVE INTEGER ---"
- ;;
- -S) # get spacing
- shift # to get the next parameter
- # test if parameter starts with minus sign
- errorMsg="--- INVALID SPACING SPECIFICATION ---"
- checkMinus "$1"
- spacing=`expr "$1" : '\([0-9]*\)'`
- [ "$spacing" = "" ] && errMsg "--- SPACING=$spacing MUST BE A NON-NEGATIVE INTEGER ---"
- ;;
- -R) # set remove
- remove="yes"
- ;;
- -) # STDIN and end of arguments
- break
- ;;
- -*) # any other - argument
- errMsg "--- UNKNOWN OPTION ---"
- ;;
- *) # end of arguments
- break
- ;;
- esac
- shift # next option
- done
- #
- # get infile and outfile
- infile="$1"
- outfile="$2"
- fi
- echo "6"
- # test that infile provided
- [ "$infile" = "" ] && errMsg "NO INPUT FILE SPECIFIED"
- # test that outfile provided
- [ "$outfile" = "" ] && errMsg "NO OUTPUT FILE SPECIFIED"
- outname=`echo "$outfile" | sed -n 's/^\(.*\)[\.].*$/\1/p'`
- suffix=`echo "$outfile" | sed -n 's/^.*[\.]\(.*\)$/\1/p'`
- sfx=`echo "$suffix" | tr "[:upper:]" "[:lower:]"`
- if [ "$mode" = "animation" -a "$sfx" != "gif" -a "$sfx" != "miff" ]; then
- errMsg "--- ANIMATION REQUIRES SUFFIX OF GIF OR MIFF ---"
- fi
- # setup temporary images
- tmpA1="$dir/overlapcrop_A_$$.mpc"
- tmpA2="$dir/overlapcrop_A_$$.cache"
- tmp1="$dir/overlapcrop_1_$$.miff"
- trap "rm -f $tmpA1 $tmpA2 $tmp1;" 0
- trap "rm -f $tmpA1 $tmpA2 $tmp1; exit 1" 1 2 3 15
- trap "rm -f $tmpA1 $tmpA2 $tmp1; exit 1" ERR
- # read the input image and filter image into the temp files and test validity.
- convert -quiet "$infile" $gray +repage "$tmpA1" ||
- errMsg "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAS ZERO SIZE ---"
- echo "7"
- # get width and height of image
- ww=`identify -ping -format "%w" $tmpA1`
- hh=`identify -ping -format "%h" $tmpA1`
- # get width and height of subsection
- sw=`echo "${size}" | cut -dx -f1`
- sh=`echo "${size}" | cut -dx -f2`
- #echo "sw=$sw; sh=$sh"
- # test that subsection smaller than image
- [ $sw -ge $ww -o $sh -ge $hh ] && errMsg "--- SUBSECTION SIZE MUST BE SMALLER THAN INFILE SIZE ---"
- echo "8"
- # get offset amount in pixels for subsection taking into account overlap
- test=`echo "$overlap" | grep "%"`
- #echo "test=$test"
- if [ "$test" = "" ]; then
- # overlap in pixels
- ox=`echo "${overlap}" | cut -dx -f1`
- oy=`echo "${overlap}" | cut -dx -f2`
- else
- # overlap in percent
- overlap=`echo "$overlap" | sed 's/%//g'`
- ox=`echo "${overlap}" | cut -dx -f1`
- oy=`echo "${overlap}" | cut -dx -f2`
- # convert to pixels
- ox=`convert xc: -format "%[fx:floor($ox*$sw/100)]" info:`
- oy=`convert xc: -format "%[fx:floor($oy*$sh/100)]" info:`
- fi
- ow=`convert xc: -format "%[fx:$sw-$ox]" info:`
- oh=`convert xc: -format "%[fx:$sh-$oy]" info:`
- # test if overlap is sw or sh
- [ $ox -eq $sw ] && errMsg "--- X OVERLAP CANNOT EQUAL THE WIDTH OF THE SUBSECTION ---"
- [ $oy -eq $sh ] && errMsg "--- Y OVERLAP CANNOT EQUAL THE HEIGHT OF THE SUBSECTION ---"
- echo "9"
- # get ending pixel for stopping loops
- if [ "$uniform" = "no" ]; then
- ew=`convert xc: -format "%[fx:$ww-$sw+$ox-1]" info:`
- eh=`convert xc: -format "%[fx:$hh-$sh+$oy-1]" info:`
- elif [ "$uniform" = "yes" ]; then
- ew=`convert xc: -format "%[fx:$ww-$sw]" info:`
- eh=`convert xc: -format "%[fx:$hh-$sh]" info:`
- fi
- echo "9.1"
- #echo "ww=$ww; hh=$hh; sw=$sw; sh=$sh; ow=$ow; oh=$oh; ew=$ew; eh=$eh"
- # set up to keep virtual canvas
- if [ "$canvas" = "off" ]; then
- repaging="+repage"
- else
- repaging=""
- fi
- echo "9.2"
- # compute number of sections
- k=0
- for ((i=0;i<=eh;i+=oh)); do
- for ((j=0;j<=ew;j+=ow)); do
- ((k++))
- done
- done
- num=$k
- echo "10"
- echo "mode=$mode"
- if [ "$mode" = "frames" -o "$mode" = "animation" ]; then
- convert -size $size xc: $tmp1
- fi
- echo ""
- # process subsections
- filelist=""
- t=1
- k=$initnum
- m=$initnum
- dh=0
- for ((i=0;i<=eh;i+=oh)); do
- dw=0
- n=$initnum
- for ((j=0;j<=ew;j+=ow)); do
- echo "Subsection: $t out of $num (${sw}x${sh}+${dw}+${dh}) row=$m col=$n"
- if [ "$mode" = "frames" ]; then
- convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging miff:- | convert $tmp1 - $tmp1
- elif [ "$mode" = "animation" ]; then
- convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging miff:- | convert $tmp1 - $tmp1
- elif [ "$mode" = "sequential" ]; then
- kk=`printf "%0${zeropad}d" $k`
- convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging ${outname}_$kk.$suffix
- filelist="$filelist ${outname}_$kk.$suffix"
- elif [ "$mode" = "matrix" ]; then
- convert $tmpA1[${sw}x${sh}+${dw}+${dh}] $repaging ${outname}_r${m}_c${n}.$suffix
- filelist="$filelist ${outname}_r${m}_c${n}.$suffix"
- fi
- dw=$(($dw+$ow))
- ((t++))
- ((k++))
- ((n++))
- done
- dh=$(($dh+$oh))
- ((m++))
- done
- echo ""
- echo "11"
- if [ "$mode" = "frames" ]; then
- convert $tmp1 -delete 0 ${outname}.$suffix
- elif [ "$mode" = "animation" ]; then
- convert -delay $delay -dispose Background $tmp1 -delete 0 -loop $loop "${outname}_animation.$suffix"
- fi
- echo "12"
- if [ "$mode" != "frames" -a "$mode" != "animation" -a "$montage" = "yes" ]; then
- if [ "$label" = "yes" ]; then
- labeling="-label %t"
- else
- labeling=""
- fi
- montage $labeling $filelist -tile $((n-initnum))x$((m-initnum)) \
- -frame $frame -geometry +${spacing}+${spacing} \
- "${outname}_montage.$suffix"
- if [ "$remove" = "yes" ]; then
- rm $filelist
- fi
- fi
- echo "13"
- exit 0
Advertisement
Add Comment
Please, Sign In to add comment