#!/bin/sh # $Id: filtr,v 1.50 2008/05/04 22:13:56 asc Exp $ # package : filtr # version : 0.3 # author : Aaron Straup Cope # url : http://aaronland.info/bin/filtr/ # date : $Date: 2008/05/04 22:13:56 $ # copyright : Copyright (c) 2005-2007 Aaron Straup Cope. All Rights Reserved. # license : Perl Artistic License. This is free software, you may use it and # distribute it under the same terms as Perl itself. # # Hello world # NAME="filtr" VERSION="0.3" case $1 in ''|-h|-help|--help|-u|--usage|'-?') echo "${NAME} ${VERSION}" echo "Usage: `basename $0` in.jpg out.jpg [filtr|dazd|postr|postcrd|rockstr]" echo " `basename $0` in.mp4 out.jpg movr " echo " `basename $0` in1.jpg in2.jpg heathr out.jpg" echo " `basename $0` in1.jpg in2.jpg stndpipe out.jpg" exit 0 ;; *) ;; esac # # # OSTYPE=`uname` echo "[startup] ${NAME} ${VERSION}" echo "[startup] ${OSTYPE} ${PATH}" INPUT=$1 OUTPUT=$2 FILTER=$3 # # Bare-bones sanity checking # for file in ${INPUT} do if ! [ -e ${file} ] then echo "[startup] input file ${file} does not exist" echo "[startup] exiting" exit 1 fi done DO_REPORT=1 DO_HEATHR=0 # # Small pieces loosely joined, baby # FILTR=$0 FILTRKIT=`dirname $0`/filtrkit IDENTIFY="identify" CONVERT="convert" COMPOSITE="composite" MONTAGE="montage" FFMPEG="ffmpeg" PERL="perl" PYTHON="python" GS="gs" export PYTHONPATH=${FILTRKIT}/lib/py:${PYTHONPATH} if test "`which gm`" != "" then echo "[startup] found GraphicsMagic -- using that" IDENTIFY="gm identify" CONVERT="gm convert" COMPOSITE="gm composite" MONTAGE="gm montage" fi # # App support - image crunching # echo "[startup] checking filtr dependencies" if test "`which gm`" = "" then for app in $IDENTIFY $CONVERT $COMPOSITE $MONTAGE do if test "`which ${app}`" = "" then echo "[startup] can not locate ${app}" echo "[startup] Exiting" exit 1 fi done fi # # App support various # for app in $PYTHON do if test "`which ${app}`" = "" then echo "[startup] can not locate ${app}" echo "[startup] Exiting" exit 1 fi done # # App support for movr # if test $FILTER = "movr" then for app in $FFMPEG $PERL do if test "`which ${app}`" = "" then echo "[startup] can not locate ${app}" echo "[startup] Exiting" exit 1 fi done fi # # App support for reporting # if [ ${DO_REPORT} -gt 0 ] then if test "`which gs`" = "" then echo "[startup] can not find 'gs' -- disabling reporting"; DO_REPORT=0 fi fi # # Make sure there's a file to work with # if ! [ -e ${INPUT} ] then echo "[startup] can not locate file ${INPUT}" echo "Exiting" exit 1 fi # # What am I trying to do # case $FILTER in postr|postcrd|rockstr|dazd|stndpipe|movr) ;; heathr) FILTER="stndpipe" DO_HEATHR=1 ;; *) FILTER="filtr" ;; esac # # Create a unique identifier for the working image # PID=`${PYTHON} ${FILTRKIT}/md5sum.py ${INPUT} | awk '{split($1, parts, " "); print parts[1]; }'` # # Basic tmp/work files # TMP="${HOME}/.filtr" if ! [ -d ${TMP} ] then echo "[startup] creating ${TMP}" mkdir ${TMP} if ! [ -d ${TMP} ] then echo "[startup] failed to create ${TMP}" echo "[startup] exiting" exit 1 fi fi ID="${TMP}/${PID}-${FILTER}-id.txt" LOMO="${TMP}/${PID}-${FILTER}-lomo.png" MASK="${TMP}/${PID}-${FILTER}-mask.png" NEW="${TMP}/${PID}-${FILTER}-new.jpg" # # Report archives # YMD=`date "+%Y/%m/%d"` if ! [ -d ${TMP}/${YMD} ] then echo "[startup] creating ${TMP}/${YMD}" mkdir -p ${TMP}/${YMD} fi BASENAME=`echo ${INPUT} | awk '{split($1,parts,"/"); i=0; for (p in parts) { i = i + 1}; print parts[i];}'` BASENAME=`echo ${BASENAME} | awk '{split($1,parts,"."); i=0; for (p in parts) { i = i + 1}; print parts[i-1];}'` REPORT="${TMP}/${YMD}/${BASENAME}_${PID}-${FILTER}.jpg" # # Clean up any old files # if [ -e ${OUTPUT} ] then case $FILTER in stndpipe|heathr) ;; *) # fix me echo "[startup] remove ${OUTPUT} (disabled)" # rm ${OUTPUT} esac fi if [ -e ${ID} ] then echo "[startup] remove ${ID}" rm ${ID} fi if [ -e ${MASK} ] then echo "[startup] remove ${MASK}" rm ${MASK} fi if [ -e ${NEW} ] then echo "[startup] remove ${NEW}" rm ${NEW} fi if [ -e ${LOMO} ] then echo "[startup] remove ${LOMO}" rm ${LOMO} fi # # Figure out dimensions # case $FILTER in movr) ;; *) ${IDENTIFY} ${INPUT} | awk '{ split($3,a,"+"); print a[1]; }' > ${ID} W_ORIG=`awk '{ split($1, dims,"x"); print dims[1]; }' ${ID}` H_ORIG=`awk '{ split($1, dims,"x"); print dims[2]; }' ${ID}` W_THUMB=`awk '{ split($1, dims,"x"); print dims[1] / 10; }' ${ID}` H_THUMB=`awk '{ split($1, dims,"x"); print dims[2] / 10; }' ${ID}` W_REPORT=`awk '{ split($1, dims,"x"); print dims[1] * .5; }' ${ID}` H_REPORT=`awk '{ split($1, dims,"x"); print dims[2] * .5; }' ${ID}` ;; esac # # Actually do some work # echo "[startup] process ${INPUT} with ${FILTER} (${PID})" case $FILTER in postcrd|postr) echo "[${FILTER}] create mask" ${CONVERT} -size ${W_THUMB}x${H_THUMB} -contrast -modulate 100,150 -gaussian 1x2 +matte ${INPUT} ${MASK} echo "[${FILTER}] resize mask" ${CONVERT} -resize ${W_ORIG}x${H_ORIG} -gaussian 0x5 -modulate 180,150 ${MASK} ${MASK} echo "[${FILTER}] create lomo" ${CONVERT} -unsharp 1.5x1.5 -modulate 175,100 -contrast -contrast -contrast ${INPUT} ${LOMO} echo "[${FILTER}] tweak lomo" ${CONVERT} -gaussian 1x2 ${LOMO} ${LOMO} echo "[${FILTER}] compose" ${COMPOSITE} -compose multiply ${MASK} ${LOMO} ${NEW} if test $FILTER = "postr" then echo "[${FILTER}] recompose" ${COMPOSITE} -compose multiply ${INPUT} ${NEW} ${NEW} fi mv -f ${NEW} ${OUTPUT} if [ ${DO_REPORT} -gt 0 ] then echo "[${FILTER}] generate report ${REPORT}" ${MONTAGE} -geometry ${W_REPORT}x${H_REPORT}+5+5 -tile 2x2 ${INPUT} ${MASK} ${LOMO} ${OUTPUT} ${REPORT} fi ;; rockstr) echo "[${FILTER}] create output" ${CONVERT} -unsharp 1.5x1.5 -modulate 175,150 -contrast -contrast -contrast ${INPUT} ${OUTPUT} echo "[${FILTER}] blur" ${CONVERT} -gaussian 1x2 ${OUTPUT} ${OUTPUT} echo "[${FILTER}] grayscale" ${CONVERT} -depth 16 -colorspace GRAY -contrast -sharpen 5x5 ${OUTPUT} ${OUTPUT} if [ ${DO_REPORT} -gt 0 ] then echo "[${FILTER}] generate report ${REPORT}" ${MONTAGE} -geometry ${W_REPORT}x${H_REPORT}+5+5 -tile 2x2 ${INPUT} ${OUTPUT} ${REPORT} fi ;; dazd) echo "[${FILTER}] create output" ${CONVERT} -unsharp 1.5x1.5 -modulate 175,150 -contrast -contrast -contrast ${INPUT} ${OUTPUT} echo "[${FILTER}] blur" ${CONVERT} -gaussian 1x2 ${OUTPUT} ${OUTPUT} if [ ${DO_REPORT} -gt 0 ] then echo "[${FILTER}] generate report ${REPORT}" ${MONTAGE} -geometry ${W_REPORT}x${H_REPORT}+5+5 -tile 2x2 ${INPUT} ${OUTPUT} ${REPORT} fi ;; stndpipe) INPUT2=${OUTPUT} HFILTR=$4 HFILTR2=$5 OUTPUT=$6 if test ${DO_HEATHR} = "1" then cp ${INPUT} ${INPUT}.tmp INPUT=${INPUT}.tmp cp ${INPUT2} ${INPUT2}.tmp INPUT2=${INPUT2}.tmp fi for img in ${INPUT} ${INPUT2} do echo "[${FILTER}] ${FILTR} ${img} ${img} ${HFILTR}" ${FILTR} ${img} ${img} ${HFILTR} HFILTR=${HFILTR2} done if test ${DO_HEATHR} = "1" then for img in ${INPUT} ${INPUT2} do ${IDENTIFY} ${img} | awk '{ split($3,a,"+"); print a[1]; }' > ${ID} W_IMG=`awk '{ split($1, dims,"x"); print dims[1]; }' ${ID}` H_IMG=`awk '{ split($1, dims,"x"); print dims[2]; }' ${ID}` echo "[${FILTER}][heathr] img dimensions : ${W_IMG} x ${H_IMG}" CROP_TO=${W_IMG} CROP_X=`awk "BEGIN { print ${W_IMG} - ${H_IMG} }"` CROP_Y=0 if [${W_IMG} -gt ${H_IMG}] then CROP_TO=${H_IMG} CROP_Y=`awk "BEGIN { print ${H_IMG} - ${W_IMG} }"` CROP_X=0 fi echo "[${FILTER}][heathr] ${CONVERT} -crop ${CROP_TO}x${CROP_TO}+${CROP_X}+${CROP_Y} ${img} ${img}" ${CONVERT} -crop ${CROP_TO}x${CROP_TO}+${CROP_X}+${CROP_Y} ${img} ${img} echo "[${FILTER}][heathr] ${IDENTIFY} ${img} > ${ID}" ${IDENTIFY} ${img} | awk '{ split($3,a,"+"); print a[1]; }' > ${ID} W_IMG=`awk '{ split($1, dims,"x"); print dims[1]; }' ${ID}` H_IMG=`awk '{ split($1, dims,"x"); print dims[2]; }' ${ID}` BORDER_SIDES=`awk "BEGIN { print ${W_IMG} * .1 }"` BORDER_TOP=`awk "BEGIN { print ${H_IMG} * .1 }"` BORDER_BOTTOM=`awk "BEGIN { print ${H_IMG} * .3 }"` echo "[${FILTER}][heathr] img borders ${BORDER_SIDES} ; ${BORDER_TOP} ; ${BORDER_BOTTOM}" W_CANVAS=`awk "BEGIN { print ${W_IMG} + (${BORDER_SIDES} * 2) }"` H_CANVAS=`awk "BEGIN { print ${BORDER_TOP} + ${H_IMG} + ${BORDER_BOTTOM} }"` echo "[${FILTER}][heathr] img canvas ${W_CANVAS} x ${H_CANVAS}" CANVAS=${TMP}/${PID}-blank.jpg BG=${TMP}/${PID}-bg.jpg DRAFT=${TMP}/${PID}-draft.jpg echo "[${FILTER}][heathr] ${CONVERT} -size ${W_CANVAS}x${H_CANVAS} xc:white ${CANVAS}" ${CONVERT} -size ${W_CANVAS}x${H_CANVAS} xc:white ${CANVAS} # composite echo "[${FILTER}][heathr] ${COMPOSITE} -geometry +${BORDER_SIDES}+${BORDER_TOP} ${img} ${CANVAS} ${DRAFT}" ${COMPOSITE} -geometry +${BORDER_SIDES}+${BORDER_TOP} ${img} ${CANVAS} ${DRAFT} # generate the background W_BG=`awk "BEGIN { print ${W_CANVAS} + 2 }"` H_BG=`awk "BEGIN { print ${H_CANVAS} + 2 }"` echo "[${FILTER}][heathr] ${CONVERT} -size ${W_BG}x${H_BG} xc:black ${BG}" ${CONVERT} -size ${W_BG}x${H_BG} xc:black ${BG} # place the composite on the background echo "[${FILTER}][heathr] ${COMPOSITE} -geometry +1+1 ${DRAFT} ${BG} ${img}" ${COMPOSITE} -geometry +1+1 ${DRAFT} ${BG} ${img} rm -f ${ID} rm -f ${DRAFT} rm -f ${CANVAS} rm -f ${BG} done # /heathr fi echo "[${FILTER}] ${INPUT} ${INPUT2} heathr ${HFILTR} ${OUTPUT}" echo "[${FILTER}] ${IDENTIFY} ${INPUT} > ${ID}" ${IDENTIFY} ${INPUT} | awk '{ split($3,a,"+"); print a[1]; }' > ${ID} W_ORIG=`awk '{ split($1, dims,"x"); print dims[1]; }' ${ID}` H_ORIG=`awk '{ split($1, dims,"x"); print dims[2]; }' ${ID}` ID2="${TMP}/${PID}-${FILTER}-id2.txt" echo "[${FILTER}] ${IDENTIFY} ${INPUT2} > ${ID2}" ${IDENTIFY} ${INPUT2} | awk '{ split($3,a,"+"); print a[1]; }' > ${ID2} W_ORIG2=`awk '{ split($1, dims,"x"); print dims[1]; }' ${ID2}` H_ORIG2=`awk '{ split($1, dims,"x"); print dims[2]; }' ${ID2}` echo "[${FILTER}] dimensions : ${W_ORIG2} x ${H_ORIG2}" W_HEATHR=`awk "BEGIN{ print ${W_ORIG}+${W_ORIG2} }"` H_HEATHR=${H_ORIG} if [ ${H_ORIG2} -gt ${H_ORIG} ] then H_HEATHR=${H_ORIG2} fi echo "[${FILTER}] dims : ${W_HEATHR} x ${H_HEATHR}" BORDER_CALC=${W_HEATHR} echo "[${FILTER}] border calc : ${BORDER_CALC}" if [ ${H_HEATHR} -gt ${W_HEATHR} ] then BORDER_CALC=${H_HEATHR} echo "[${FILTER}] border calc reset : ${BORDER_CALC}" fi # # hrm...I *think* this is what I want it to do... # BORDER_SIDES=0 #`awk "BEGIN { print ${BORDER_CALC} * .1 }"` BORDER_CENTER=`awk "BEGIN { print ${BORDER_CALC} * .005 }"` BORDER_TOP=0 #`awk "BEGIN { print ${BORDER_CALC} * .1 }"` BORDER_BOTTOM=0 #`awk "BEGIN { print ${BORDER_CALC} * .15 }"` echo "[${FILTER}] borders ${BORDER_SIDES} ; ${BORDER_CENTER} ; ${BORDER_TOP} ; ${BORDER_BOTTOM}" W_CANVAS=`awk "BEGIN { print ${W_HEATHR} + (${BORDER_SIDES} * 2) + ${BORDER_CENTER} }"` H_CANVAS=`awk "BEGIN { print ${BORDER_TOP} + ${H_HEATHR} + ${BORDER_BOTTOM} }"` echo "[${FILTER}] canvas ${W_CANVAS} x ${H_CANVAS}" CANVAS=${TMP}/${PID}-blank.jpg DRAFT=${TMP}/${PID}-draft.jpg ${CONVERT} -size ${W_CANVAS}x${H_CANVAS} xc:white ${CANVAS} W_OFFSET=`awk "BEGIN { print ${W_ORIG} + ${BORDER_SIDES} + ${BORDER_CENTER} }"` echo "[${FILTER}] ${COMPOSITE} -geometry +${BORDER_SIDES}+${BORDER_TOP} ${INPUT} ${CANVAS} ${DRAFT}" ${COMPOSITE} -quality 100 -geometry +${BORDER_SIDES}+${BORDER_TOP} ${INPUT} ${CANVAS} ${DRAFT} echo "[${FILTER}] ${COMPOSITE} -geometry +${W_OFFSET}+${BORDER_TOP} ${INPUT2} ${DRAFT} ${OUTPUT}" ${COMPOSITE} -quality 100 -geometry +${W_OFFSET}+${BORDER_TOP} ${INPUT2} ${DRAFT} ${OUTPUT} echo "[${FILTER}] done!" rm -f ${CANVAS} rm -f ${DRAFT} rm -f ${ID2} if test ${DO_HEATHR} = "1" then rm -f ${INPUT} rm -f ${INPUT2} fi echo "clean" ;; movr) MOVR=$4 IDENT=${PID}"-ffmpeg" TMP_FMT=${PID}"-fr%02d.jpg" echo "[${FILTER}] movring ${INPUT} (${TMP_FMT})" ${FFMPEG} -i ${INPUT} 2> ${TMP}/${IDENT} ${PERL} -MFile::Spec -Mstrict -e 'local $/; undef $/; my $txt = <>; $txt =~ /Duration:\s+(\d{2}):(\d{2}):(\d{2})(?:\.(\d+))?/m; my $hh = $1 * 60 * 60; my $mm = $2 * 60; my $ss = $3; if ($4) { $ss += 1; } my $d = $hh + $mm + $ss; for (my $i = 0; $i < $d; $i++) { my $outfile_name = sprintf("'${TMP_FMT}'",$i); my $outfile = File::Spec->catfile("'${TMP}'", $outfile_name); my $cmd = "'${FFMPEG}' -i '${INPUT}' -f singlejpeg -ss $i $outfile"; print "$cmd\n"; system($cmd); }' ${TMP}/${IDENT} rm -f ${TMP}/${IDENT} for img in `ls ${TMP}/${PID}-fr*.jpg` do echo "[${FILTER}][movr] filtring ${img} (${img}.tmp) ${MOVR}" ${FILTR} ${img} "${img}.tmp" ${MOVR} rm -f ${img} done ${IDENTIFY} ${TMP}/${PID}-fr01.jpg.tmp | awk '{ split($3,a,"+"); print a[1]; }' > ${ID} W_FRAME=`awk '{ split($1, dims,"x"); print dims[1] / 2; }' ${ID}` H_FRAME=`awk '{ split($1, dims,"x"); print dims[2] / 2; }' ${ID}` echo "[${FILTER}] create ${OUTPUT} : ${W_FRAME} ${H_FRAME} per frame" FRAMES=`ls ${TMP}/${PID}-fr*.jpg.tmp | wc -l` TILES=`${PERL} -MPOSIX -e 'print POSIX::ceil(sqrt($ARGV[0]));' ${FRAMES}` echo "[${FILTER}] ${FRAMES} frames makes ${TILES} tiles" ${MONTAGE} -geometry ${W_FRAME}x${H_FRAME}+2+2 -tile ${TILES}x -bordercolor black `ls ${TMP}/${PID}-fr*.jpg.tmp` ${OUTPUT} for img in `ls ${TMP}/${PID}-fr*.jpg.tmp` do echo "[${FILTER}] remove frame ${img}" rm -f ${img} done ;; *) ${CONVERT} -size ${W_THUMB}x${H_THUMB} -contrast -gaussian 1x2 +matte ${INPUT} ${MASK} echo "[${FILTER}] resize mask" ${CONVERT} -resize ${W_ORIG}x${H_ORIG} -gaussian 0x5 -modulate 180,150 ${MASK} ${MASK} echo "[${FILTER}] create lomo" ${CONVERT} -unsharp 1.5x1.5 -contrast -modulate 100,120 ${INPUT} ${LOMO} echo "[${FILTER}] compose" ${COMPOSITE} -compose Multiply ${MASK} ${LOMO} ${NEW} mv -f ${NEW} ${OUTPUT} ;; esac # # EXIF # echo "[cleanup] transfer EXIF data" ${PYTHON} ${FILTRKIT}/mvexif.py ${INPUT} ${OUTPUT} # # Clean up # echo "[cleanup] clean up work files" if [ -e ${ID} ] then echo "[cleanup] remove ${ID}" rm ${ID} fi if [ -e ${MASK} ] then echo "[cleanup] remove ${MASK}" rm ${MASK} fi if [ -e ${LOMO} ] then echo "[cleanup] remove ${LOMO}" rm ${LOMO} fi