#!/bin/bash
# usage: ./findangle pages/02_02_1-Center.jpg

DEBUG="0"
rm -f /tmp/CONNECTED.txt

fix(){
    # pnmshear barfs on -.05 but accepts -0.05, hence this hack...
    echo $1 | ecce - - -command "v/-./s/-0./;%c" 2>/dev/null
}

rotate(){  # $1 angle  $2 input file (ignored because cached) $3 output file
##  convert $2 -negate ROT-TEST1-inverted.jpg
##  jpegtopnm < ROT-TEST1-inverted.jpg > ROT-TEST1.pnm 2> /dev/null
    pnmshear -noantialias "`fix $1`" ROT-TEST1.pnm > ROT-OUT-inverted.pnm
    pnmtojpeg < ROT-OUT-inverted.pnm > ROT-OUT-inverted.jpg
    convert ROT-OUT-inverted.jpg -negate $3
    rm -f ROT-OUT-inverted.pnm ROT-OUT-inverted.jpg
}

vertical(){
    if [ $DEBUG -eq 1 ] ; then
     convert $1 \
       -fuzz 15% \
       -auto-level -depth 1 \
       -define connected-components:exclude-header=true \
       -define connected-components:mean-color=true \
       -define connected-components:area-threshold=200-20000 \
       -define connected-components:eccentricity-threshold=0.99 \
       -define connected-components:angle-threshold=3 \
       -define connected-components:verbose=true -connected-components 8 \
       /dev/null | grep -v " 0:" | tee $2
    else
     convert $1 \
       -fuzz 15% \
       -auto-level -depth 1 \
       -define connected-components:exclude-header=true \
       -define connected-components:mean-color=true \
       -define connected-components:area-threshold=200-20000 \
       -define connected-components:eccentricity-threshold=0.99 \
       -define connected-components:angle-threshold=3 \
       -define connected-components:verbose=true -connected-components 8 \
       /dev/null | grep -v " 0:" > $2
    fi
}

iterate(){
    TESTANGLE="`echo $TESTANGLE + $1 | bc -l`"
    if [ $DEBUG -eq 1 ] ; then
        echo New Testing Angle = $TESTANGLE \(Delta rotation was $1\)
    fi
    
    rotate $TESTANGLE DUMMY ROT-OUT.jpg  
##   cached once:
##    pnmshear -noantialias "`fix $TESTANGLE`" ROT-TEST1.pnm > ROT-OUT-inverted.pnm
##    pnmtojpeg < ROT-OUT-inverted.pnm > ROT-OUT-inverted.jpg
##    convert ROT-OUT-inverted.jpg -negate ROT-OUT.jpg

    vertical ROT-OUT.jpg ROTATED.txt; rm -f ROT-OUT.jpg

    if [ $DEBUG -eq 1 ] ; then
        echo A: compare `./widths ROTATED.txt | bc -l` to `./widths BASELINE.txt | bc -l`
    fi
    if [ `./widths ROTATED.txt | bc -l` -lt `./widths BASELINE.txt | bc -l` ] ; then
        if [ $DEBUG -eq 1 ] ; then
            echo Best Angle so far is now $TESTANGLE
        fi
        PREVIOUS_BEST="$BEST_SO_FAR"
        BEST_SO_FAR="`fix $TESTANGLE`"
        mv ROTATED.txt BASELINE.txt
        iterate $1
    elif [ `./widths ROTATED.txt | bc -l` -eq `./widths BASELINE.txt | bc -l` ] ; then
        if [ $DEBUG -eq 1 ] ; then
            echo Best Angle so far remains $TESTANGLE
        fi
        mv ROTATED.txt BASELINE.txt
        iterate $1        
    fi
}

clockloop(){
    if [ $DEBUG -eq 1 ] ; then
        echo "Will increase clockwise rotation until vertical"
    fi
    mv CLOCKWISE.txt BASELINE.txt
    iterate $1
}

anticlockloop(){
    if [ $DEBUG -eq 1 ] ; then
        echo "Will increase anti-clockwise rotation until vertical"
    fi
    mv ANTICLOCKWISE.txt BASELINE.txt
    iterate $1
}

# we have to work with white on black because sheared empty spaces are in black

if [ $# -eq 0 ]; then
    echo syntax: findangle [-d] filename
    exit 1
fi

if [ $# -eq 2 -a "$1" == "-d" ]; then
    DEBUG="1"
    shift
fi

if [ ! -f $1 ]; then
    echo findangle: file not found - $1
fi

# cache processed version of input:
convert $1 -negate ROT-TEST1-inverted.jpg
jpegtopnm < ROT-TEST1-inverted.jpg > ROT-TEST1.pnm 2> /dev/null

BEST_SO_FAR="0"
TESTANGLE="0.05"
vertical $1 BASELINE.txt

# clockwise
rotate -$TESTANGLE DUMMY ROT-OUT.jpg
vertical ROT-OUT.jpg CLOCKWISE.txt
if [ $DEBUG -eq 1 ] ; then
    echo B: compare `./widths CLOCKWISE.txt | bc -l` to `./widths BASELINE.txt | bc -l`
fi
if [ `./widths CLOCKWISE.txt | bc -l` -lt `./widths BASELINE.txt | bc -l` ] ; then
    if [ $DEBUG -eq 1 ] ; then
        echo Initial guess improvement - Clockwise
    fi
    PREVIOUS_BEST="0"
    BEST_SO_FAR="-0.05"
    clockloop "-0.05"
    if [ $DEBUG -eq 1 ] ; then
        echo PREVIOUS_BEST $PREVIOUS_BEST BEST_SO_FAR $BEST_SO_FAR GETTING_WORSE $TESTANGLE
    fi
    #
    # At this point we COULD iterate from PREVIOUS_BEST to TESTANGLE in -0.01 steps to fine tune!
    #
    if [ $DEBUG -eq 1 ] ; then
        echo Fine tuning...
    fi
    BEST_SO_FAR="$PREVIOUS_BEST"
      rotate $PREVIOUS_BEST DUMMY ROT-OUT.jpg
      vertical ROT-OUT.jpg CLOCKWISE.txt
    clockloop "-0.01"
    if [ $DEBUG -eq 1 ] ; then
        echo PREVIOUS_BEST $PREVIOUS_BEST BEST_SO_FAR $BEST_SO_FAR GETTING_WORSE $TESTANGLE
    fi
    
    rm -f ROT-OUT.jpg CLOCKWISE.txt BASELINE.txt ROTATED.txt ROT-TEST1-inverted.jpg ROT-TEST1.pnm
    echo `fix $BEST_SO_FAR`
    exit 0
fi

##echo ""

# anticlockwise
rotate $TESTANGLE $1 ROT-OUT.jpg
vertical ROT-OUT.jpg ANTICLOCKWISE.txt
if [ $DEBUG -eq 1 ] ; then
    echo C: compare `./widths ANTICLOCKWISE.txt | bc -l` to `./widths BASELINE.txt | bc -l`
fi
if [ `./widths ANTICLOCKWISE.txt | bc -l` -lt `./widths BASELINE.txt | bc -l` ] ; then
    if [ $DEBUG -eq 1 ] ; then
        echo Initial guess improvement - Anti-clockwise
    fi
    PREVIOUS_BEST="0"
    BEST_SO_FAR="0.05"
    anticlockloop "0.05"
    if [ $DEBUG -eq 1 ] ; then
        echo PREVIOUS_BEST $PREVIOUS_BEST BEST_SO_FAR $BEST_SO_FAR GETTING_WORSE $TESTANGLE
    fi
    #
    # At this point we COULD iterate from PREVIOUS_BEST to TESTANGLE in 0.01 steps to fine tune!
    #
    if [ $DEBUG -eq 1 ] ; then
        echo Fine tuning...
    fi
    BEST_SO_FAR="$PREVIOUS_BEST"
      rotate $PREVIOUS_BEST DUMMY ROT-OUT.jpg
      vertical ROT-OUT.jpg ANTICLOCKWISE.txt
    clockloop "0.01"
    if [ $DEBUG -eq 1 ] ; then
        echo PREVIOUS_BEST $PREVIOUS_BEST BEST_SO_FAR $BEST_SO_FAR GETTING_WORSE $TESTANGLE
    fi
    
    rm -f ROT-OUT.jpg CLOCKWISE.txt ANTICLOCKWISE.txt BASELINE.txt ROTATED.txt ROT-TEST1-inverted.jpg ROT-TEST1.pnm
    echo `fix $BEST_SO_FAR`
    exit 0
fi

# HACK
# If we didn't find improvement with initial 0.05 guess, repeat with 0.01 guess
#
# Everything between HACK and END HACK may be deleted...
if [ $DEBUG -eq 1 ] ; then
    echo Looked aligned - trying finer adjustments...
fi

BEST_SO_FAR="0"
TESTANGLE="0.01"
vertical $1 BASELINE.txt

# clockwise
rotate -$TESTANGLE $1 ROT-OUT.jpg
vertical ROT-OUT.jpg CLOCKWISE.txt
if [ $DEBUG -eq 1 ] ; then
    echo D: compare `./widths CLOCKWISE.txt | bc -l` to `./widths BASELINE.txt | bc -l`
fi
if [ `./widths CLOCKWISE.txt | bc -l` -lt `./widths BASELINE.txt | bc -l` ] ; then
    if [ $DEBUG -eq 1 ] ; then
        echo Initial guess improvement - Clockwise
    fi
    PREVIOUS_BEST="0"
    BEST_SO_FAR="-0.01"
    clockloop "-0.01"
    rm -f ROT-OUT.jpg CLOCKWISE.txt BASELINE.txt ROTATED.txt ROT-TEST1-inverted.jpg ROT-TEST1.pnm
    if [ $DEBUG -eq 1 ] ; then
        echo PREVIOUS_BEST $PREVIOUS_BEST BEST_SO_FAR $BEST_SO_FAR GETTING_WORSE $TESTANGLE
    fi
    echo `fix $BEST_SO_FAR`
    exit 0
fi

##echo ""

# anticlockwise
rotate $TESTANGLE $1 ROT-OUT.jpg
vertical ROT-OUT.jpg ANTICLOCKWISE.txt
if [ $DEBUG -eq 1 ] ; then
    echo E: compare `./widths ANTICLOCKWISE.txt | bc -l` to `./widths BASELINE.txt | bc -l`
fi
if [ `./widths ANTICLOCKWISE.txt | bc -l` -lt `./widths BASELINE.txt | bc -l` ] ; then
    if [ $DEBUG -eq 1 ] ; then
        echo Initial guess improvement - Anti-clockwise
    fi
    PREVIOUS_BEST="0"
    BEST_SO_FAR="0.01"
    anticlockloop "0.01"
    rm -f ROT-OUT.jpg CLOCKWISE.txt ANTICLOCKWISE.txt BASELINE.txt ROTATED.txt ROT-TEST1-inverted.jpg ROT-TEST1.pnm
    if [ $DEBUG -eq 1 ] ; then
        echo PREVIOUS_BEST $PREVIOUS_BEST BEST_SO_FAR $BEST_SO_FAR GETTING_WORSE $TESTANGLE
    fi
    echo `fix $BEST_SO_FAR`
    exit 0
fi

# END HACK

rm -f ROT-OUT.jpg CLOCKWISE.txt ANTICLOCKWISE.txt BASELINE.txt ROTATED.txt ROT-TEST1-inverted.jpg ROT-TEST1.pnm
echo "0"
exit 0
