lilypond-user
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: png cropping


From: Patrick Horgan
Subject: Re: png cropping
Date: Fri, 19 Sep 2008 10:42:00 -0700
User-agent: Thunderbird 2.0.0.16 (X11/20080724)

Jonathan Kulp wrote:
Patrick!  It's all working beautifully now.
I must say that you are most awesomely cool.  How wonderful to find someone that digs in in the best linux/Unix tradition and puts together a string of programs to achieve a desired result.  Hats off to you.

... much cool stuff elided...
p.s. now that we have a tool with a version number, I might try learning how to write a brief manpage for it.  Good idea?
A most excellent idea!  manedit is your friend.  Complete wysiwyg man editor.  Its help has a complete and easy tutorial.  On ubuntu it's just sudo apt-get install maneditSince you're doing that I'm adding a -a (about) with your name and mine, some more comments so others can modify it more easily, and will call it version 1.1.1.  I also added a -V=viewer, so I could use, for example evince if the output format was ps.  N.B. evince doesn't display transparency so if you use it with transparent gifs or pngs you might think the transparency gone, but it's not.

    One feature it really needs is an ability to handle the situation where the output for file.ly is for example, file-page1.png and file-page2.png.  You'd have to get a wildcard list of things that matched $STEM*.png and loop over them to do the conversions, then something like $viewer $STEM*.$FORMAT & at the end.  That would make it work as it currently does for most things, there'd just be one thing in the list, but still work for the case where there's something there.  A generic wildcard is best because someone might have done a #(define output-suffix "blablabla") and we want to support that case too.  eog will bring up all the pages and let you page up and page down through them, and evince will bring a a window for each file.  There's enough examples in the script so that you could figure out how to do it if you would.  We could call it 1.1.2;)  If you don't have time let me know and I'll get to it sometime.  If you do, change the version in the script, add to the changelog at the top and send me a copy:)  Maybe we could donate it to the lilypond project.

Patrick
#!/bin/bash
#*****************************************************#
# Script for making image files from lilypond source  #
# suitable for use as musical examples to insert in a #
# document or web page.                               #
# Creator                      - Jonathan Kulp        #
# Johnny come lately assistant - Patrick Horgan       #
#*****************************************************#
# Change log
#
# 1.1.1 Added -a, -V and much comments
# 1.1   Added checking of return codes so we could
#       abort if something failed.
# 1.0   Initial release
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# setformatlist - gets the list of all the things that
# you can convert to
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
setformatlist()
{
    currentdir=`pwd`    # Remember our current directory
    examp=`which ppmtojpeg` # find out where the progs are
    returnstatus=$?
    if [ $returnstatus -eq 0 ] ; then
        OUTDIR="`dirname $examp`" #grab the directory
        cd $OUTDIR      # change to it so we can
        # find all the programs starting with ppmtoxxxx
        # and remove the initial part so that we can 
        # figure out what ppms can be converted to
        ppmtos=`ls ppmto* | sed -n s/ppmto//p`
        # same for pnmto
        pnmtos=`ls pnmto* | sed -n s/pnmto//p`
        # Now combine the two, change the space separated
        # list into individ line that sort can sort with
        # -u to throw away duplicates, then change newlines
        # back to spaces so we have a sorted list without
        # duplicate of all things we can convert to
        alltos=`echo  $ppmtos $pnmtos | tr " " "\n" | sort -u | tr "\n" " "`
    fi
    cd $currentdir   # Change back so we don't affect anything
}
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# usage is called when we're called incorrectly.
# it never returns
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
usage()
{
    echo "Usage: " `basename $0` " [-v] [-t] [-rN] [-fFORMAT] filename"
    echo "      -v              print version number and quit"
    echo "      -a              about - tell about us and exit"
    echo "      -t              indicates transparency is desired"
    echo "      -r=N            set resolution to N (usually 72-2000)"
    echo "      -f=FORMAT       set format to FORMAT one of:"
    echo "                        jpeg, png, tiff, gif, pcx, bmp"
    echo "      -V=viewer       set image viewer, examp: -V=evince"
    echo "      filename        a lilypond file"
    exit -1
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# about - tell about us and exit
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
about()
{
    echo `basename $0`
    echo "      Creator                 Jonathan Kulp"
    echo "      Johnny-come-lately      Patrick Horgan"
    exit 0
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set prompt to the prompt you want to give a user
# goodvals to the list of acceptable values
# call getval
# when it returns your value is in outval
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getval()
{
    flag="notdone"
    address@hidden
    until [ $flag == "done" ] ; do
        echo -n $prompt " "
        read inval
        if [ A$inval == "A" ] ; then
            # inval is empty
            if [ A$default != 'A' ] ; then
                # default is set to something
                inval=$default
                default=""
            else
                #inval is empty, no default
                echo You must enter a value
                index=0
                echo -n "Expecting one of : "
                while [ "$index" -lt "$elementcount" ] ; do
                    echo -n "${goodvals["$index"]}" " "
                    let index++
                done
                echo
            fi
        fi
        if [ A$inval != "A" ] ; then
            # inval not empty, either they sent us something
            # or we got it from the default
            index=0
            while [ "$index" -lt "$elementcount" ] ; do
                # Walk through list of goodvals to see if we got one
                if [ ${goodvals[$index]} == $inval ] ; then
                    # Yep!  We're done.
                    flag="done"
                    outval=${goodvals[$index]}
                fi
                let index++
            done
            if [ $flag != "done" ] ; then
                # inval not in goodvals, let them know
                index=0
                echo -n "Expecting one of : "
                while [ "$index" -lt "$elementcount" ] ; do
                    echo -n "${goodvals["$index"]}" " "
                    let index++
                done
                echo
            fi
        fi
    done
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Set prompt to the prompt you want to give a user
# call getnumval
# when it returns your value is in outval
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getnumval()
{
    flag="notdone"
    until [ $flag == "done" ] ; do
        echo -n $prompt " "
        read inval
        if [ A$inval == "A" ] ; then
            # inval is empty
            if [ A$default != 'A' ] ; then
                # but default is not, so use it
                inval=$default
                default=""
            else
                # no inval, no default
                echo You must enter a value, expecting a positive numeric value
            fi
        fi
        if [ "A"$inval != 'A' ] ; then
            # inval set either from user or default
            case $inval in
                *[^0-9]*) echo "Error: expecting positive numeric value" ;;
                * ) flag="done" ;;
            esac
        fi
    done
    outval=$inval
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# validatearg()
# set inarg to the value of the argument
# set goodvals to the list of acceptable values
# set prompt to the error message you'd like to give,
# for example "ERROR: bad value for transparency arg"
# this routine will append to it, " expecting: " and
# the list of values from goodvals, then call usage
# to exit
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
validatearg()
{
    flag="notgood"
    address@hidden
    index=0
    if [ "A"$inarg != "A" ] ; then
        while [ "$index" -lt "$elementcount" ] ; do
            if [ ${goodvals[$index]} == $inarg ] ; then
                flag="good"
                outval=${goodvals[$index]}
            fi
            let index++
        done
    fi
    if [ $flag != "good" ] ; then
        index=0
        echo -n $prompt
        echo -n " expecting one of : "
        while [ "$index" -lt "$elementcount" ] ; do
            echo -n "${goodvals["$index"]}" " "
            let index++
        done
        echo
        usage
    fi
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# getopt_simple - Orig by Chris Morgan, stolen from
# the ABS Guide and modified a bit
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
getopt_simple()
{
    until [ -z "$1" ] ; do
        if [ ${1:0:1} = '-' ] ; then
            tmp=${1:1}               # Strip off leading '-' . . .
            if [ ${tmp:0:1} = '-' ] ; then
                tmp=${tmp:1}         # Allow double -
            fi
            parameter=${tmp%%=*}     # Extract name.
            value=${tmp##*=}         # Extract value.
            eval $parameter=$value
        else
            filename=$1
        fi
        shift
    done
}

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Our program starts here.  This is the equivalent of
# our main()
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Give initial defaults to things so we can tell if they
# change
alltos=""
transparency='no'
t='no'
resolution=0
r=0
format='none'
f='none'
V='eog'
filename="none"
version=1.1

setformatlist           # Gets list of all image formats we can convert to
if [ $returnstatus -ne 0 ] ; then
    # Apparently none!
    echo "Sorry, you have to have the netpbm utilities installed to use this."
    exit 1
fi

# process all the options

getopt_simple $*

if [ "$v" == 'v' ] ; then
    # version
    echo `basename $0` version $version
    exit
fi

viewer=$V       # default to eog

if [ "$a" == 'a' ] ; then
    about
fi
if [ $filename == "none" ] ; then
    usage
fi

if [ $t != 'no' ] ; then
    # We let them use -t or --transparency, so if they used -t, we shove
    # the value in $transparency so we don't have to deal with both later
    transparency=$t
fi
if [ $transparency != 'no' ] ; then
    # if transparency is set, make that setting be 'Y' cause that's what
    # we check for later.
    transparency='Y'
fi

# We know $r starts numeric cause we initialize it to 0 if it's not numeric
# now the user put something in in not numeric

case $r in
        *[^0-9]*) echo "Error: resolution not numeric"; usage ;;
esac

if [ $r -ne 0 ] ; then
    # same as with -t, two versions of args, -r and --resolution
    resolution=$r
fi

# Now check resolution for numeric...if it came from -r it has already
# been checked, but no harm checking again

case $resolution in
    *[^0-9]*) echo "Error: resolution must be positive numeric"; usage ;;
esac

if [ $f != 'none' ] ; then
    # fold -f into --format
    format=$f
fi

if [ $format != "none" ] ; then
    # They set format so check it
    inarg=$format
    goodvals=( $alltos )
    prompt="Error: format arg incorrect"
    validatearg
fi


# get filename from first argument

srcfile="`basename $filename`"   

# get filename without .ly extension

STEM="`basename $filename .ly`"

# determine output directory

OUTDIR="`dirname $filename`"

if [[ $resolution -ne 0 ]] ; then
    echo Resolution set to $resolution dots per inch.
    RES=$resolution
else
    # ask for output resolution
    prompt="Enter output resolution in DPI 72, 100, 300, 600, etc...(72): "
    default=72
    getnumval
    RES=$outval
fi

# If transparency is not set, then prompt for it if format is not set yet, or
# if format is set to one of the ones that supports transparency, i.e. gif, png

if [ "$transparency" == 'no' ] ; then
    if [[ ( "$format" == 'gif') || ( "$format" == 'png' ) || ( "$format" == 
'none' ) ]] ; then

        # only prompt for transparency if format unset or set to gif or png

        prompt="Transparency? y/N"
        default="N"
        goodvals=("y" "Y" "n" "N")
        getval
        transparency=$outval
    fi
fi

# ask for desired final output format with a lot of complications based on 
# whether transparency is set.

if [[ ( "$transparency" == "Y" )  || ( "$transparency" == "y" ) ]] ; then
    if [[ ( "$format" != 'gif') && ( "$format" != 'png' ) ]] ; then
        # if they ask for transparency and format's set to something other
        # than gif or png we can't procede--it makes no sense, get them to
        # resolve it.
        if [[ "$format" != 'none' ]] ; then
            echo "You ask for transparency which doesn't work with" $format
        fi
        prompt="Enter desired output format png, gif (png): "
        default="png"
        goodvals=("png" "gif")
        getval
        FORMAT=$outval
    else
        FORMAT=$format
    fi
else
    # we know transparency's not Y or y, but make any other value be 'no'
    # so we only have one thing to check for later
    transparency="no"
    # transparency's not set, so if they gave us a format on the command
    # line use that, else ask them for one.
    if [[ $format != 'none' ]] ; then
        echo Output format is $format
        FORMAT=$format
    else
        prompt="Enter desired output format jpeg, png, tiff, gif, pcx, bmp ... 
(png)  : "
        default='png'
        goodvals=( $alltos )
        getval
        FORMAT=$outval
    fi
fi

cd $OUTDIR

# run lilypond on file with png output for further processing...

lilypond --format=png -dresolution=$RES $srcfile
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
    echo lilypond failed--aborting
    exit $returnstatus
fi

# The next commands crop the png file so that
# it only includes the example instead of an entire page.
# First convert image to pnm for processing with netpbm tools

pngtopnm $STEM.png > $STEM.pnm
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
    echo pngtopnm failed converting the file to pnm so it could be 
cropped--aborting
    exit $returnstatus
fi

# crop all the white space off

pnmcrop -white $STEM.pnm > $STEM-cropped.pnm
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
    echo pnmcrop failed--aborting
    exit $returnstatus
fi

# Now look for a command to do the final conversion, assume we won't find it...

outcmd="invalid"

# assume ppmto$FORMAT will be found

which >& /dev/null ppmto$FORMAT
if [ $? -eq 0 ] ; then
    outcmd=ppmto$FORMAT
else
    # Nope, try pnmto$FORMAT and see if we find that

    which >& /dev/null pnmto$FORMAT
    if [ $? -eq 0 ] ; then
        outcmd=pnmto$FORMAT
    fi
fi

if [ $outcmd == "invalid" ] ; then
    # Baboo!  Didn't find the command
    echo "Sorry, can't find a command for that format."
    exit -1
fi

# convert to end format

if [[ $transparency != 'no' ]] ; then
    echo $outcmd -transparent '#ffffff' $STEM-cropped.pnm
    $outcmd -transparent '#ffffff' $STEM-cropped.pnm > $STEM.$FORMAT
else
    echo $outcmd $STEM-cropped.pnm
    $outcmd $STEM-cropped.pnm > $STEM.$FORMAT
fi
returnstatus=$?
if [ "$returnstatus" -ne 0 ] ; then
    echo $outcmd failed converting to final output--aborting
    exit $returnstatus
fi

# removes pnm and ps files

rm *.pnm

if [ $FORMAT != 'ps' ] ; then
    rm $STEM.ps
fi

# open final image as background process in "Eye of Gnome" Image Viewer
# or alternate viewer set via the -V argument

$viewer $STEM.$FORMAT &

reply via email to

[Prev in Thread] Current Thread [Next in Thread]