#!/bin/bash
#Batch file to process one or more image files in a folder
# normalise (transform image to span the full range of colors),
# sharpen, size(width- maintaining aspect ratio), and change output type. 
#Using a small subset of the options available for the 
#ImageMagick convert and display command line tools
#If something goes wrong, check for any error messages that convert produces
# see http://www.imagemagick.org/script/convert.php for more information.
# by norman bakker adapted from work by many unnamed others
#$0 is the name of this program
#======================================================================
help_message() {
msg="Help instructions for running $0\n  
-h this message\n
-m manual adjustment on each image using Imagemagick after any prior processing\n\n
-b use batch mode (manually scroll through selected images and adjust individually-follow prompts)\n
-d add a date and time stamp to output name of file (in format -YYYY-MM-DD-HH-MM)\n
-l place a label with the date and time in the bottom rh corner of the image\n
-L Only place a label (don't carry out any other processing)\n
-c crop the existing file name to specified no of characters (0)\n
-C add a caption to the filename and timestamp, replacing existing filename\n
-o output file type : save as type (eg jpg, png, bmp,tif) [no change]\n
-u do not use sharpen process [sharpen];\n
 otherwise accept defaults (0x1.0+1.0+0.05) or specify one or more of -r,-s,-a,-t in the following\n
\t    -r unsharp parameter (radius - pixels) [0] - radius should be > sigma, 0 allows method to choose.\n 
\t    -s unsharp parameter (sigma - pixels) [1.0]\n
\t    -a unsharp parameter (amount - fraction) [1.0]\n
\t    -t unsharp parameter (threshold -fraction) [0.05] - increase for noisy images\n
-w width in pixels - [1200] aspect ratio is retained;  -w 0  retains existing size\n
-n do not normalise [normalised]\n
-x usercommand1 : add other convert options not requiring arguments of their own []\n
-y usercommand2 : eg: negate, enhance, identify,\n
-z usercommand3 : eg: auto-gamma, flip, flop, monochrome\n
-0 do nothing; only show commands []\n
\n
Examples :\n  
open the folder with the images,  then to convert all jpg files :\n
\t $0 -o png -w 0 -s 1.5 -a 0.5 -n *.jpg\n
or, after including some of the usercommands to convert all files starting with 'image' :\n
\t $0 -o png -x auto-level -y negate -z flop image*.*\n " 
echo -e $msg
}
#===============================================
check_errs()
# http://steve-parker.org/sh/exitcodes.shtml
{
  # Function. Parameter 1 is the return code
  # Para. 2 is text to display on failure.
  if [ "${1}" -ne "0" ]; then
    echo "ERROR # ${1} : ${2}"
    # as a bonus, make our script exit with the right error code.
    exit ${1}
  fi
}
#===============================================
set_vars() {
# set defaults and variables, defaults can be changed here if desired
width="1200"; 
useunsharp="y";
radius="0";        #see http://www.imagemagick.org/script/command-line-options.php#unsharp
sigma="1.0";       #and particularly  http://redskiesatnight.com/2005/04/06/sharpening-using-image-magick/
amount="1.0";      #For reasonable results, radius should be larger than sigma. Use a radius of 0 to have the method select a suitable radius.
threshold="0.05";  #amount is the percentage of the difference between the original and the blur image that is added 
                   #back into the original (1.0 equals 100%).If you have a noisy image, raise the threshold (1.0 equals 100%)
normalised=" -normalize ";
outfiletype="";
dosomething="y"; #for checking of commands prior to exectution
usercommand1=" "; #choose one from auto-gamma,flip, flop, monochrome,
usercommand2=" "; # negate, transpose, transverse , identify etc 
usercommand3=" "; # ie commands not requiring arguments of their own
suffix="im";  #for output file naming
timestamp="n";  #for timestamp string if not specified
label="n";
labelonly="n";
cropname="0";
caption="0";
ImagemagickGUI="";
ops=""
ts=""
space=" "
seqno=0
#manualforce="";
echo set_vars
}

if [ ${#*} == "0" ];then help_message;exit 0;fi;  #test to see that at least one argument is provided, if not print help


echo -e '\E[37;44m'"Imagemagick processing on `date`\033[0m" #white on blue background

set_vars;

#get options
while getopts "0bdlLnhuIo:r:s:a:t:w:x:y:z:c:C:" optionName; do 
 	case $optionName in     #test for type of arguments;
		h )	help_message; exit 0;;
		o ) outfiletype=$OPTARG;;  #don't leave any spaces here between variable=$OPTARG;;
		r ) radius=$OPTARG;; 
		s ) sigma=$OPTARG;;
		a ) amount=$OPTARG;; 
		t ) threshold=$OPTARG;; 
		w ) width=$OPTARG;;
		x ) usercommand1=" "-$OPTARG" ";; 
		y ) usercommand2=" "-$OPTARG" ";;
		z ) usercommand3=" "-$OPTARG" ";;
		d ) timestamp="y";;
		l ) label="y";timestamp="y";;    #add a timestamp label to image(s)
		L ) labelonly="y";label="y";timestamp="y";;
		c ) cropname=$OPTARG;;
		C ) caption=$OPTARG;;
    	I ) ImagemagickGUI="y";;
#    	M ) manualforce="y";;
		n ) normalised="";;
		0 ) dosomething="";;  #echos rather than executes convert command
		u ) useunsharp="";;
		b ) batchmode="";;
	   \? ) echo Invalid option, try -h "for help"
	 		exit 1 ;;
	   \: ) echo option -$OPTARG requires an argument 
    esac
done
#=================================================
# BYPASS ALL PROCESSING: use the ImagemagickGUI to manually process the images; continue until no files left; then exit
if [[ $ImagemagickGUI = 'y' ]];then shift $(($OPTIND - 1));until [[ -z "$1" ]];
do display -resize 1000 $1;shift;done;echo "Completed ImageMagick";exit 0;fi; 
#=================================================

#build option string for convert command based on options chosen; store these in $ops
if [[ $labelonly = "y" ]];then ops=""; 
else 
if [[ $width != "0" ]] ;then ops=$ops" -resize "$width" ";fi; #if width = 0 then no resizin

ops="$ops $normalised $usercommand1 $usercommand2 $usercommand3";  #normalised is already set above as required
 
if [[ $useunsharp = "y" ]];then ops="$ops -unsharp ${radius}x${sigma}+$amount+$threshold";fi
fi
#==================================================
#read the image files one by one
shift $(($OPTIND - 1)); until [[ -z "$1" ]];   # continue until no files left
do
#--------------------------------------------------
    identify $1  #check we are dealing with a valid image file
    check_errs $? "$1 is not an image file";
    if [[ $? -ne "0" ]]; then exit 1; fi;  #if not halt execution
#--------------------------------------------------
    name="${1%.*}"  #strip the extension from the file name (in $1): see parameter expansion :http://mywiki.wooledge.org/BashFAQ/073
  	ext="${1##*.}"  #get the extension from the file name 
#--------------------------------------------------
  	if [[ $cropname != "0" ]];then name=${name:0:$cropname};fi;    #crop the name the file to the number of characters selected
#--------------------------------------------------
    #add the date and time of the photo if available using extract command (must be installed)
    #note backticks to execute the extract shell command sequence including sed : 
    #example of normal output of extract -p date : date - 2011:08:01 13:49:23
    #extract date metadata then delete all to '- '; delete all ':'; replace remaining ' ' with '-'; 
    #to delete last two characters (seconds) add :  -e 's/..$//g' 
    if [[ $timestamp = "y" ]];then ts=-`extract -p date "$1" | sed -e 's/^.*- //' -e 's/:/ /g' -e 's/ /-/g' `;fi;
    #echo Timestamp is $ts   --OK? y/n;read ans; if [[ $ans = 'n' ]]; then echo Enter ts : $ts; read ts; fi; 
    if [[ $caption != "0" ]];then name="${caption}-$name";fi; #name="${caption}-$seqno"; 
   	if [[ -n "$outfiletype" ]];then ext="$outfiletype";fi #convert to new output file type if one provided
  	outputfilename="$name$ts-$suffix.$ext"
    if  [[ $dosomething = "y" ]]; then  echo Executing : convert "$1" $ops "$outputfilename";
        convert "$1" $ops "$outputfilename";

    else echo No execution:  convert "$1" $ops "$outputfilename";fi
    if [[ $label = 'y' ]];then lble="$name$space$ts";
        actualheight=`identify -format '%h' "$outputfilename"`
        #echo $actualwidth 
        pointsz=$[actualheight/50]
        #echo $pointsz
        fillcolor="gold"  
        #fillcolor="maroon"
        #convert "$outputfilename" -gravity southeast -pointsize $pointsz -fill $fillcolor -annotate 0 "$lble"  "$outputfilename";fi  #plain label
        # http://www.imagemagick.org/Usage/annotating/#anno_on  : outlined label
        convert   "$outputfilename" -gravity southeast -pointsize $pointsz -fill $fillcolor \
                -stroke '#000C' -strokewidth 4 -annotate 0 "$lble" -stroke  none   -annotate 0 "$lble"  "$outputfilename";fi   
                
        #view before and after side by side 
        convert $1 "$outputfilename"  +append -quality 95 'ba.jpg' 
        #display -resize 50% ba.jpg
        #ans=$(zenity --entry --text="OK?")

        if zenity --question --text="Do you want to see the before/after?"; then 
            display -resize 50% ba.jpg;
            if ! zenity --question --text="OK?"; then 
                echo Reprocess "$1"!;
                rm "$outputfilename";
                 #ans=$(zenity --title="Processing parameters" --entry --text="$ops")
                 `zenity --list --title="Parameterlist" --column="$ops" --separator=' ' --multiple`
                fi;
        fi;

        rm ba.jpg

shift
done
echo Finished output is in the same directory
echo ALL DONE!



