#!/bin/bash ## Make an electronic "Greeting-Card" from a photo -- 2010-Dec-18 Eugene Reimer; ## could also be described as a text-onto-photo tool, however it uses super-imposed Postscript-text, not modification of raster-image as done by annotatepix; ## USAGE: revise var X below, with text-editor, before running; each line of text is described with a one-line 5-tuple: ## X Y FONTSIZE FONTNAME TEXT ## the IMAGEFILE is given on the commandline; an aspect-ratio of approximately 1.54 is suggested, that being for folded-in-half letter-size paper; ## could become a "proper command" by giving it parameters for text, font-name, fontsize, x-y-location; ## ## PREREQ: bc bcf chgsed scalepix -- from http://ereimer.net/programs/general-purpose-scripts.htm ## PREREQ: sam2p -- from http://code.google.com/p/sam2p (was: img2ps from http://www.cs.cmu.edu/~chuck/softpg) ## PREREQ: ghostscript netpbm imagemagick -- from any Linux-distro, non-Penguins can google for them USAGE=' cmdline: mk-greetingcard-from-photo [option]... IMAGEFILE option: -?|--help provide usage info -o|--out=FILENAMEBASE output filenames will have .ps and .jpg added -P NBRxNBR pagesize in PS-points; eg: 595x421 for A4-L, 612x396 for Letter-L, 396x612 for Letter-P -D NBR DPI for the Postscript and PDF results -d NBR DPI for the JPEG result -v verbose output defaults: -o greetingcard -P612x396 -m0' ##note the ending stroph ##==defaults for the cmdline params: Wpt=612; Hpt=396 ##pagesize: 612x396-pts (Letter-L); eg: 595x421 for A4-L, 396x612 Letter-Portrait DPI=105.9 ##DPI for JPEG result (so 8.5in==900px); default is no rescaling on PS-intermediate OUT=greetingcard ##for naming result files ##VERBOSE=Y; ##use verbose while debugging; controls additional debug-output X=(40 467 90 /champers-plain "Season's" 40 375 90 /champers-plain "Greetings" 40 128 45 /champers-plain "from" 40 82 45 /champers-plain "Eugene Reimer") ##==VAR for lines of text; each line: X Y SIZE FONTNAME TEXT; dimensions are in points ##parsing cmdline options: if [[ $1 == -\? ]];then echo "$USAGE"; exit 0;fi ##because getopt doesn't support question-mark as a short-option TEMP=$(getopt -nmk-greetingcard -o ho:P:D:d:v --long help,out:,pagesize:,psdpi:,dpi: -- "$@"); if [ $? != 0 ];then echo "$USAGE"; exit 1;fi eval set -- "$TEMP" while true;do case "$1" in ##loop thru getopt result... -h|--help) echo "$USAGE"; exit 0;; -o|--out) OUT="$2"; shift 2;; -P|--pagesize) Wpt=${2%x*};Hpt=${2#*x}; shift 2;; -D|--psdpi) PSDPI=$2; shift 2;; -d|--dpi) DPI=$2; shift 2;; -v|--verbose) VERBOSE=Y; shift;; --) shift;break;; *) echo "getopt Internal Error!"; exit 1;; esac; done [[ $# -eq 1 ]] || { echo "$USAGE"; exit 1; } ##errmsg if too few or too many args IMG=$1 ##remaining non-option arg is the image Win=$(bcf "%.1f" <<<"$Wpt/72"); Hin=$(bcf "%.1f" <<<"$Hpt/72") ##compute size in inches; bcf avoids trailing zeroes for nicer verbose msgs JW=$(bc <<<"round($Win*$DPI)"); JH=$(bc <<<"round($Hin*$DPI)") ##compute JPEG-result-size in pixels eDo () { [ $VERBOSE ] && echo "$@"; "$@"; } ##function to echo then execute args; echoing only when Verbose-output wanted cd /tmp || exit ##==work in /tmp dir rm -f /tmp/$OUT* ##cleanup tmpfiles from previous runs if [ $PSDPI ];then ##==rescale image for use in EPS; not needed when jpeg end-result is wanted W=$(bc <<<"round($Win*$PSDPI)"); H=$(bc <<<"round($Hin*$PSDPI)") ##compute PS-imagesize in pixels as W by H; needs round,scale from my version of bc eDo scalepix -t0 -a0 -s${W}x$H -DISTORT -PR=$OUT $IMG ##rescale to WxH jpeg; -DISTORT option for exactly that size else cp -f $IMG $OUT-x.${IMG##*.} ##==conversion-less copy to /tmp/greetingcard-x.IMAGESUFFIX SZ=$(identify -format "%wx%h" $OUT-x.${IMG##*.}); W=${SZ%x*}; H=${SZ#*x} ##get PS-imagesize in pixels as W by H fi [ $VERBOSE ] && echo "pagesize:${Wpt}x$Hpt points == ${Win}x$Hin inches; PS-size:${W}x$H pixels; JPEG-size:${JW}x$JH pixels; IMG:$IMG; OUT:$OUT" for I in $OUT*${IMG##*.};do true;done ##get I the name of image to use in eps eDo sam2p -j:quiet $I ${I/%.*/.eps} ##==convert to eps-raster-image; had: -m:dpi:17.28 chgsed -n -q '1,/^%%Page:/d; /^end restore/,$cend restore' ${I/%.*/.eps} ##simplify sam2p-produced postscript; omit -n for debug { ##==produce Postscript-program with image and text... echo -e "%!PS-Adobe-3.0 EPSF-3.0\n%%Pages: 1\n%%BoundingBox: 0 0 $W $H" ##PS preamble for an EPS echo "/inch{72 mul}def /stfont{exch findfont exch scalefont setfont}def" ##PS functions needed for text echo "gsave 0 inch 0 inch translate %%${I/%.*/.eps}"; cat ${I/%.*/.eps}; echo "grestore" ##include sam2p-produced image-as-eps-rasterimage echo "1.000 1.000 1.000 setrgbcolor" ##PS code to set colour, to white echo "$(bc <<<"$W/$JW") dup scale" ##PS code to scale text for imgsize-independence for((J=0; J<${#X[*]}; J+=5))do echo "${X[J+0]} ${X[J+1]} moveto ${X[J+3]} ${X[J+2]} stfont (${X[J+4]})show";done ##lines of text } >$OUT.ps ##==produce PS result eDo ps2pdf -dAutoRotatePages=/None -dEPSCrop -g${W}x$H -r72 -dPDFSETTINGS=/printer $OUT.ps $OUT.pdf ##--and PDF result eDo convert -colorspace RGB -resize "${JW}x$JH!" -interlace none -density $DPI -quality 90 $OUT.ps $OUT.jpg ##==and JPEG result; add -verbose for debug echo "Greetingcard is available as: /tmp/$OUT.ps /tmp/$OUT.pdf /tmp/$OUT.jpg" ##tell user about the result choices ##rm -f $I ${I/%.*/.eps} ##no need to keep the tmpfiles exit 2010-12-18: in 2009-Dec, made Christmas-Card using TheGimp, as a 900x675 JPEG; added text with Gimp's Text-tool, in Champers-Plain font; previous Xmas-cards also made with Gimp; Consider: make 2 different layouts: one for e-viewing is half-page PDF/JPEG, other for printing + folding-in-half is full-page PDF?? the for-printing PDF version could be 2-sided with text on inside if to-be-printed-by-me; delivering 2-sided is dubious as too many ways to go wrong; have mixed feelings about delivering as full-page printable meant for fold-in-half, since that encourages printing... Decided: this script makes it in Postscript and uses imagemagick-convert to rasterize-to-JPEG; will deliver just one, the e-viewable JPEG; cmdline: convert -colorspace RGB -resize 900 -interlace none -density 120 -quality 90 $F ${F/pdf/jpg} (for 900px to be 8.5in means 105.9dpi) Size: 900x675 was for 1.33 aspect-ratio; half of letter-page marginless is 8.5x5.5 for 1.545 aspect-ratio, eg: 900x582; I like the 1.54 aspect-ratio, ideal for printing half-page-fullbleed onto letter-sized paper for one-fold "card" use, despite the jpeg-delivery decision; 2010 Christmas-Card: am using /pix/er100712/17308_erCCALTE.png which is 1166x759 aspect-ratio:1.54; will rescale to get 900x582 result; Note: in general this method will involve 2 re-scalings, first one when for making the EPS-raster-image, 2nd one when rasterizing the PS to make a JPEG; note: sam2p handles PNG => can ensure EPS is lossless; with the selected image, there's no reason to downsize when making EPS => total of one lossy conversion; note: were I delivering as PDF then I'd care about its filesize, but since desired end-product is JPEG I hardly care how big the PS/PDF "intermediates" are, so can avoid having two lossy operations. the PDF gets partial image, the bottom-left quarter roughly, but at a size of 1166x759?? final jpeg is 900x582; also getting errmsg from sam2p, it needs png22pnm; NOTE: found 2 versions of png22pnm, one a Linux-binary, other from source; SIZES DIFFER BY >FACTOR-OF-10: 232430 png22pnm-from-binary 16636 png22pnm-from-src; (1) errmsg from sam2p goes away after installing png22pnm, result unchanged -- using from-source version of png22pnm; (2) from-binary version of png22pnm gives same result; filesize of eps-result also identical; also same as with neither png22pnm despite errmsg in that case; NOTE: the pre-simplifying eps file (/tmp/greetingcard-x.eps~) can be opened by TheGimp -- for debugging; doing so shows that file is the entire image!! NOTE: only the PDF is wrong; doing convert-to-jpeg from PS gives entire photo (tho text too small); scrapped the PDF result since not needed; scaling to get desired text-size; 1166/900 is nowhere near 2, and yet that's what I get; added PS-scale for imgsize-indepenent dimensions; ie: added PS-scale-cmd to increase text-size by $W/900 (1.29 on this img), then increase all dimensions by factor of 2/that == 1.54 on this img; 2010-12-21 (after sending my 2010-xmas-ecard): revised Pagesize param; was for size of Paper being used with image being half that, now for the image; 842-->421; 792-->396; /2-->emptystring; supporting Portrait-mode photo seems more sensible this way; JPEG final-result is more sensible this way; added separate DPI params, one for the PS/PDF, another for the JPEG; $RESCALE-->$PSDPI; 300-->$PSDPI; 900-->$JW==$Win*$DPI; be warned: some combinations of the new params have never been tested; convert-cmdline: added its equivalent to scalepix's -sWxH -DISTORT which is exclamation-mark as in -resize WxH! now get the desired 900x582 result, was 900x586; sizing JPEG-result: its DPI-attribute ought to be ROUNDED-UP to integer (bc-ceil function), to print at 8.5-inches or LESS, never more; not crucial?? DPIceil=$(bc <<<"ceil($DPI)") ##compute DPIceil as DPI rounded-up to integer fixed the ps2pdf cmdline; and added -dPDFSETTINGS=/printer for it to use higher quality jpeg; ...=/prepress is its best quality-level; ==sizing the PS|PDF-results: need to add a scale-command and revise the bounding-box, making it be 8.5-inches wide or rather specified pagesize!!