#!/bin/bash

tmp=./tmp
limit=150
meldwidth=10

if [ ! -d $tmp ]; then
  mkdir $tmp
fi

function makeppm ()
{
  if [ -f $1 ] ; then
    cat $1
  elif [ -f $1.ppm ] ; then
    cat $1.ppm
  elif [ -f $1.pgm ] ; then
    cat $1.pgm
  elif [ -f $1.pbm ] ; then
    cat $1.pbm
  elif [ -f $1.tif ] ; then
    tifftopnm $1.tif
  elif [ -f $1.tiff ] ; then
    tifftopnm $1.tiff
  else
    cat /dev/null
  fi
}

function nthword()
{
  index=$[$1+1]
  echo $@ | awk "{print \$$index}"
}

#
# syntax: filesize FILENAMEBASE WIDTHVARNAME HEIGHTVARNAME
#

function filesize()
{
  pnminfo=$(pnmfile <(makeppm $1))
  eval "$2=$(eval nthword 4 $pnminfo)"
  eval "$3=$(eval nthword 6 $pnminfo)"
}

function avgpgmval()
{
  read
  read
  totpixels=0
  sumvals=0
  while read value count rest ; do
    totpixels=$[totpixels+count]
    sumvals=$[sumvals+count*value]
  done
  echo $[(sumvals+totpixels/2)/totpixels]
}

#
# syntax: matchfiles LEFTFILE RIGHTFILE LEFTCENTER RIGHTCENTER HEIGHTOFFSET WINDOWSIZE WINDOWSTEP
#
# if LEFTCENTER or RIGHTCENTER is zero, the function will calculate
# the assumed "center of final image" offsets in the left/right files
# based on the sizes of the two files.
#
# Returns with the following useful variables set:
#
# leftcenter, rightcenter
# stripleft, striptop     (strip cut from left file)
# windowleft, windowtop   (window cut from right file)
# bestx, besty            (best-match offsets from center of window)
# mindiff                 (best/lowest error)

function matchfiles ()
{
  file1=$1
  file2=$2
  leftcenter=$3
  rightcenter=$4
  heightoffset=$5
  windowsize=$6
  windowstep=$7

  echo "Looking at $file1 and $file2"

  filesize $file1 x1 y1
  filesize $file2 x2 y2

  echo ""

  echo "$file1 is $x1 by $y1, $file2 is $x2 by $y2"

  if [ $y1 -gt $y2 ] ; then
    height=$y1
  else
    height=$y2
  fi

  height=$[105*height/100]

  echo ""

  echo "Final image height is $height"

  width=$height

  if [ $leftcenter -eq 0 ] ; then
    leftcenter=$[width/2]
  fi

  if [ $rightcenter -eq 0 ] ; then
    rightcenter=$[x2-(width/2)]
  fi

  stripheight=$[90 * height / 100 - 2 * $windowsize]
#  stripwidth=20
  stripwidth=$[width/10]

  windowleftmargin=$windowsize
  windowrightmargin=$windowsize
  windowtopmargin=$windowsize
  windowbottommargin=$windowsize
  
  if [ $[windowleftmargin+stripwidth/2] -gt $rightcenter ] ; then
    windowleftmargin=$[rightcenter-stripwidth/2]
  fi

  windowwidth=$[stripwidth+windowleftmargin+windowrightmargin]
  windowheight=$[stripheight+windowtopmargin+windowbottommargin]
  
  leftdown=$[y1/2]
  rightdown=$[y2/2+heightoffset]

  striptop=$[leftdown-stripheight/2]
  stripleft=$[leftcenter-(stripwidth/2)]

  windowtop=$[rightdown-windowheight/2]
  windowleft=$[rightcenter-windowleftmargin-(stripwidth/2)]

  echo ""
  echo "Left-side strip is $stripwidth by $stripheight"
  echo "  pinned $leftcenter from the left"
  echo "  offset $stripleft from the left, $striptop from the top"
  echo ""
  echo "Right-side window is $windowwidth by $windowheight"
  echo "  pinned $rightcenter from the left"
  echo "  offset $windowleft from the left, $windowtop from the top"
  echo ""

  echo "Cutting strip"

  makeppm $file1 | pnmcut $stripleft $striptop $stripwidth $stripheight > $tmp/strip.ppm

  echo "Cutting window"

  makeppm $file2 | pnmcut $windowleft $windowtop $windowwidth $windowheight > $tmp/window.ppm

  mindiff=9999
  
  rm -f $tmp/mesh.pgm
  echo "P2" > $tmp/mesh.pgm
  echo $[windowtopmargin+windowbottommargin+1] >>  $tmp/mesh.pgm
  echo $[windowleftmargin+windowrightmargin+1] >>  $tmp/mesh.pgm
  echo "255" >> $tmp/mesh.pgm
  
#  offsetx=-$windowleftmargin
#  while [ $offsetx -le $windowrightmargin ] ; do
#    offsety=-$windowtopmargin
#    while [ $offsety -le $windowrightmargin ] ; do
#      pnmcut $[offsetx+windowleftmargin] $[offsety+windowtopmargin] $stripwidth $stripheight $tmp/window.ppm > $tmp/chomp.ppm
#      pnmarith -difference $tmp/strip.ppm $tmp/chomp.ppm \
#          | ppmtopgm > $tmp/compare.pgm
#      diff=$(pgmhist $tmp/compare.pgm | ./avgpgmval)
#      echo $[255-diff] >> $tmp/mesh.pgm
#      if [ $diff -lt $mindiff ] ; then
#        echo "Offset $offsetx $offsety    Average error $diff"
#        mindiff=$diff
#        bestx=$offsetx
#        besty=$offsety
#	mv $tmp/compare.pgm $tmp/glare.pgm
#	mv $tmp/chomp.ppm $tmp/best.ppm
#      fi
#      offsety=$[offsety+windowstep]
#    done
#    offsetx=$[offsetx+windowstep]
#  done

  matchresults=$(match $tmp/strip.ppm $tmp/window.ppm $windowstep)
  bestx=$(nthword 1 $matchresults)
  besty=$(nthword 2 $matchresults)
  mindiff=$(nthword 3 $matchresults)
  
  pnmcut $[bestx+windowleftmargin] $[besty+windowtopmargin]  $stripwidth $stripheight < $tmp/window.ppm > $tmp/best.ppm

  echo "Best match was at $bestx $besty with average error $mindiff"

}

#
# syntax; rotmatch FILEBASE ANGLE [CENTERLINE]
#

function rotmatch ()
{

  echo ""
  echo "*** Computing with rotation of $2 degrees ***"
  echo ""
  
  rm -f $tmp/*
  
  echo $2 > /tmp/rotation
  
  echo "Converting to PPM and rotating"
  makeppm $1-2 | pnmrotate $2 > $tmp/rotated.ppm

  echo "Creating 1/9-scale subimages"
  
  makeppm $1-1 | pnmscale .11111 > $tmp/ninth-left.ppm
  pnmscale .11111 < $tmp/rotated.ppm > $tmp/ninth-right.ppm
  
  echo ""
  echo "Matching 1/9-scale files"
  echo ""
  
  if [ "$3" = "" ] ; then
     centerline=0
  else
     centerline=$3
  fi

#  matchfiles $tmp/ninth-left $tmp/ninth-right $centerline 0 0 20 2
  matchfiles $tmp/ninth-left $tmp/ninth-right $centerline 0 0 20 2
  
  pnmtotiff $tmp/strip.ppm  > $tmp/strip-9.tif
  pnmtotiff $tmp/window.ppm > $tmp/window-9.tif
  pnmtotiff $tmp/best.ppm   > $tmp/best-9.tif
#  pnmtotiff $tmp/mesh.pgm   > $tmp/mesh-9.tif
#   pnmtotiff $tmp/glare.pgm  > $tmp/glare-9.tif
  
  if [ $mindiff -gt $limit ] ; then
    echo ""
    echo "Poor match, bailing out"
    echo ""
    return
  fi
  
  echo ""
  echo "Creating 1/3-size subimages"
  echo ""
  
  makeppm $1-1 | pnmscale .33333 > $tmp/third-left.ppm
  pnmscale .33333 < $tmp/rotated.ppm > $tmp/third-right.ppm
  
  echo ""
  echo "Matching 1/3-scale files"
  echo ""
  
  displacey=$[besty*3]
  
#  matchfiles $tmp/third-left $tmp/third-right \
#  	$[leftcenter*3] $[(rightcenter+bestx)*3] $displacey 6 1
  matchfiles $tmp/third-left $tmp/third-right \
  	$[leftcenter*3] $[(rightcenter+bestx)*3] $displacey 30 2
  
  pnmtotiff $tmp/strip.ppm  > $tmp/strip-3.tif
  pnmtotiff $tmp/window.ppm > $tmp/window-3.tif
#  pnmtotiff $tmp/mesh.pgm   > $tmp/mesh-3.tif
  pnmtotiff $tmp/best.ppm   > $tmp/best-3.tif
#  pnmtotiff $tmp/glare.pgm  > $tmp/glare-3.tif
  
  if [ $mindiff -gt $limit ] ; then
    echo ""
    echo "Poor match, bailing out"
    echo ""
    return
  fi
  
  echo ""
  echo "Matching full-scale files"
  echo ""
  
  displacey=$[(displacey+besty)*3]
  
  matchfiles $1-1 $tmp/rotated \
  	$[leftcenter*3] $[(rightcenter+bestx)*3] $displacey 6 1
#  matchfiles $1-1 $tmp/rotated \
#  	$[leftcenter*3] $[(rightcenter+bestx)*3] $displacey 10 1
  
  pnmtotiff $tmp/strip.ppm  > $tmp/strip-1.tif
  pnmtotiff $tmp/window.ppm > $tmp/window-1.tif
#  pnmtotiff $tmp/mesh.pgm   > $tmp/mesh-1.tif
  pnmtotiff $tmp/best.ppm   > $tmp/best-1.tif
#  pnmtotiff $tmp/glare.pgm  > $tmp/glare-1.tif
  
}

#
# syntax: avgerr file1 file2
#
# echos back the average pixel difference
#
function avgerr ()
{
#  toodark=$(pnmarith -subtract $1 $2 | ppmtopgm | pgmhist | ./avgpgmval)
#  toobright=$(pnmarith -subtract $2 $1 | ppmtopgm | pgmhist | ./avgpgmval)
#  
#  echo $[toobright-toodark]
   leftbrightness=$(ppmtopgm < $1 | pgmhist | avgpgmval)
   rightbrightness=$(ppmtopgm < $2 | pgmhist | avgpgmval)
   echo $[rightbrightness-leftbrightness]
}

# syntax: adjustederr file1 file2 adjustment
#
# Runs ppmbrighten on the second files, then uses avgerr to return
# the error between the first and adjusted-second files
#
function adjustederr ()
{
  rm -f $tmp/adjusted.ppm
  ppmbrighten -v $(hundredths $3) < $2 > $tmp/adjusted.ppm
  avgerr $1 $tmp/adjusted.ppm
}

function hundredths ()
{
  (sed -e 's/-/_/' << EOF
2
k
$1
100
/
p
EOF
)  | dc | sed -e 's/^-\./-0\./'
}

#
# syntax: brightmatch file1 files
#
# returns with $brighter (adjustment amount) and $brighterr set.
#

function brightmatch ()
{
  brighter=5000
  dimmer=-5000
  
  brighterr=$(adjustederr $1 $2 $brighter)
  dimerr=$(adjustederr $1 $2 $dimmer)
  
  go=1
  
  while [ $go -eq 1 ] ; do
  
     midpoint=$[(brighter+dimmer)/2]
     midpointerr=$(adjustederr $1 $2 $midpoint)
     
     echo "Probe correction of $midpoint, error is $midpointerr";
     
     if [ $midpointerr -gt 0 ] ; then
       if [ $brighter -eq $midpoint ] ; then
         go=0
       fi
       brighter=$midpoint
       brighterr=$midpointerr
     else
       if [ $dimmer -eq $midpoint ] ; then
         go=0
       fi
       dimmer=$[midpoint]
       dimerr=$midpointerr
     fi

#    adjust=$[(brighter-dimmer)/10]
    
#    if [ $adjust -le 0 ] ; then
#      adjust=1
#    fi
    
#    if [ $brighterr -gt $[-dimerr] ] ; then
#      brighter=$[brighter-adjust]
#      brighterr=$(adjustederr $1 $2 $brighter)
#    else
#      dimmer=$[dimmer+adjust]
#      dimerr=$(adjustederr $1 $2 $dimmer)
#    fi

    done
}

#
# syntax: splice leftfile rightfile
#
# assumes that many of the variables for this file base were set
# in a prior invokation of rotmatch.
#

function splice ()
{
  rightcenter=$[rightcenter+bestx]
  rightdown=$[rightdown+besty]

  if [ $leftdown -ge $rightdown ] ; then
    lefttop=$[leftdown-rightdown]
    righttop=0
    downtocenter=$rightdown
  else
    lefttop=0
    righttop=$[rightdown-leftdown]
    downtocenter=$leftdown
  fi

  leftheight=$[y1-lefttop]
  rightheight=$[y2-righttop]
  
  leftwidth=$leftcenter
  rightwidth=$[x2-rightcenter]
  
  echo ""
  echo "Left strip is $leftwidth by $leftheight"
  echo "  starting at 0, $lefttop"
  echo "Right strip is $rightwidth by $rightheight"
  echo "  starting at $rightcenter, $righttop"
  echo ""
  
  echo "Cutting left strip"

  makeppm $1 | pnmcut 0 $lefttop $leftwidth $leftheight >   $tmp/left.ppm
  
  echo "Cutting right strip"
  
  pnmcut $rightcenter $righttop $rightwidth $rightheight < $2 > $tmp/right.ppm
  
  echo "Catenating strips"
  
  pnmcat -black -leftright -jtop $tmp/left.ppm $tmp/right.ppm > $tmp/splice.ppm

  leftupper=$[leftdown-lefttop]
  leftlower=$[y1-leftdown]
  
  rightupper=$[rightdown-righttop]
  rightlower=$[y2-rightdown]
  
  meldupper=$leftupper
  
  if [ $rightupper -lt $meldupper ] ; then
    meldupper=$rightupper
  fi
  
  meldlower=$leftlower
  
  if [ $rightlower -lt $meldlower ] ; then
    meldlower=$rightlower
  fi

  meldheight=$[meldupper+meldlower]
  
  echo "Cutting left meld slice"
  
  makeppm $1 | pnmcut $[leftcenter-(meldwidth/2)] $[leftdown-meldupper] \
                        $meldwidth $meldheight >   $tmp/meldleft.ppm
  
  echo "Cutting right meld slice"
  
  pnmcut $[rightcenter-($meldwidth/2)] $[rightdown-meldupper] \
         $meldwidth $meldheight < $2 > $tmp/meldright.ppm
  
  echo "Constructing meld ramps"
  
  pgmramp8 -lr $meldwidth $meldheight > $tmp/rightramp.pgm
  pnminvert < $tmp/rightramp.pgm > $tmp/leftramp.pgm  

  echo "Ramping meld slices"
  
  pnmarith -multiply $tmp/meldleft.ppm $tmp/leftramp.pgm > $tmp/meldedleft.ppm
  pnmarith -multiply $tmp/meldright.ppm $tmp/rightramp.pgm > $tmp/meldedright.ppm
  
  echo "Blending ramps"
  
  pnmarith -add $tmp/meldedleft.ppm $tmp/meldedright.ppm > $tmp/meld.ppm
  
  echo "Pasting blend into the composite"
  
  pnmpaste -replace $tmp/meld.ppm \
          $[leftcenter-(meldwidth/2)] \
	  $[downtocenter-meldupper] $tmp/splice.ppm > $tmp/final.ppm

  echo "Making TIFF"
  
  pnmtotiff -lzw < $tmp/final.ppm > $tmp/final.tif
}
  
