%!PS-Adobe-3.1 % Poison Ivy in a Spray Can demo of nonlinear transforms % ====================================================== % Copyright c 2019 by Don Lancaster & Synergetics, Box 809, Thatcher, AZ, 85552 % (928) 428-4073 Email: don@tinaja.com Website: http://www.tinaja.com % Consulting services available http://www.tinaja.com/info01.html % All commercial rights and all electronic media rights ~fully~ reserved. % Linking usually welcome. Reposting expressly forbidden. Version 1.1 % A revision of our older Tuna Can transform that shows how to % use a triple JPEG-Grid-New Code layering to trace a document into % "raw" PostScript to create ultra compact, clean, sharp, colorized, and % simple text-searchible new code. % This differs from Meowwrr in that Meowrrr featured curvetracing, while % featuring nonlinear transformation of https://www.tinaja.com/glib/nonlingr.pdf % A gonzo tutorial is found at https://www.tinaja.com/glib/gonzotut.pdf % A PostScript Reference Manual at % % https://www.adobe.com/content/dam/acom/en/devnet/actionscript/articles/PLRM.pdf % A PostScript Video at https://www.youtube.com/watch?v=C_tWW560tAE % Not yet usable on Google Drive. Intended for acrobat distiller use via command % line //acrodist /F % IMPORTANT: Change these two lines to switch betweeen tracing code and any result! /want_to_trace { true } store /want_to_see_grid {true} store %%////// Extracted Gonzo Utilities ////// /mt {moveto} def /li {lineto} def /rm {rmoveto} def /rl {rlineto} def /ct {curveto} def /cp {closepath} def /f {fill} def /pd {0 exch neg rl} def /pr { 0 rl} def /pu {0 exch rl} def /pl {neg 0 rl} def /line1 {.06 dup setlinewidth 5 mul /erase exch def} def /line2 {.12 dup setlinewidth 5 mul /erase exch def} def /line3 {.18 dup setlinewidth 5 mul /erase exch def} def /thingridlines {0} def /setgrid { /blocksize exch def translate % simplified blocksize dup scale} def /showgrid {gsave /vblocks exch def /hblocks exch def thingridlines setlinewidth [{0 0 moveto 0 vblocks rlineto stroke} 1 hblocks 1 add] xrpt [{0 0 moveto hblocks 0 rlineto stroke} 1 vblocks 1 add] yrpt fatterborder { gsave newpath 0 0.96 blocksize div dtransform round idtransform setlinewidth pop 2 setlinecap 0 0 moveto hblocks 0 rlineto 0 vblocks rlineto hblocks neg 0 rlineto closepath stroke grestore} if fat5 { gsave newpath 0 0.48 blocksize div dtransform round idtransform setlinewidth pop mark {5 0 moveto 0 vblocks rlineto stroke} 5 hblocks 5 div cvi] xrpt mark {0 5 moveto hblocks 0 rlineto stroke} 5 vblocks 5 div cvi] yrpt grestore} if fatter10 { gsave 18 setwebtint % emphasize here newpath 0 0.96 blocksize div dtransform round idtransform setlinewidth pop mark {10 0 moveto 0 vblocks rlineto stroke} 10 hblocks 10 div cvi] xrpt mark {0 10 moveto hblocks 0 rlineto stroke} 10 vblocks 10 div cvi] yrpt grestore} if grestore} def /fatterborder {true } store /fat5 {true} store /fatter10 { true} store /showdots { false } store /dot { showdots { currentpoint newpath 0.150 0 360 arc fill }if} def /mdot { mt dot} def /random {rand 65536 div 32768 div mul cvi} def % as in -- 6 random -- /gonzofont {dup type cvlit /arraytype eq {exch findfont exch makefont} {exch findfont exch scalefont} ifelse setfont mark /spacewidth ( ) stringwidth pop /cstretch cvx /add cvx /sstretch cvx /add cvx /def cvx currentfont dup backcdict exch (F?) dup 1 14 index (xxxxx) cvs 4 get put put /setfont cvx ] cvx def} def 50 dict /backcdict exch def % used "backwards" during compiling to get % fontname given the "made" font dictionary /cstretch 0 store /sstretch 0 store % repeats [ proc distance trips] xrpt /xrpt{gsave aload pop /trips exch def /dist exch def /rproc exch def trips { gsave rproc grestore dist 0 translate } repeat grestore} def /yrpt{gsave aload pop /trips exch def /dist exch def /rproc exch def trips { gsave rproc grestore 0 dist translate } repeat grestore} def % timing utilities. use stopwatchon and stopwatchoff for simple % one shot timing. For multiple time totals, use resettimer % starttimer stoptimer ... starttimer stoptimer reporttimer /mergestr {2 copy length exch length add string dup dup 4 3 roll 4 index length exch putinterval 3 1 roll exch 0 exch putinterval} def /stopwatchoff {stoptimer reporttimer} def % for single shots /stopwatchon {resettimer starttimer} def % for single shots /reporttimer {mytime 1000 div (\rElapsed time: ) print 20 string cvs print ( seconds.\r) print flush} def % to host /resettimer {/mytime 0 def} def % reset timer /starttimer {usertime /mytimenow exch def} def % add to time so far /stoptimer {usertime mytimenow sub /mytime exch mytime add def} def % for multiple timing intervals % curvetrace - creates a smooth curved path from a data point list. % enter with currentpoint set and absolute array. % 0 0 as initial data appends path; any other values % creates new path /curvetrace {/curvelist exch def tension 0 eq {/tension .000001 def} if curvelist length 3 div 1 sub cvi /#triads exch def /ptr 0 def firstpoint morepoint} def /tension 2.83301 def % default value for best fit SLIGHTLY REVISED! /showtick false def % don't show points /ticklen 15 def % length of ticks /tickhead ticklen 4 div def /prvx { curvelist ptr 3 sub get } def /curx { curvelist ptr get } def /prvy { curvelist ptr 2 sub get } def /cury { curvelist ptr 1 add get } def /prva { curvelist ptr 1 sub get } def /cura { curvelist ptr 2 add get 180 sub} def /showtic1 { showtick true eq {gsave currentpoint newpath translate cura 180 add rotate ticklen neg 2 div 0 moveto ticklen 0 rlineto tickhead neg dup rlineto tickhead dup rlineto tickhead dup neg exch rlineto 0 setlinewidth stroke 0 ticklen neg 2 div moveto 0 ticklen rlineto stroke grestore} if }def /firstpoint { curx cury 2 copy abs exch abs add 0 eq {pop pop currentpoint curvelist exch 1 exch put curvelist exch 0 exch put}{moveto} ifelse showtic1 /ptr ptr 3 add def}def /morepoint {#triads { curx prvx sub dup mul cury prvy sub dup mul add sqrt tension div /zdist exch def prva cos zdist mul prvx add prva sin zdist mul prvy add cura cos zdist mul curx add cura sin zdist mul cury add curx cury curveto showtic1 /ptr ptr 3 add def} repeat} def /showtick false def % insert image proc /jpegimageprocwithlink { % hoffset voffset hres vres urlfrom urlto save /snap2 exch def /inurllink exch store % grab link filename /infilename exch store % grab passed pix file /photoscale exch store /vpixels exch store /hpixels exch store % (\nvpixels = )print vpixels == % (\nhpixels = )print hpixels == % (\photoscale = ) print photoscale == % (\ninurllink = ) print inurllink == % (\ninfilemane = ) print infilename == translate % adjust position for final figure ??? inurllink setareaurl % autolink sizing /DeviceRGB setcolorspace % pick color model 0 0 translate % set page position hpixels vpixels scale % magnify unit square photoscale dup scale /infile infilename (r) file def % establish input read file /Data {infile /DCTDecode filter} def % define a data source << % start image dicationary /ImageType 1 % always one /Width hpixels % JPEG width in pixels /Height vpixels % JPEG height in pixels /ImageMatrix [hpixels 0 0 vpixels neg 0 vpixels ] /DataSource Data % proc to get filtered JPEG /BitsPerComponent 8 % color resolution /Decode [0 1 0 1 0 1] % per red book 4.10 >> image % call the image operator ypos snap2 restore /ypos exch def } def /setareaurl { % for auto include routine /cururlname exch store mark % start pdfmark /Rect [ 0 0 hpixels photoscale mul vpixels photoscale mul ] /Border [ 0 0 0] % [0 0 0 ] = none; [0 0 2] = debug /Color [ .7 0 0 ] /Action <> /Subtype /Link /ANN % annotation type pdfmark % call pdf operators } def % ///////// (A) WEB FRIENDLY COLOR UTILITIES ///////////// % tintmat is a self-generating list of 216 triple color values /webtintmat [ 0 1 5 { /a exch store 0 1 5 { /b exch store 0 1 5 { 5 div b 5 div a 5 div }for } for } for ] def % setwebtint accepts a color number 0 to 215 and then % sets the PostScript color generator for later use... /setwebtint { abs cvi 216 cvi mod % restrict range webtintmat exch 3 mul 3 getinterval % get values from table aload pop setrgbcolor} def % and set them % The blocks are arranged as red to the right, green % up in order of increasing blue. % Some "pure color" sequences are % red: 0 1 2 3 4 5 % orange: 0 7 8 15 16 23 (sort of) % yellow: 0 7 14 21 28 35 % green: 0 6 12 18 24 30 % aqua: 0 42 84 126 168 210 % blue: 0 36 72 108 144 180 % magenta: 0 37 74 111 148 185 % purple 0 73 73 110 147 183 (sort of) % gray 0 43 86 129 172 215 % ///////////// DEMO /ypos 0 store % ////////////////////// want_to_trace { % code used by tracing program but not yet Google Drive compatible /imagelocaldirectory (C:/Users/don/Desktop/canal/images/) store % sin fwd slashes for win /imageremotedirectory (http://www.tinaja.com/canal/images/) store % sin fwd slashes for chrome /imageurl imageremotedirectory (prep1.jpg) mergestr store % goto remote image % /imagelocalsource imagelocaldirectory (prep1.jpg) mergestr store % /imagelocalsource (C:/Users/don/Desktop/google_drive/Meowrrr/meowwr1a.jpg) store /imagelocalsource (C:/Users/don/Desktop/google_drive/Ivy/ivyvid1.jpg) store gsave 66 100 % page translate ( data for jpegimageprocwithlink ) 946 1223 % hpixels and vpixels 0.445 % photoscale imagelocalsource % local jpg source imageurl % image url on clickthru jpegimageprocwithlink grestore } if /black {0 setwebtint} store /ypos 0 store % ////////////////////// 30 setwebtint % this puts a grid between tracer and tracee 50 50 10 setgrid want_to_see_grid { 50 62 showgrid % uncomment to show grid } if 0 setwebtint /bodycolor { 137 setwebtint } store % global color changes /darkerbodycolor { 59 setwebtint} store /stripecolor {45 setwebtint } store /debugcolor {5 setwebtint } store /batcolor { 212 setwebtint } store /batedgecolor { 192 setwebtint} store /glovecolor { 215 setwebtint } store /black {0 setwebtint} store /white {215 setwebtint } store /darkgrey { 86 setwebtint } store /heavyline {0.24 setlinewidth} store /lighterline {0.17 setlinewidth} store 1 setlinecap 1 setlinejoin %%%%%%%%%% can overlay % Rewritten code does the tuna can transform % tuna transform is % tilt constant k = (D/2) sin (theta) % x' = (D/2) sin (114.591 x/D) % y' = y - k cos (114.591 x/D) /tiltangle 33.8 def % forward tilt angle %%% %%% %%% /diam 26 def % major can diameter MUST be even! /allowfils {true} store % see what is underneath? /allowtrace {true} store % do a trace? ( distiller only ) /magick { diam 2 div tiltangle sin mul } def % special numble /xtransform { /xx exch store % MUST save for y!!!! diam 2 div 114.591 xx mul diam div sin mul } def /ytransform { /yy exch store yy magick 114.591 xx mul diam div cos mul sub } def % these procs can be rewritten to do most nonlinear transforms... /movetoproc {moveto} def /linetoproc {lineto} def /curvetoproc {curveto} def /closepathproc {closepath} def % initial movetoproc converts to a cruvetrace to try and minimize % corner cutting. Long horizontal lines should be done in segments. /movetoproc { 2 copy /lastymt exch store /lasty lastymt store % save close and cp /lastxmt exch store /lastx lastxmt store exch xtransform exch ytransform % x must go first! /moveto cvx} def /linetoproc { /y3 exch store /x3 exch store x3 lastx sub 3 div lastx add xtransform y3 lasty sub 3 div lasty add ytransform x3 lastx sub 3 div 2 mul lastx add xtransform y3 lasty sub 3 div 2 mul lasty add ytransform x3 dup /lastx exch store xtransform % save for currentpoint y3 dup /lasty exch store ytransform /curveto cvx } def /curvetoproc {/y3 exch store /x3 exch store % can use stack roll - nonobvious /y2 exch store /x2 exch store /y1 exch store /x1 exch store /lasty y3 store /lastx x3 store x1 xtransform y1 ytransform x2 xtransform y2 ytransform x3 xtransform y3 ytransform /curveto cvx } def /closepathproc { lastxmt lastx sub 3 div lastx add xtransform lastymt lasty sub 3 div lasty add ytransform lastxmt lastx sub 3 div 2 mul lastx add xtransform lastymt lasty sub 3 div 2 mul lasty add ytransform lastxmt xtransform lastymt ytransform /curveto cvx /closepath cvx } def % final close should be zero /remapit { mark {movetoproc} {linetoproc} {curvetoproc} {closepathproc} pathforall ] newpath cvx exec } def /fudge 3.1415926 2 div store % distance around can to diameter %%%%%%%%%%%%%%%%%%%%%%% /canfront { -13 fudge mul 0 mt 28.5 pu 13 {2 fudge mul pr } repeat 28.5 pd 13 {2 fudge mul pl } repeat remapit allowfils pop true { gsave 215 setwebtint fill grestore} if 0 setwebtint line3 stroke } def /outerring { -13 fudge mul 28.6 mt 13 26 add {2 fudge mul pr } repeat remapit allowfils { gsave 129 setwebtint fill grestore } if % when allowed 0 setwebtint line3 stroke }store /middlering { /diam 20 def % major can diameter MUST be even! -10 fudge mul 28.6 mt 10 20 add {2 fudge mul pr } repeat remapit allowfils { gsave 172 setwebtint fill grestore } if % when allowed 0 setwebtint line3 stroke }store /innerring { /diam 8 def % major can diameter MUST be even! -4 fudge mul 31.2 mt 4 12 add {1 fudge mul pr } repeat remapit allowfils { gsave 129 setwebtint fill grestore } if % when allowed 0 setwebtint line3 stroke }store /button { /diam 4 store -2 fudge mul 32.2 mt 4 {1 fudge mul pr } repeat remapit 4.55 pu 4 {-1 fudge mul pr } repeat remapit 4.5 pd allowfils pop false { gsave 176 setwebtint fill grestore } if % when allowed 5 setwebtint line3 stroke }store /buttontop { save /diam 4 store -2 fudge mul 36.8 mt 8 12 add {0.5 fudge mul pr } repeat remapit allowfils pop true { gsave 22 setwebtint fill grestore } if % when allowed 130 0 setwebtint line3 stroke restore } store /button2 { save /diam 4 store -2 fudge mul 36.7 mt 4.6 pd 8 {0.5 fudge mul pr } repeat remapit 4.6 pu allowfils pop true { gsave 0 setwebtint fill grestore } if % when allowed 130 0 setwebtint line3 stroke restore } store /nozzle {0 34.1 0.5 0 360 arc 22 setwebtint fill} store /lettering1 { /diam 26 store /font1 /StoneSans-Bold 7 gonzofont -13.5 12.3 moveto (POISON) false charpath remapit gsave 30 setwebtint fill grestore 0 setwebtint line3 stroke } store /lettering2 { /diam 26 store /font1 /StoneSans-Bold 7 gonzofont -6.0 6.4 moveto (IVY) false charpath remapit gsave 30 setwebtint fill grestore 0 setwebtint line3 stroke } store /lettering3 { /diam 26 store /HarlowSolid findfont 4.8 scalefont setfont 5 setwebtint -14.0 24 moveto (Swampfelder's) false charpath remapit 12 setwebtint fill } store /lettering4 { /diam 26 store /BookAntiqua-Bold findfont 1.8 scalefont setfont 1 setwebtint -6.0 20.5 moveto (INDUSTRIAL) false charpath remapit 0 setwebtint fill } store /lettering5 { /diam 26 store /BookAntiqua-Bold findfont 1.8 scalefont setfont 1 setwebtint -5.0 18.5 moveto (STRENGTH) false charpath remapit 0 setwebtint fill } store /lettering6 { /diam 26 store /BookAntiqua-Bold findfont 1.8 scalefont setfont 1 setwebtint -7.0 3.2 moveto (INSTA-SPRAY) false charpath remapit 0 setwebtint fill } store % ////// demo - remove or alter before reuse ///// 22.5 17.3 translate % have to center can %%% %%% %%%%%%%%%%%%%%%%%%%%% canfront outerring middlering innerring button2 buttontop nozzle lettering1 lettering2 lettering3 lettering4 lettering5 lettering6 % //////////// showpage %EOF