#!/bin/bash ## annotatepix -- by Eugene Reimer 2002-July; originally a separate script, then integrated into scalepix, ## separated again in 2008-11, when rewriting to: (1) eliminate use of convertOLD (long story), (2) and to get nicer anti-aliased text; ## USAGE EXAMPLE: ## annotatepix -f$Afont -a$Asize -c$Acolor -x$Amargin -y-$Aborder -t"$Atext" tmp$b-R.ppm <--from scalepix for Photog+Date at bottom; ## annotatepix -f$Afont -a$AsizeR -c$Acolor -x$Amargin -y$Atop -t"$Atext" tmp$b-R.ppm <--from scalepix for Nbr+Species at top; ## ## Copyright © 2002,2009 Eugene Reimer; can be used, modified, copied, and distributed or sold under the terms of either the LGPL or the GPL (your choice); ## see http://www.gnu.org/licenses for the details of these terms. USAGE='Usage: annotatepix [-f FONTNAME] [-a FONTSIZE] [-c FONTCOLOR] [-x X-COORD] [-y Y-COORD] [-t TEXT] PPM-PICTUREFILENAME' AT="$@" ##parsing cmdline options with getopt: if [[ $1 == -\? ]];then echo "$USAGE"; exit 0;fi ##because getopt doesn't support question-mark as a short-option TEMP=$(getopt -nannotatepix -o ha:c::f:t:x:y: --long help -- "$@"); if [ $? != 0 ];then echo "$USAGE"; exit 1;fi eval set -- "$TEMP" while [ $# -gt 0 ] && [[ $1 == -* ]];do ##parse options loop; same as before using getopt case "$1" in -a) SIZE=$2; shift 2;; -c) COLOR=$2; shift 2;; -f) FONT=$2; shift 2;; -t) TEXT=$2; shift 2;; -x) X=$2; shift 2;; -y) Y=$2; shift 2;; --) shift;break;; *) echo "$USAGE"; exit 2;; esac done IMG=$1; shift while [[ $TEXT == *\ ]];do TEXT=${TEXT%?}; done ##trim trailing spaces ##echo "CMDLINE:annotatepix $AT; FONT:$FONT; SIZE:$SIZE; COLOR:$COLOR; X:$X; Y:$Y; TEXT:$TEXT; IMG:$IMG;"; ##set -v ##DEBUG ##--Create annotation-text from a postscript-font, in B&W, making it say 5x (RRx) bigger than wanted: RR=4; RR_INV=0.250; ##RR replaces hard-coded scale-factor; was 4 RR=8; RR_INV=0.125; ##RR replaces hard-coded scale-factor; was 4, then 8 RR=5; RR_INV=0.200; ##RR replaces hard-coded scale-factor; was 4, then 8, then 5 ##mtextps -font=$FONT -fontsi=9 -r=$((72*RR*SIZE/9)) "$TEXT" >tmp$$CXUNCROPPED.pbm ##DEBUG to see pbmtextps output pbmtextps -font=$FONT -fontsi=9 -r=$((72*RR*SIZE/9)) "$TEXT" | ##resolution so after scaling by RR_INV will have fontsize:SIZE in pixels pnmcrop -left -white |pamcut -height=$((SIZE*RR)) >tmp$$CX.pbm ##want fixed height whether descendered or not; was just pnmcrop -white if [ $SPACEKLUGE ];then ##2009-10: YANKED after upgrading to netpbm-10.35.69 pbmtextps -font=$FONT -fontsi=9 -r=$((72*RR*SIZE/9)) "$TEXT " | pnmcrop -left -white |pamcut -height=$((SIZE*RR)) >tmp$$CXSPACE.pbm ##redo using TEXT+SPACE -- to get around pbmtextps's spurious "!" LN1=${#TEXT}; XW1=$(pnmfile tmp$$CX.pbm |gawk '{ print $4 }') XW2=$(pnmfile tmp$$CXSPACE.pbm |gawk '{ print $4 }') if ((LN1/2*2==LN1)) && ((XW10));then VA=top; ((CY-XH<2)) && ((CY=XH+2)); ((XY=CY)); fi ##on-top, adjustments ##echo "XW=$XW; XH=$XH; Y=$Y; CY=$CY; XY=$XY; VA=$VA;" ##DEBUG (output can be 'source'd for testcases-for-annotatepix) if [ "$COLOR" = "" ];then ##--Pick colour for annotation, based on lightness/darkness of that region: if ((X+XW>BW));then ((XW=BW-X)); fi ##2009-11-02: avoid trying to crop past right edge pamcut -w=$XW -h=$XH -l=$X -b=$CY $IMG >tmp$$C.ppm ##CROP the region to be overlaid with text, using pamcut NCHARS=${#TEXT}; ((NPX=NCHARS/2)); if ((NPX>17));then ((NPX=17));fi ##NPX was:5; 2008-02-28:nbrchars/2; 2009-10:kluge max 17 for single-line PGM pnmscale -xsize=$NPX -ysize=1 tmp$$C.ppm |ppmtopgm -plain >tmp$$C5plain.pgm ##reduce to $NPX pixels, as a plain-pgm { read; read; read; read -a PIX; ##BEWARE: NPX>17 leads to multiple lines -- not presently handled ((PALE=0)); for ((i=0; iPALE)) && ((PALE=PIX[i])); done; ((DARK=255)); for ((i=0; i=170));then ((K=(GG-170)*40/85));fi ##pick shade-of-BLACK: map GG=170..255 into K=0..40 fi COLOR=$(printf "#%02x%02x%02x" $K $K $K) ##repeat K thrice to make the RGB-COLOR, in hex if ((Y<0));then ##2010-05: only for on-bottom ##--darken/lighten the region where annotation-text is going, including 3px border ((DX=X-3, DW=XW+6, DH=XH+3)); pamcut -w=$DW -h=$DH -l=$DX -b=$CY $IMG >tmp$$Cb.ppm ##CROP region with 3px border on Left,Right,Top if ((K>128));then pamfunc -max=190 tmp$$Cb.ppm >tmp$$CB.ppm ##darken it; 200 not enough; 180 too much else pamfunc -min=110 tmp$$Cb.ppm >tmp$$CB.ppm; fi ##lighten it; 75 not enough; 100,128 close?? pamcomp -valign=bottom -xoff=$DX -yoff=$CY tmp$$CB.ppm $IMG >tmp$$CIMG; mv -f tmp$$CIMG $IMG ##replace that region in $IMG fi fi ##--Annotate the photo (using NetPBM antialiased text as of 2008-11-23): echo "##annotate: $Photo text:$TEXT size:$SIZE color:$COLOR palest:$PALE darkest:$DARK avg:$AVG gg=$GG" [[ -d /pix ]] && echo "$DATE: $Photo text:$TEXT size:$SIZE color:$COLOR palest:$PALE darkest:$DARK avg:$AVG gg=$GG" >>/pix/ANNOTATIONS ##==to /pix/ANNOTATIONS was /$PROJ pgmtoppm $COLOR-gray tmp$$CX.pbm >tmp$$CX.ppm ##remap colours in text-image producing PPM; gray pixels will become transparent pgmtoppm white-black tmp$$CX.pbm |ppmtopgm >tmp$$CX.pgm ##create transparency-mask; simpler way to do this: invert + pnmdepth?? pamstack -tupletype=RGB_ALPHA tmp$$CX.ppm tmp$$CX.pgm 2>/dev/null >tmp$$CXbig.pam ##pamstack needs PGM; the NetPBM-doc lies about taking PBM; noise msg... pamscale $RR_INV tmp$$CXbig.pam >tmp$$CXsma.pam ##rescale the RGB_ALPHA image; pamcomp -valign=$VA -xoff=$X -yoff=$XY tmp$$CXsma.pam $IMG >tmp$$CA.pam ##overlay the RGB_ALPHA image onto original $IMG, result is pam(rgba)!! pamtopnm tmp$$CA.pam >$IMG ##convert result to ppm; for general use support other formats?? rm -f tmp$$C*.p?m ##yank to debug with tmpfiles exit COLOR-PICKING troublesome cases: ================================ 2006-Feb: a troublesome photo bad with black,white,red... /pix/noci0602-Newsletter/PitcherPlant-Leaves-Zv210f_2002sep04_erCB.jpg 2006-May06: revised the first rule for picking black based on AVG; of 4 examples getting black, either 2 or 3 of them better with white: 09375_erCCB has avg:170 - am happy with black here (background is bright yellow); 09382_erCB has avg:160 - slightly better with white?? (is OK with either) 09388_erC has avg=143 - want WHITE annotation => revised above 09393_erB has avg:147 - want WHITE here too; 2006-Oct: another troublesome case: BookImageLOSN-Fig2_lh350.jpg palest:203 darkest:85 avg:155 - white is terrible!! black isn't great but better than white 2008-02-28: troublesome cases, with the annotation-options used by my send-photos... script: /pix/er080215/11986_hrB.jpg had palest:194 darkest:24 avg:70 -- want red, and got red with NPX=NCHARS/3; the next two needed NCHARS*2/5 to behave: /pix/er080215/11977_hrCB.jpg -- expected red; went from white to black after NPX mod; now has palest:207 darkest:67 avg:133 /pix/er080215/11983_hr.jpg -- expected red; and got red; now has palest:210 darkest:22 avg:60 -- NPX=NCHARS*2/5 was enough to get sensible results for today's examples; am going a little further, using: NPX=NCHARS/2 2008-09-02: 12864_erX1024.jpg color:white palest:197 darkest:129 avg:156 -- white is bad; could retune 1st or 2nd rule to get black, but black bad too!! need smaller pixels to detect that black also bad?? turns out red not great either, in fact white is best after all, just needed larger fontsize:-) 2008-11-26: used NEW (NetPBM) ANNOTATION code on InuvikTrip-slideshow before altogether ready -- gave me some testcases: /pix/noci08-InuvikTrip-Slideshow-Operashow/IT* --USED: scalepix -t0 -s780x555 /pix/noci08-InuvikTrip-Slideshow-Operashow/IT* ER13322 - chose black, not great; palest:181 darkest:146 avg:169 gg=157 ==NEEDED WAY MORE LIGHTENING(128); BORDER WILL HELP PB07510 - black is fine, but background NEEDS MORE LIGHTENING; ==HERE THE WAY-MORE(128) LOOKED OVERDONE-->110 DA00719 - chose black, black/white both dubious; palest:207 darkest:91 avg:158 gg=124 ==NOW GETTING WHITE ==NEEDED MORE DARKENING!! DA00721 - black is fine, but background NEEDS MORE LIGHTENING ==OK NOW DA00884 - chose black, WANT WHITE; palest:204 darkest:74 avg:116 gg=95; ==NOW GETTING WHITE, and OK DA00412 - chose white, a surprise; palest:196 darkest:120 avg:159 <--AVG right on the borderline... DA00672 - chose white, a surprise; palest:217 darkest:123 avg:160 <--is borderline DA00463 - chose black, a surprise; palest:183 darkest:141 avg:166 <--is borderline ER13145 - chose black, a surprise; palest:175 darkest:158 avg:165 <--is borderline PB06585 - chose black, a surprise; palest:182 darkest:145 avg:166 <--is borderline the shade-of-white picking looks to be mildly erratic, am toning down too much?? is clearly doing better than any single shade could; SUMMARY of Changes: black-vs-white now purely by AVG; darkening/lightening now unconditional w/o logging, more aggressive, includes border; redid: scalepix -t0 -s780x555 /pix/noci08-InuvikTrip-Slideshow-Operashow/IT*{PB07510,DA00721,DA00719,ER13322,DA00884}* ER12768,ER12938,DA00288,ER13045,ER13083,DA00402 ==TOO FAR OFF-WHITE; OK AFTER ADJUSTING; ER13959 ==THE DARKENING SEEMED EXCESSIVE - hue-preserving needed!! ==OK AFTER TWEAK; actually better with BLACK-ink, AVG 160/161 borderline CHANGE-LOG: =========== 2003-Sep: added intelligent ink-colour picking, based on background-colour in that region; with logging of annotation-info to ANNOTATIONS file (may be useful when fine-tuning the colour-picking); 2004-Jan: Fedora FC1, going from convert v5.0.27 to v5.5.6, broke this script in 2 ways: 1) the -crop option does something very different under new version of convert 2) the -draw option does nothing under new version of convert suspect both involve specifying geometry, possibly due to new -gravity ?? TEMP: using convertOLD (v5.0.27) for both cropping and annotating operations; ==may have been losing error-msgs due to 2>/dev/null -- should try again now that I've removed those redirections== ==consider switching to "pnm" routines everywhere?? 2005-Oct: Fedora FC4 again broke this script: 1) it came with a broken pnmtoplainpnm, which calls nonexistent pnmtopnm (fixed in /etc/sbin/pnmtoplainpnm by calling pamtopnm instead) 2) redid copying over of convertOLD, and its required libs: libMagick.so.5 and libpng.so.2; also its magick.mgk?? 2006-Sep: THE BETTER WAY: instead of cmdline piping into bash-code, using a bash-block with input-redirection avoids subshell creation, so vars work as wanted; eg: cat $F | while read;do...done --becomes--> while read;do...done <$F finally made the change in 2008-11, scrapping tmp$$.sh; note that can use -plain on any netpbm program!! 2008-02-28: use more pixels in the colour-picking (NPX==5-->NCHARS/2) -- was easy but the retuning may well be time-consuming; ==RETUNING== using more pixels will lead to more extreme values for both palest & darkest, hence, the 200 may need to go higher, the 55 lower, the 160 unchanged since average unaffected; ==SURPRISE: no such retuning needed==!!== 2008-02-28: for colour-picking crop: determine length of annotation-text and look at region that wide -- to properly handle long names and/or FULLDATE; using a guessed-at chars-to-pixels formula; ==note: going to pbmtextps method will make it trivial to get exact width-in-pixels; 2008-11-21: made this script, by isolating that part of the scalepix script; simplified the Annotation-logging, to always log to /pix/ANNOTATIONS (was to /$PROJ/ANNOTATIONS where $PROJ is the top-level of cwd); note: Annotation-logging needs $DATE $Photo -- now passed as exported vars; note: the pam-routines will/may need width & height of image -- pass as params?? NOPE, scalepix doesn't have handy until after annotation, tho it could have?? 2008-11-22: switched to pamcut to do the cropping; note: have been specifying the Y-coord to the Annotation-Text-BASELINE -- now simpler & more natural to specify to the BOTTOM of the text?? 2008-11-23 MUCH GRIEF WITH NetPBM ROUTINES: pbmtopgm: on PBM input can get PGM output, but it's not useful since it has maxval=1; pam routines can produce new format, known as rgb_alpha, but it is NOT viewable in The-Gimp; Jeez, such pam images don't even work as input to pnmtopng!! am forever getting maxval=1 results -- the whole philosophy of NetPBM seems wrongheaded, very different from ImageMagick's wrongheadedness, but is it better?? 'tis certainly more painful to use, but at least when it works then it usually works correctly (in my limited experience); both have sinned repeatedly by making incompatible changes, but NetPBM's such changes have caused much less grief, wasted way less of my time, etc; ==$#@!!==pamcomp said: pamcomp: There is no plain version of PAM. -plain option is not allowed <--What the Hell Can That Mean?? (I did not specify -plain) Found a bug-fix: 06.10.21 BJH Release 10.35.09 Fix pamcomp: due to use of undefined value, sometimes produces plain format Mine was v10.27.0; ==!!==UPGRADED VIA YUM, to get 10.33-1.FC4 -- not new enough to include that fix:-( Upgrading got rid of that errmsg -- now produces empty output w/o any msg -- that feels like negative progress--!!-- GODDAMM this is painful -- I'm starting to think that none of the PAM-programs work!! (hmm, pamcut is one that does work) THE GOOD NEWS: the upgrade brought me pamtotiff and pamrgbatopng (misnamed?) -- so now a pam-image can be converted to something useful; THE BAD NEWS: still no topam conversions from anything useful -- so there are very few possible ways of getting around buggy pam-routines!! GIMP: v2.2.13 is said to support PAM; my Gimp was 2.2.8; upgrading via yum got me 2.2.12 -- still fails to open PAM!! (1) the ALL-BLACK screwup after pamscale: the to-png conversions provide a clue: tmp--CXbig.pam has the text transparent -- was to be the background!! hmm, the doc is not altogether clear about whether one supplies Opacity or Transparency; in any event, have inverted to fix; ANOTHER BUG: on tmp--CXsma.pam, pamtopnm produces awful & misleading image, has maxval=255 yet is B+W (partial pixels became part of text => bad+over-bold); FORTUNATELY pamrgbatopng produces the correct image, and is viewable with Gimp; (2) back to the pamcomp bug: consider trying with both images as RGB_ALPHA-pam => convert $IMG to that?? correction: the output is not/no-longer empty, just misdiagnosed as such by non-pam-aware NetPGM routines => convert to PPM, but pamtopnm is broken?? SURPRISE: on the pamcomp-produced PAM, here pamtopnm works (HURRAH); however, this time pamrgbatopng does NOT!! TESTING NOTES: cmdline: cd /pix/er080918; rm tmp*; cp 14737_erCB.jpg tmp_erCB.jpg; scalepix -t0 -p720 tmp_erCB.jpg Note: temporarily revised all tmp$$xx-->tmp--xx to make debugging easier; pamtopnm tmp--CXbig.pam >tmp--CXbig.ppm; pamrgbatopng tmp--CXbig.pam >tmp--CXbig.png ##--convert pam to ppm & png to view in gimp pamtopnm tmp--CXsma.pam >tmp--CXsma.ppm; pamrgbatopng tmp--CXsma.pam >tmp--CXsma.png ##--convert pam to ppm & png to view in gimp -- only PNG worked here!! pamtopnm tmp--CA.pam >$IMG; pamrgbatopng tmp--CA.pam >tmp--CA.png ##--convert pam to ppm & png to view in gimp -- only PPM worked here!! 2008-11-23: switched to NetPBM (pbmtextps+pamscale+pamcomp) for annotation, because have long been fed up with ImageMagick changes, AND want antialiased text; using: pbmtextps to make a pbm that's bigger by 4x, then using pamscale to scale to rgb_alpha... FOR FONT_CHOICES: show-fonts-gs; After all that work I'm disappointed that the antialiased text seems a paltry improvement -- not sure it even justifies redoing all old photos:-( QUESTION: does pamscale produce antialiased pixels as (a) in $COLOUR but partially transparent; or (b) same color-mixing as w/o alpha-channel?? I've been assuming (a); the answer would be (a) with the view that a fully transparent pixel has no color, but who knows?? pam-plain is needed... OLD CODE (WITH HISTORY): ((CW=SIZE*NCHARS*100/173)) ##CW text-width-estimate obsoleted by netpbm-rewrite ((CY=1-Y-SIZE*25/60)) ##2008-02-28: CY=...*1/5-->2/5=24/60-->25/60 pamcut -w=$XW -h=$XH -l=$X -b=-$CY $IMG >tmp$$C.ppm ##CROP with pamcut, eg: annotate at y=-6 => crop at y=-2 (was y=-1 in convertOLD units) 2008-11-25: tried NPX==NCHARS/2-->NCHARS; BEFORE-and-AFTER stats (on /pix/er080918/14737_erCB.jpg): BEFORE: palest:83 darkest:68 avg:75 AFTER: palest:85 darkest:0 avg:68 <--expected palest slightly bigger, darkest slightly smaller, avg to remain unchanged, on average:-) AFTER: palest:90 darkest:0 avg:68 <--after switching to BOLD font AFTER: palest:83 darkest:68 avg:77 <--after YANKING; ie: really BEFORE, but with BOLD font which is slightly wider; yanked when it broke the computations (esp of DARK) -- because plain-format uses very short lines, ie: was getting two lines of data, expecting one; 2008-11-25: (1) SCRAP using RED when neither white nor black works; instead will DARKEN that region and use WHITE; (2) always use a BOLD font, but adjust the color based on contrast: white-->offwhite when contrast is good, etc; (first thought of switching between $FONT and $FONT-BOLD based on the contrast, but that would be messy because text-width would change); EG: on dark background (avg:68 palest:85), verdana-bold in #d0d0d0 (208,208,208) looks roughly equivalent to regular-verdana in WHITE; for COLOR==WHITE: gg:= avg of AVG,PALE, lower is better; gg=100..0: color:=255..208; <--wild guesses, will tune, see code above; gg>100: color:=255; darken, nothing >200; for COLOR==BLACK: gg:= avg of AVG,DARK, higher is better; gg=180..255: color:=0..32; <--wild guesses, will tune, see code above; gg<180: color:=0; lighten, nothing <55; Darkening/Brightening the region: use just a threshold -- pamfunc with -min/-max is close to what's needed ==WANTED: hue+sat left unchanged; with fuzzy edges: on a border around region, use a half-way threshold; better: several levels smoothly progressive <--may not need?? TESTCASES: /pix/er080918/14741_erC.jpg -- previously got red, altho white better except for last part where YEAR goes (Bold-Red was better but ...) /er/website/20080918: all photos; perfectly reasonable, altho not perfect: NOTE: my degrees-of-boldness experiments are illustrated in http://ereimer.net/programs/annotation.htm 2008-11-27: black-vs-white now decided purely by AVG; since after ignoring darkest<55 lightest>210 (lighten/darken will eliminate those), alg simplifies to that; OLD CODE (WITH HISTORY): if ((AVG>160)) && ((DARK>55));then COLOR=black ##was: AVG>180; 04aug:140; 06may:160; (DARK-comparand always same as 3rd rule) elif ((PALE <200));then COLOR=white ##was: 210; 06oct:200; 2008-11-27: now want 210 => use AVG alone... elif ((DARK >55));then COLOR=black ##was: 45; 06oct:55 else COLOR=red ##2008-11-25: now want white, and will darken the background... fi 2008-11-27: darkening/lightening now unconditional, and no longer logged; is also more aggressive; now includes border; the border for darkening/lightening region, is only on left,right,top -- bottom already has one since descenders are rare... now turfing all msgs from pamstack, altho only want rid of the noise msg "Writing 4 channel PAM image"; piping not available for stderr:-( fixed: for descender-less name (like Doris Ames) was getting the text lower than wanted, due to the cropping used in new method -- see CY, XY tidying below; fixed a bug in the setting of TEXTBG, when COLOR in hex; since bug didn't matter, did TEXTBG-->gray simplification; the (fixed) OLD CODE: TEXTBG=black ##TEXTBG completely useless if [[ ${COLOR:0:1} == "#" ]];then KK=16#${COLOR:1:2}; ((KK<99)) && TEXTBG=white ##set TEXTBG for hex color elif [[ $COLOR == black ]];then TEXTBG=white ##set TEXTBG for named color fi pgmtoppm $COLOR-$TEXTBG tmp$$CX.pbm >tmp$$CX.ppm ##change colours in text-image, producing an RGB-ppm 2008-11-28: went from 4x->8x, ie: from .25 scaling to .125 -- should get very slightly better antialiased pixels; toned down the off-white & off-black formulas; 180->190, 48->40; tidied up vars Y, CY, XY, and fixed sign-convention -- looked as though had long been broken for $Y param a positive-number (very rarely used); considered 3 ways of computing XY, but have yet to eliminate the guessed-at descender-height for computing CY: ((CY=Y-3+SIZE*25/60)) ##will crop at $CY = Y + (guessed-at) descender-height; need font-properties... ((XY=CY)); if [[ $TEXT != *[gjpqy]* ]];then ((XY=Y)); fi ##will place text at $XY; XY==CY if descendered, XY==Y if not ((XY=CY)); if ((XH upgrading is worth a try; sadly, their newest source package is too old ==> would need to grab the SubVersion source... ==tried to install Subversion according to http://netpbm.sourceforge.net/gettingsubversion.html -- DID NOT WORK!! ==made a bug-report, and a request for newer source package; tried trimming trailing spaces: the problem didnot go away, but now happened on different annotation-text (text previously had zero or two trailing spaces); also tried exactly one trailing space -- appears to mostly reverse the working<->nonworking cases, wrt zero spaces--!!-- KLUGY FIX: call pbmtextps twice (with zero,one trailing space), and use the narrower -- works for all images in BeautyInDiversity-slideshow!! OOPS: my first version of the kluge tried ONE,TWO trailing spaces; BUT IT ALSO WORKS after fixing to try ZERO,ONE; LENGTH OF ANNOTATION-TEXT: is there an odd/even explanation? is there a shortness explanation for those that work both ways? Even/Odd: when length odd then adding a space makes it worse; when even adding space makes it better -- if it changes that is... "drawing by Walter Mueller" length:25 works either way; "Steve Pschia" length:12 DOES NOT --NOTE: that means the buffer-overflow explanation is crap!! (assume its an oversimplification carried to the point of making no sense) cases that work either way are either odd & long, or even & very short?? eg: 19 fails with, 25 ok either way; 12 fails without, 8 ok either way; NOPE: the OK-EITHER-WAY cases include length 18, 16, 22, 8, BUT NOT 12; include 17, 25, BUT NOT 19; note: 3 common-lengths, the only ones I'd previously used: 19 for "Eugene Reimer YYYY", 16 for "Doris Ames YYYY", 26 for Peggy -- all work; COULD IMPROVE KLUGE: pad with spaces until length is ODD -- to avoid the two calls... based on my "len odd guess" being correct... BryanHenderson, response to my bug-report: ==ANSWER is to install Advanced tarball from: http://netpbm.sourceforge.net/release.html#tarball info on netpbm has changed?? now has links for Advanced & Development Tarballs (not just Super-Stable & Stable); gone are all version-nbrs?? ==AHA, I was previously looking at: http://sourceforge.net/project/showfiles.php?group_id=5128; what a confusing mess this is!! --2009-10-29: I was still using netpbm-v10.33 as installed 2008-nov24 -- see 2009-10-29 below; --2009-10-29: netpbm pages on sourceforge: the godawful mess has been fixed, altho leaving half of above links broken; 2009-10: BUG: using mk-calendar-8up-wallet-sized, annotation-text getting chopped at the end -- must be some length-limit--??-- eg: /pix/er-Calendar-Making-2009/ER06740-Polar-bear--and-cub-on-the-rocks_Churchill_20040717_erBCX.jpg --note it works at fontsize:18, gets chopped at fontsize:21 ==> chopping due to width-in-pixels, not nbr-chars!! --going to RR=5 from 8 did NOT change result ==> not exactly width-in-pixels either; must be width-in-postscript-points; --limit is in pbmtextps; it makes 3960x248 image when RR=5; ie: it makes fixed-pagesize output, 11-inches wide; ==NEW: to handle long caption: use constant fontsize==9, and resolution:72*RR*SIZE/9 -- avoids fractions, since 9 goesinto 72 -- 12,9,8,6,4,2,1 are candidates; --also tried fontsize==1, and resolution:72*RR*SIZE -- but it ran very very slowly, because the gs-page had more pixels?? went with fontsize:9 version; 2009-10-29: upgraded netpbm to current tarball 10.35.69 (2009-10-18); ==YANKED the pad-with-space-if-improves kluge, assuming it's no longer needed; 2009-11-02: prevent over-long annotation-text resulting in: pamcut:...right edge (900) that is beyond the right edge of the image (730); since things then ended badly -- indirectly led to clobbering input image, thru flaw in mk-calendar-8up-wallet-sized (discarding the tmp jpeg...) 2009-11-02: support negative X to mean centered; 2009-11-11: avoid writing to /pix/ANNOTATIONS if the dir /pix doesnot exist; 2009-11-21: added getopt to allow operand being either adjacent or as next-word; 2009-12-02: made -c take optional-opnd; this means caller must write opnd immediately after "-c", with no space between; revised calls in scalepix, mk-calendar-covers, testcases-for-annotatepix; reran mk-calendar-8up-wallet-sized to test (see mk-calendar-variants) 2010-05-08: tested & fixed on-top annotation;