#!/bin/bash
#
# Developed by Fred Weinhaus 10/18/2014 .......... revised 4/25/2015
# 
# ------------------------------------------------------------------------------
# 
# Licensing:
# 
# Copyright © Fred Weinhaus
# 
# My scripts are available free of charge for non-commercial use, ONLY.
# 
# For use of my scripts in commercial (for-profit) environments or 
# non-free applications, please contact me (Fred Weinhaus) for 
# licensing arrangements. My email address is fmw at alink dot net.
# 
# If you: 1) redistribute, 2) incorporate any of these scripts into other 
# free applications or 3) reprogram them in another scripting language, 
# then you must contact me for permission, especially if the result might 
# be used in a commercial or for-profit environment.
# 
# My scripts are also subject, in a subordinate manner, to the ImageMagick 
# license, which can be found at: http://www.imagemagick.org/script/license.php
# 
# ------------------------------------------------------------------------------
# 
####
#
# USAGE: color2alpha [-ca alphacolor] [-cr replacecolor] [-a] [-g gain] 
# infile outfile
# USAGE: color2alpha [-h or -help]
# 
# OPTIONS:
# 
# -ca     alphacolor       color to to become transparent in the alpha channel; 
#						   any valid opaque IM color; default=red
# -cr     replacecolor     color to use to replace alphacolor in the output; 
#						   any valid IM color; default does no color 
#                          replacement in the output and the alpha channel 
#       				   is attached to the input.
# -a                       output only the alpha channel.
# -g      gain             gain control for transiton between black and white  
#                          in the alpha channel; float>0; default=1;
#                          values larger than 1 will show more transparency;
#                          values smaller than 1 will show less transparency;
# 
###
# 
# NAME: COLOR2ALPHA 
# 
# PURPOSE: To create a ramped alpha channel from the input according to the 
# specified color.
# 
# DESCRIPTION: COLOR2ALPHA creates a ramped alpha channel from the input image
# according to the specified color. The output can be either the alpha mask 
# alone or made as an alpha channel on the input image. If a second replacement
# color is provided, then the output will use the alpha channel to replace the
# specified colors and those near it with the replacement color. This is
# useful to change one color to another with anti-aliasing, especially when
# converting background color under colorized text or vice-versa.
# 
# 
# ARGUMENTS: 
# 
# -ca alphacolor ... ALPHACOLOR is the color that is to become transparent in 
# the alpha channel. Any valid opaque IM color is allowed. The default=red.
#
# -cr replacecolor ... REPLACECOLOR is the color to use to replace the 
# alphacolor in the output. Any valid IM color is allowed. The default does 
# no color replacement in the output and the alpha channel is attached to 
# the input.
#
# -a ... output only the ALPHA channel.
#
# -g gain ... GAIN control for the transition between black and white in 
# the alpha channel. Values are floats>0. The default=1. Values larger than 1 
# will show more transparency and a shorter transition. Value smaller than 1 
# will show less transparency and a longer transition.
#
# REFERENCE: http://www.gimp.org/tutorials/Changing_Background_Color_1/
#
# REQUIREMENTS: IM 6.6.0.4 in order to support -evaluate-sequence max
#
# 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
color1="red"		# alphacolor
color2=""			# replacecolor
alphaout="no"		# yes means output only the alpha channel
gain=1				# transition gain control


# set directory for temporary files
# use tmpdir="." or replace with tmpdir="/tmp"
tmpdir="."


# 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 -e '1,/^####/d;  /^###/g;  /^#/!q;  s/^#//;  s/^ //;  4,$p' "$PROGDIR/$PROGNAME"
	}
usage2() 
	{
	echo >&2 ""
	echo >&2 "$PROGNAME:" "$@"
	sed >&2 -e '1,/^####/d;  /^######/g;  /^#/!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 9 ]
	then
	errMsg "--- TOO MANY ARGUMENTS WERE PROVIDED ---"
else
	while [ $# -gt 0 ]
		do
			# get parameter values
			case "$1" in
		  -h|-help)    # help information
					   echo ""
					   usage2
					   exit 0
					   ;;
			   -ca)    # get color1 (alphacolor)
					   shift  # to get the next parameter
					   # test if parameter starts with minus sign 
					   errorMsg="--- INVALID COLOR1 SPECIFICATION ---"
					   checkMinus "$1"
					   color1="$1"
					   ;;
			   -cr)    # get color2 (replacecolor)
					   shift  # to get the next parameter
					   # test if parameter starts with minus sign 
					   errorMsg="--- INVALID COLOR2 SPECIFICATION ---"
					   checkMinus "$1"
					   color2="$1"
					   ;;
				-a)    # set alphaout
					   alphaout="yes"
					   ;;
				-g)    # get gain
					   shift  # to get the next parameter
					   # test if parameter starts with minus sign 
					   errorMsg="--- INVALID GAIN SPECIFICATION ---"
					   checkMinus "$1"
					   gain=`expr "$1" : '\([.0-9]*\)'`
					   [ "$gain" = "" ] && errMsg "--- GAIN=$gain MUST BE A NON-NEGATIVE FLOAT ---"
					   test1=`echo "$gain == 0" | bc`
					   [ $test1 -eq 1 ] && errMsg "--- GAIN=$gain MUST BE A POSITIVE FLOAT ---"
					   ;;
				 -)    # 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"



# create temp directory
dir="$tmpdir/COLOR2ALPHA.$$"
mkdir "$dir" || {
  echo >&2 "UNABLE TO CREATE WORKING DIR \"$dir\" -- ABORTING"
  exit 10
}
trap "rm -rf $dir;" 0
trap "rm -rf $dir; exit 1" 1 2 3 10 15
trap "rm -rf $dir; exit 1" ERR

# read and test input and turn off alpha
if ! convert -quiet "$infile" -alpha off $dir/tmp1.mpc; then
	echo "--- FILE $infile DOES NOT EXIST OR IS NOT AN ORDINARY FILE, NOT READABLE OR HAG ZERO SIZE ---"
	exit 1
fi	


# generate alpha image
convert $dir/tmp1.mpc \
	\( -clone 0 -fill "$color1" -colorize 100 \) \
	-compose difference -composite \
	-separate -evaluate-sequence max \
	-auto-level -evaluate pow $gain \
	$dir/tmp2.mpc

# create output as specified
if [ "$alphaout" = "yes" ]; then
	convert -quiet $dir/tmp2.mpc "$outfile"
elif [ "$color2" = "" ]; then
	convert -quiet $dir/tmp1.mpc $dir/tmp2.mpc \
		-alpha off -compose copy_opacity -composite "$outfile"
elif [ "$color2" != "" ]; then
	convert -quiet $dir/tmp1.mpc $dir/tmp2.mpc \
		-alpha off -compose copy_opacity -composite \
		-compose over -background "$color2" -flatten "$outfile"
fi

exit 0


