summaryrefslogtreecommitdiffstats
path: root/trimmer
diff options
context:
space:
mode:
authorFlorian Pritz <bluewind@xinu.at>2012-10-16 15:08:18 +0200
committerFlorian Pritz <bluewind@xinu.at>2012-10-16 15:08:18 +0200
commit900aa95d4dc4254cf54328c9466b801a38fa540d (patch)
tree328eca1ba834478933b3482c967fea245e1e6da9 /trimmer
parent27052abe40c471807fc3fe2d97b775ac4ec9c44c (diff)
downloadbin-900aa95d4dc4254cf54328c9466b801a38fa540d.tar.gz
bin-900aa95d4dc4254cf54328c9466b801a38fa540d.tar.xz
add trimmer; partextract.c
Signed-off-by: Florian Pritz <bluewind@xinu.at>
Diffstat (limited to 'trimmer')
-rwxr-xr-xtrimmer384
1 files changed, 384 insertions, 0 deletions
diff --git a/trimmer b/trimmer
new file mode 100755
index 0000000..dfc2182
--- /dev/null
+++ b/trimmer
@@ -0,0 +1,384 @@
+#!/bin/bash
+#
+# Developed by Fred Weinhaus 5/14/2009 .......... revised 5/15/2009
+#
+# USAGE: trimmer [-s sides] [-f fuzzval] [-b bcolor] [-g gcolor] infile outfile
+# USAGE: trimmer [-h or -help]
+#
+# OPTIONS:
+#
+# -s sides comma delimited list of sides to trim; list can include
+# any combination of: north, east, south, west or just "all";
+# default=north
+# -f fuzzamt fuzz amount in percent for trimming border color; float;
+# fuzzamt>=0; default=0
+# -b bcolor background color for area to trim; any valid IM color
+# may be specified; default will be determined automatically
+# from the average color of all specified sides
+# -g gcolor guard color used to preserve sides not be trimmed;
+# any valid IM color that is further from the background color
+# than the fuzzval; default will be determined automatically
+# as either the complement of the background color, black or
+# white whichever is furthest from the background color.
+#
+###
+#
+# NAME: TRIMMER
+#
+# PURPOSE: To trim the background from any number of specified sides of an image.
+#
+# DESCRIPTION: UNROTATE trims the background from any number of specified sides
+# of an image. The user may specify from one to four sides as a comma delimited list
+# that is enclosed in quotes. A fuzz value may be specified if the background is not
+# a constant color.
+#
+#
+# Arguments:
+#
+# -s sides --- SIDES is a comma delimited list of the sides to be trimmed enclosed
+# in quotes. Any number of sides from one to four may be specified. The list can
+# include any combination of: north, east, south, west or just "all".
+# The default=north.
+#
+# -f fuzzamt --- FUZZAMT is the fuzz amount specified as a float percent greater
+# than zero (without the % sign). The default is zero which indicates that border
+# is a uniform color. Larger values are needed when the border is not a uniform color.
+#
+# -b bcolor --- BCOLOR is the background color for the area to trim. Any valid IM
+# color may be specified. The default will be determined automatically from the
+# average color of all specified sides. There is no guarantee that this will be
+# accurate. So if it does not work, then you will need to supply the border color.
+#
+# -g gcolor --- GCOLOR is the guard color used to preserve the side that are not
+# to be trimmed. Any valid IM color may be specified that is further from the
+# background color than the fuzzval. The default will be determined automatically
+# as either the complement of the background color, black or white whichever is
+# furthest from the background color. There is no guarantee that this will be
+# accurate. So if it does not work, then you will need to supply the guard color.
+#
+# 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;
+sides="north" # comma delimited list: north, south, east, west, all
+fuzzamt=0 # fuzz amount in percent
+bcolor="" # background color; use none for transparent background
+gcolor="" # guard color
+
+# set directory for temporary files
+dir="." # suggestions are dir="." or dir="/tmp"
+
+# 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 -n '/^###/q; /^#/!q; s/^#//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
+ }
+usage2()
+ {
+ echo >&2 ""
+ echo >&2 "$PROGNAME:" "$@"
+ sed >&2 -n '/^######/q; /^#/!q; s/^#*//; s/^ //; 4,$p' "$PROGDIR/$PROGNAME"
+ }
+
+# function to report error messages
+errMsg()
+ {
+ echo ""
+ echo $1
+ echo ""
+ usage1
+ exit 1
+ }
+
+# 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"
+ }
+
+# test for correct number of arguments and get values
+if [ $# -eq 0 ]
+ then
+ # help information
+ echo ""
+ usage2
+ exit 0
+elif [ $# -gt 10 ]
+ then
+ errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---"
+else
+ while [ $# -gt 0 ]
+ do
+ # get parameters
+ case "$1" in
+ -h|-help) # help information
+ echo ""
+ usage2
+ ;;
+ -s) # sides
+ shift # to get the next parameter
+ # test if parameter starts with minus sign
+ errorMsg="--- INVALID SIDES SPECIFICATION ---"
+ checkMinus "$1"
+ sides=$1
+ # further testing done later
+ ;;
+ -f) # fuzzamt
+ shift # to get the next parameter - fuzzval
+ # test if parameter starts with minus sign
+ errorMsg="--- INVALID FUZZAMT SPECIFICATION ---"
+ checkMinus "$1"
+ fuzzamt=`expr "$1" : '\([.0-9]*\)'`
+ [ "$fuzzamt" = "" ] && errMsg "--- FUZZAMT=$fuzzamt MUST BE A NON-NEGATIVE FLOATING POINT VALUE (with no sign) ---"
+ fuzzamttest=`echo "$fuzzamt < 0" | bc`
+ [ $fuzzamttest -eq 1 ] && errMsg "--- FUZZAMT=$fuzzamt MUST BE A NON-NEGATIVE FLOATING POINT VALUE ---"
+ ;;
+ -b) # bcolor
+ shift # to get the next parameter
+ # test if parameter starts with minus sign
+ errorMsg="--- INVALID BACKGROUND COLOR SPECIFICATION ---"
+ checkMinus "$1"
+ bcolor=$1
+ ;;
+ -g) # gcolor
+ shift # to get the next parameter
+ # test if parameter starts with minus sign
+ errorMsg="--- INVALID GUARD COLOR SPECIFICATION ---"
+ checkMinus "$1"
+ gcolor=$1
+ ;;
+ -) # 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
+
+# test that infile provided
+[ "$infile" = "" ] && errMsg "NO INPUT FILE SPECIFIED"
+
+# test that outfile provided
+[ "$outfile" = "" ] && errMsg "NO OUTPUT FILE SPECIFIED"
+
+# setup temporary files
+tmpA="$dir/trimmer_$$.mpc"
+tmpB="$dir/trimmer_$$.cache"
+trap "rm -f $tmpA $tmpB; exit 0" 0
+trap "rm -f $tmpA $tmpB; exit 1" 1 2 3 15
+
+# read the input image into the TMP cached image.
+convert -quiet -regard-warnings "$infile" +repage "$tmpA" ||
+ errMsg "--- FILE $infile NOT READABLE OR HAS ZERO SIZE ---"
+
+
+# get sides as array
+sides=`echo "$sides" | tr "[:upper:]" "[:lower:]"`
+# add comma to end, then remove spaces, then change commas to spaces
+sides_list=`echo "${sides}," | sed -n 's/[ ]*//gp' | tr "," " "`
+sidesArray=($sides_list)
+num=${#sidesArray[*]}
+
+
+# test valid sides
+i=0
+while [ $i -lt $num ]; do
+ side="${sidesArray[$i]}"
+ case "$side" in
+ north) ;;
+ east) ;;
+ south) ;;
+ west) ;;
+ all) ;;
+ *) echo "--- INVALID SIDE SPECIFIED ---" ;;
+ esac
+ i=`expr $i + 1`
+done
+
+
+# strip duplicate sides
+# change space delimited list to list of one-word rows
+# note \012 is octal for line break
+sides_list=`echo "$sides_list" | tr " " "\012"`
+
+# sort list of rows to reorder and remove duplicates
+sides_list=`echo $sides_list | sort -u`
+
+# use grep '.*' to put back into space delimited list from sorted rows
+sides_list=`echo $sides_list | grep '.*'`
+
+
+# process image if sides=all or all 4 sides provided, then exit 0
+# otherwise continute
+if [ "$sides_list" = "all" -o $num -eq 4 ]; then
+ convert $tmpA -fuzz ${fuzzamt}% -trim +repage $outfile
+ exit 0
+fi
+
+
+# change sides to "remove" to sides to "preserve" by
+# deleting elements from list of all possible values
+pSidesArray=(north east south west)
+i=0
+while [ $i -lt $num ]; do
+ side="${sidesArray[$i]}"
+ [ "$side" = "north" ] && pnum=0
+ [ "$side" = "east" ] && pnum=1
+ [ "$side" = "south" ] && pnum=2
+ [ "$side" = "west" ] && pnum=3
+ unset pSidesArray[$pnum]
+ i=`expr $i + 1`
+done
+pnum="${#pSidesArray[*]}"
+
+# NOTE: must reset array from list to remove empty and non-showing elements
+# produced by unset, so that the new array can be indexed properly again.
+pSidesArray=(${pSidesArray[*]})
+pnum="${#pSidesArray[*]}"
+
+
+if [ "$bcolor" = "" ]; then
+ # get average color of specified sides
+
+ # get width and height and sides to be removed
+ ww=`identify -ping -format "%w" $tmpA`
+ hh=`identify -ping -format "%h" $tmpA`
+ [ "${sidesArray[0]}" != "" ] && side1="${sidesArray[0]}"
+ [ "${sidesArray[1]}" != "" ] && side2="${sidesArray[1]}"
+ [ "${sidesArray[2]}" != "" ] && side3="${sidesArray[2]}"
+ [ "${sidesArray[3]}" != "" ] && side4="${sidesArray[3]}"
+
+ # get average colors for all four outer edges
+ color_north=`convert ${infile} -gravity north -crop ${ww}x1+0+0 +repage -format '%[pixel:s.p{0,0}]' info:`
+ color_east=`convert ${infile} -gravity east -crop 1x${hh}+0+0 +repage -format '%[pixel:s.p{0,0}]' info:`
+ color_south=`convert ${infile} -gravity south -crop ${ww}x1+0+0 +repage -format '%[pixel:s.p{0,0}]' info:`
+ color_west=`convert ${infile} -gravity west -crop 1x${hh}+0+0 +repage -format '%[pixel:s.p{0,0}]' info:`
+
+ # compute global average from only edges (averages) to be removed
+ # use that for background color
+ if [ $num -eq 1 ]; then
+ eval color1="\${color_${side1}}"
+ bcolor="$color1"
+ elif [ $num -eq 2 ]; then
+ eval color1="\${color_${side1}}"
+ eval color2="\${color_${side2}}"
+ bcolor=`convert xc: -format "%[pixel:($color1+$color2)/2]" info:`
+ elif [ $num -eq 3 ]; then
+ eval color1="\${color_${side1}}"
+ eval color2="\${color_${side2}}"
+ eval color3="\${color_${side3}}"
+ bcolor=`convert xc: -format "%[pixel:($color1+$color2+$color3)/3]" info:`
+ elif [ $num -eq 4 ]; then
+ eval color1="\${color_${side1}}"
+ eval color2="\${color_${side2}}"
+ eval color3="\${color_${side3}}"
+ eval color4="\${color_${side4}}"
+ bcolor=`convert xc: -format "%[pixel:($color1+$color2+$color3+$color4)/4]" info:`
+ fi
+fi
+
+
+if [ "$gcolor" = "" ]; then
+ # get color complement (negate) to background color for possible guard color
+
+ # note: negating the alpha channel does not work for opaque white "rgba(255,255,255,1)"
+ # as ncolor becomes "none" as does not make a good guard color
+ # so just negate ignoring the alpha channel
+ # that seems to work
+ ncolor=`convert -size 1x1 xc:"$bcolor" \
+ -negate -format '%[pixel:s.p{0,0}]' info:`
+
+ # test differnce between background color (in percent) with complement (in percent)
+ # and also with opaque black and opaque white
+ # choose color that is furtherest (largest diff) from background color
+ # to use as guard color
+ diffn=`compare -metric rmse -size 1x1 xc:"$bcolor" xc:"$ncolor" null: 2>&1 | \
+ sed -n 's/^.*[(]\(.*\)[)].*$/\1/p'`
+ diffb=`compare -metric rmse -size 1x1 xc:"$bcolor" xc:"black" null: 2>&1 | \
+ sed -n 's/^.*[(]\(.*\)[)].*$/\1/p'`
+ diffw=`compare -metric rmse -size 1x1 xc:"$bcolor" xc:"white" null: 2>&1 | \
+ sed -n 's/^.*[(]\(.*\)[)].*$/\1/p'`
+ diff_max=`convert xc: -format "%[fx:max(max($diffn,$diffb),$diffw)]" info:`
+ if [ "$diffn" = "$diff_max" ]; then
+ gcolor="$ncolor"
+ elif [ "$diffb" = "$diff_max" ]; then
+ gcolor="black"
+ elif [ "$diffw" = "$diff_max" ]; then
+ gcolor="white"
+ fi
+fi
+
+
+# set up spice and chop amounts
+i=0
+while [ $i -lt $pnum ]; do
+ side=${pSidesArray[$i]}
+ if [ "$side" = "north" ]; then
+ amountsArray[$i]="0x1+0+0"
+ elif [ "$side" = "south" ]; then
+ amountsArray[$i]="0x1+0+0"
+ elif [ "$side" = "west" ]; then
+ amountsArray[$i]="1x0+0+0"
+ elif [ "$side" = "east" ]; then
+ amountsArray[$i]="1x0+0+0"
+ fi
+ i=`expr $i + 1`
+done
+
+
+# set up command sequences
+# splice
+splicer=""
+i=0
+while [ $i -lt $pnum ]; do
+ splicer="$splicer -gravity ${pSidesArray[$i]} -splice ${amountsArray[$i]}"
+ i=`expr $i + 1`
+done
+
+
+# composite
+composer=""
+i=0
+while [ $i -lt $pnum ]; do
+ composer="$composer -size 1x1 xc:$gcolor -gravity ${pSidesArray[$i]} -composite"
+ i=`expr $i + 1`
+done
+
+
+# chop
+chopper=""
+i=0
+while [ $i -lt $pnum ]; do
+ chopper="$chopper -gravity ${pSidesArray[$i]} -chop ${amountsArray[$i]}"
+ i=`expr $i + 1`
+done
+
+
+# do trimming
+convert $tmpA \
+ -background "$bcolor" $splicer \
+ $composer \
+ -fuzz ${fuzzamt}% -trim +repage \
+ $chopper \
+ $outfile
+
+exit 0