#!/bin/bash
#
# hdrff: HDR für Faule - automatic processing of HDR image-sequences
# 
# This script-file will process images given on the commandline. It uses hdrff,
# which is directory-based. hdrff4img is useful for testing configurations
# (e.g. tonemapping parameters), whereas hdrff is targeted at the normal daily
# workflow.
# 
# Note that hdrff4img will not work if you hard-code your ORIG_DIR and IMG_DIR
# in your configuration-files (always use the ": ${ORIG_DIR:=xxx}" syntax!).
#
# $Author: bablokb $
# $Revision: 1.3 $
#
# License: GPL3
# -----------------------------------------------------------------------------

pgmDir=`dirname $0`
libDir="$pgmDir"/../lib/hdrff

# load functions
. "$libDir/functions.inc"

# usage   ---------------------------------------------------------------------

usage() {
   echo -e "\n`basename $0`: create LDR/HDR-images from RAW or JPG images\n\
  \nusage: `basename $0` [options] -t task image [...]\n\
  possible options:\n\
    -t task     target-task: tif fixca align enfuse hdr gimp\n\
                             drago durand fattal mantiuk pattanaik\n\
                             reinhard02 reinhard05\n\
    -D dir      target-directory (defaults to .)\n\
                use + for directory of first argument image\n\
    -C cfg-file read configuration from file cfg-file\n\
    -g          assume all images belong to a group\n\
    -G groups   assume images belong to the given groups (e.g. 1-3 4-10)\n\
    -k          keep intermediate files\n\
    -q          output only error messages\n\
    -v          verbose output (default)\n\
    -h          show this help\n\
    -d modules  list of modules to debug\n\
" >&2
  exit 3
}

# set defaults   --------------------------------------------------------------

setDefaults() {
  verbose="1"
  debug=""
  targetTask=""
  targetDir="."
  hdrffOpts="-v"
  keepFiles=0
  groupInfo=""
  cfgFile="hdrff4img.nofile"
  allTasks="tif fixca align enfuse hdr gimp drago durand fattal mantiuk \
             pattanaik reinhard02 reinhard05"
}

# parse arguments and set variables -------------------------------------------

parseArguments() {
  while getopts ":t:D:C:kgG:qvhd:" opt; do
    case $opt in
      t) targetTask="$OPTARG";;
      D) targetDir="$OPTARG";;
      C) cfgFile="$OPTARG";;
      k) keepFiles=1;;
      g) groupInfo="all";;
      G) groupInfo="$OPTARG";;
      q) verbose=0; hdrffOpts="-q";;
      v) verbose=1; hdrffOpts="-v";;
      h) usage;;
      d) debug="$OPTARG";;
      ?) usage;;
    esac
  done
  shift $((OPTIND-1))
  args=("$@")

  # fix pathnames of argument images
  local i wdir="`pwd`"
  for (( i=0; i<"${#args[@]}"; i++ )); do
    if [ "${args[$i]:0:1}" != "/" ]; then
      args[$i]="$wdir/${args[$i]}"
    fi
  done
}

# check arguments   -----------------------------------------------------------

checkArguments() {
  if [ -z "$targetTask" ]; then
    echo "error: target-type not specified!" >&2
    usage
  fi

  if [ "$allTasks" = "${allTasks/$targetTask}" ]; then
    echo "error: invalid target-type!" >&2
    usage
  fi

  if [ -z "${args[0]}" ]; then
    echo "error: no argument images!" >&2
    usage
  fi

  local f
  for f in "${args[@]}"; do
    if [ ! -f "$f" ]; then
      echo "error: $f does not exist!" >&2
      exit
    fi
  done

  if [ "$targetDir" = "+" ]; then
    targetDir="${args[0]%/*}"
  fi
}

# query extension of first image   --------------------------------------------

getExtension() {
  local ext
  ext="${args[0]}"
  tr "[A-Z]" "[a-z]" <<< "${ext##*.}"
}

# query prefix of first image   ----------------------------------------------

guessPrefix() {
  local img
  img="${args[0]}"
  img="${img##*/}"
  if [ "$img" = "${img/_}" ]; then 
    # no underscore: use everything up to first number as prefix
    imgPrefix=`sed -e "s/^\([^0-9]*\)[0-9]*\..*$/\1/" <<< "$img"`
  else
    imgPrefix="${img%%_*}_"
  fi
  mod=hdrff4img msg "debug" "guessing image-prefix as: $imgPrefix"
}

# map target-type to list of modules   ----------------------------------------

setupModules() {
  local current="$1" ext="$2"
  local mod_tif mod_fixca mod_align mod_enfuse mod_hdr mod_gimp \
        mod_drago mod_durand mod_fattal mod_mantiuk mod_pattanaik \
        mod_reinhard02 mod_reinhard05
  local pref_tif pref_fixca pref_align pref_enfuse pref_hdr pref_gimp \
        pref_drago pref_durand pref_fattal pref_mantiuk pref_pattanaik \
        pref_reinhard02 pref_reinhard05

  mod_tif="name2lc raw2tif jpg2tif"               pref_tif="$IMG_PREFIX"
  mod_fixca="$mod_tif findGroups fixCA"           pref_fixca="$FIXCA_PREFIX"
  mod_align="$mod_fixca alignImages"              pref_align="$AIS_PREFIX"
  mod_enfuse="$mod_align enfuseImages"            pref_enfuse="$ENFUSE_PREFIX"
  mod_hdr="$mod_align makeHDR"                    pref_hdr="$HDR_PREFIX"
  # problem: can't tell automatically
  mod_gimp="makeGIMP"                             pref_gimp="$GIMP_PREFIX"

  mod_drago="$mod_hdr tmDrago"            pref_drago="$TM_DRAGO_PREFIX"
  mod_durand="$mod_hdr tmDurand"          pref_durand="$TM_DURAND_PREFIX"
  mod_fattal="$mod_hdr tmFattal"          pref_fattal="$TM_FATTAL_PREFIX"
  mod_mantiuk="$mod_hdr tmMantiuk"        pref_mantiuk="$TM_MANTIUK_PREFIX"
  mod_pattanaik="$mod_hdr tmPattanaik"    pref_reinhard02="$TM_PATTANAIK_PREFIX"
  mod_reinhard02="$mod_hdr tmReinhard02"  pref_reinhard02="$TM_REINHARD02_PREFIX"
  mod_reinhard05="$mod_hdr tmReinhard05"  pref_reinhard05="$TM_REINHARD05_PREFIX"

  local varname="mod_$targetTask"
  modules="${!varname}"
  varname="pref_$targetTask"
  targetPrefix="${!varname}"
  mod=hdrff4img msg "debug" "prefix of generated files: $targetPrefix"    

  # remove modules corresponding to current task
  if [ -n "$current" ]; then
    local firstModule
    while [ -n "$modules" ]; do
      read firstModule modules <<< "$modules"
      [ "$firstModule" = "$current" ] && break;
    done
  fi
  if [ "$targetTask" != "$tif" -a "$ext" != "hdr"  \
                                 -a "$modules" = "${modules/findGroups}" ]; then
     modules="findGroups $modules"
  fi

  # remove findGoups, if user supplied explicit grouping
  [ -n "$groupInfo" ] && modules="${modules/findGroups}"

  mod=hdrff4img msg "info" "using modules: $modules"    
}

# setup environment for originals as arguments   ------------------------------

setup4orig() {
  local imgExt="$1"
  # images are in raw or jpg-format, i.e. they are original images
  export ORIG_DIR=`mktemp --tmpdir -d hdrff4i.orig.XXXXXX`

  # now link source images to ORIG_DIR
  ln -sf "${args[@]}" "$ORIG_DIR"

  # set IMG_PREFIX
  export IMG_PREFIX=`tr "[A-Z]" "[a-z]" <<< "$imgPrefix"`
  mod=hdrff4img msg "debug" "using IMG_PREFIX=$IMG_PREFIX"

  # set IMG_EXT
  export IMG_EXT=`tr "[A-Z]" "[a-z]" <<< "$imgExt"`
  mod=hdrff4img msg "debug" "using IMG_EXT=$IMG_EXT"

  # current processing-level is empty for original-images
  currentTask=""
}

# setup environment for TIFs as arguments   -----------------------------------

setup4tif() {
  ln -s "${args[@]}" "$IMG_DIR"
  export IMG_PREFIX="$imgPrefix"
  mod=hdrff4img msg "debug" "using IMG_PREFIX=$IMG_PREFIX"

  # query current processing-level
  currentTask=`getProcSw "${args[0]}"`
  mod=hdrff4img msg "info" "images created with: $currentTask"
  if [ "$currentTask" = "${currentTask/hdrff}" ]; then
    # files not processed with hdrff or with old hdrff-version
    if [ "$imgPrefix" = "$FIXCA_PREFIX" ]; then
      currentTask="fixCA"
    elif [ "$imgPrefix" = "$AIS_PREFIX" ]; then
      currentTask="alignImages"
    elif [ "$imgPrefix" = "$ENFUSE_PREFIX" ]; then
      currentTask="enfuseImages"
    else
      currentTask="raw2tif"
    fi
  else
    currentTask="${currentTask/hdrff:}"
  fi

  # setup additional configuration
  if [ "$currentTask" = "fixCA" ]; then
    export FIXCA_PREFIX="$IMG_PREFIX"
  elif [ "$currentTask" = "alignImages" ]; then
    export AIS_PREFIX="$IMG_PREFIX"
  fi
}

# setup environment for HDRs as arguments   -----------------------------------

setup4hdr() {
  ln -s "${args[@]}" "$IMG_DIR"
  export IMG_PREFIX=img_
  mod=hdrff4img msg "debug" "using IMG_PREFIX=$IMG_PREFIX"
  export HDR_PREFIX="$imgPrefix"
  mod=hdrff4img msg "debug" "using HDR_PREFIX=$HDR_PREFIX"

  # current processing-level for hdr-images is always makeHDR
  currentTask="makeHDR"
}

# setup environment for hdrff   -----------------------------------------------

setupEnvironment() {
  export IMG_DIR=`mktemp --tmpdir -d hdrff4i.work.XXXXXX`

  # query extension of first image
  guessPrefix
  local ext=`getExtension`

  local currentTask
  if [ "$ext" = "tif" ]; then
    setup4tif
  elif [ "$ext" != "tif" -a "$ext" != "hdr" ]; then
    setup4orig "$ext"
  elif [ "$ext" = "hdr" ]; then
    setup4hdr
  fi

  # map target-task to list of necessary modules and prefix of result-files
  setupModules "$currentTask" "$ext"

  # create hdr-list if user supplied explicit grouping
  if [ "$ext" = "hdr" -o -n "$groupInfo" ]; then
    createHDRlist "$ext"
  fi
}

# create hdr-list.txt from input-images   -------------------------------------

createHDRlist() {
  hdrList=`mktemp --tmpdir hdrff4i.hdrlist.XXXXXX` 
  export HDR_LIST="$hdrList"

  # prepare group-information
  if [ "$1" = "hdr" ]; then
    # every image is a single group
    groupInfo="`seq -s ' ' 1 ${#args[@]}`"
  elif [ "$groupInfo" = "all" ]; then
    # one large group
    groupInfo="1-${#args[@]}"
  fi

  # write header
  cat <<EOF > "$hdrList"
# HDR-list-file
# automatically created at $(date)
EOF

  # write list of images
  local group img first last i
  for group in $groupInfo; do
    first="${group%-*}"
    last="${group#*-}"
    for (( i=first-1; i<last; ++i )); do
      img="${args[$i]##*/}"
      img="${img%.*}.tif"
      echo -n "${img/$imgPrefix/$IMG_PREFIX}"
      if [ $i -ne $(( last-1 )) ]; then
        echo -n ","
      else
        echo
      fi
    done
  done  >> "$hdrList" 
}

# execute hdrff   -------------------------------------------------------------

runHdrff() {
  "$pgmDir/hdrff" $hdrffOpts ${debug:+-d "$debug"} \
                             ${cfgFile:+-C "$cfgFile"} $modules
}

# move results from temporary IMG_DIR   ----------------------------------------

moveResults() {
  if [ $keepFiles -eq 1 ]; then
    mv -vf "$IMG_DIR"/* "$targetDir" 2>&1 | mod=hdrff4img msg "debug"
  else
     mv -vf "$IMG_DIR"/$targetPrefix* "$targetDir" 2>&1 | 
                                                        mod=hdrff4img msg "debug"
  fi
}

# cleanup environment   --------------------------------------------------------

cleanupEnvironment() {
  if [ "$debug" = "${debug/hdrff4img}" ]; then
    [ -n "$ORIG_DIR" ] && [ "${ORIG_DIR/hdrff4i}" != "$ORIG_DIR" ] && 
                                                              rm -fr "$ORIG_DIR"
    [ -n "$IMG_DIR" ] && [ "${IMG_DIR/hdrff4i}" != "$IMG_DIR" ] && 
                                                              rm -fr "$IMG_DIR"
    rm -f "$hdrList"
  fi
}
# main program   --------------------------------------------------------------

setDefaults
parseArguments "$@"
loadConfiguration "$cfgFile"
fixConfiguration
checkArguments
setupEnvironment
if [ -z "`echo $modules`" ]; then
  mod=hdrff4img msg "warning" "no modules to process"
else  
  runHdrff
  moveResults
fi
cleanupEnvironment
