%!PS % PS Bitmap "Swings and Tilts" Architect's Perspective Untilt 3.0 ghotilt1.psl % ================================================================ % by Don Lancaster % This NUTILT30.PSL does a swing and tilt only plus a FORCED white ( no pure red ) blocking % It has a new scaling that eliminates the distortion above 0.15 % and has been simplified and heavily revised. % "backwards" (stretch the top) subjects are currently treated by a double inversion and % thus may be somewhat longer executing %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /inputfilename (cylsmcchdk.bmp) store % name of file to be tilted /tiltoutfilename (cylsmcchdkt.bmp) store /filenameprefix (C:\\Users\\don\\Desktop\\Do Today\\) store % input and tiltout files must presently be in the same subdirectory /vtiltaxis 0.5 store % the VERTICAL position at which no tilt adjustment will be made. % Usually 0.5 on a strictly limited 0 to 1.0 range. 0 = left 1 = right /htiltaxis 0.5 store % the HORIZONTAL position at which no tilt adustment will be made. % best results are often at 0.5 /howmuchtilt 0.075 store % amount of tilt to correct for. Typical range is 0.06 to 0.12 .06 = 6%. % positive values compress top of image (usual). % negative values compress bottom of image (rarely needed) /correcttilt true store % flag to fix tilt /addcrosshairs false store % add a red crosshair to htiltaxis, vtiltaxis? /adjustdistortion false store % flag to attempt to adjust distortion /distadjadj 1.0 pop 5 store % distortion ratio adjust 1.0 tracks howmuchtilt %% To run this file, select START then RUN then Acrodist-F. Drag and drop into Distiller. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Copyright c 2003,2011 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.5 % PostScript-as-language utility reads a .BMP bitmap file and provides "view camera" % swing and tilt image distortion effects that make edges truly vertical. % To use, modify filenames and correction axis and percentage. Resave and send % to Acrobat Distiller USING "Acrodist-F" from the XP command line! % Alys run at highest possible resolution, preferably before any other post processing. % Some extreme left or right pixel columns may be lost during processing % and replaced by neighbor values. Pre-expand image if edge values are critical. % Several interpolations may be explored. Nearest neighbor should not be too much of a problem % if later reductions use bicubic elsewhere. % A "no Acrobat file produced" error is normal and expected. % ========= % IMPORTANT NOTE: Don Lancaster's file gonzo.ps is optional for this program. % After obvious location mods, uncomment ONE of the following two lines: % (C:\\Users\\Don\\Desktop\\Ghost\\gonzo.psl) run % run gonzo utilities % (C:\\Documents and Settings\\don\\Desktop\\gonzo\\gonzo.ps) run % use internal gonzo % (A:\\gonzo.ps) run % use external gonzo % NOTE THAT ALL PS FILENAME STRINGS !!!DEMAND!!! DOUBLE REVERSE SLASHES. % NOTE THAT DISTILLER DEMANDS EXECUTION FROM THE COMMAND LINE VIA "acrodist-F" % Otherwise most files can not be accessed % GONZO20A Guru Gonzo PostScript power tools (Interim release) % Includes gonzo justification and layout utilities. % Copyright c 1990, 1996, 2001, 2011 and later by Don Lancaster and Synergetics, Box 809, % Thatcher Arizona, 5552 (928) 428-4073 don@tinaja.com support % via http://www.tinaja.com All commercial rights and all electronic % media rights **FULLY** reserved. Reposting is expressly forbidden. % ======== /guru { gonzo begin ps.util.1 begin printerror nuisance begin} def % guru % activate gonzo utilities % ========= % gonzo excerpts /mt {moveto} store /black {0 setgray} store % timing utilities. use stopwatchon and stopwatchoff for simple % one shot timing. For multiple time totals, use resettimer % starttimer stoptimer ... starttimer stoptimer reporttimer /stopwatchoff {stoptimer reporttimer} def % for single shots /stopwatchon {resettimer starttimer} def % for single shots /reporttimer {mytime 1000 div (\nElapsed time: ) print 20 string cvs print ( seconds.\n) 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 % mergestr merges the two top stack strings into one top stack string /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 % [yourarray] makestring converts an array to a string... /makestring {dup length string dup % new string of right size /NullEncode filter % make a file out of string 3 -1 roll {1 index exch write} forall pop } def /random {rand 65536 div 32768 div mul cvi} def % as in -- 6 random -- % no longer used %%%%%%%%% end gonzo excerpts % ========= % define connecting files /sourcefilename filenameprefix inputfilename mergestr store /targetfilename filenameprefix tiltoutfilename mergestr store /readfile sourcefilename (r) file store % establish input read file /writefile targetfilename (w+) file store % establish output target file %%%%%%%%%%% /showtime true store % show annotation? /bitsperpixelposition 28 store % These are .BMP header offset params /datastartposition 10 store /horizontalpixels 18 store /verticalpixels 22 store % % deal with possible reverse tilt... howmuchtilt 0 ge {false}{true} ifelse % set reverse=true flag /reversetilt exch store /howmuchtilt howmuchtilt abs store % and leave howmuchtilt positive %%% temporary new dictionary for ghostscript??? 5000 dict /newdict exch store newdict begin % does this help? %%%%%%%%%%%%%%%% DISK ACCESS SERVICE ROUTINES %%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%% CHECK FOR VALID 24-BIT UNCOMPRESSED BITMAP %%%%%%%%%%%%% % BM check: readfile (XX) readstring pop % error message if file not two chars long (BM) eq {(File has correct "BM" as first two bytes.\n) print } { sourcefilename ( is not in .BMP format; further eval terminated.\n\n\n) mergestr print quit } ifelse % 24 bit check: readfile bitsperpixelposition setfileposition % access 2 {readfile read pop} repeat % get color planes error if not present 1 {256 mul add} repeat % calculate bits per pixel dup /bpp exch store % save for expanded analysis 10 string cvs % make string (24) eq {(File has correct 24-bit color format.\n) print } { sourcefilename ( is not in 24-bit format; further eval terminated.\n\n\n) mergestr print quit } ifelse % Compression mode: 4 {readfile read pop} repeat % get color planes error if not present 3 {256 mul add} repeat % calculate compression mode dup /cmm exch store % save for expanded analysis 10 string cvs % make string (0) eq {(File has correct 0 uncompressed format.\n) print } { sourcefilename ( is not in uncompressed format; further action terminated.\n\n\n) mergestr print quit } ifelse % Bitmap Width: readfile horizontalpixels setfileposition % access 4 {readfile read pop} repeat % get bitmap width bytes error if not present 3 {256 mul add} repeat % calculate data start dup /hres exch def 10 string cvs % make string showtime { (Bitmap width is ) exch mergestr ( pixels.\n) mergestr print flush } if % Bitmap Width: readfile verticalpixels setfileposition % access 4 {readfile read pop} repeat % get bitmap width bytes error if not present 3 {256 mul add} repeat % calculate data start dup /vres exch def 10 string cvs % make string showtime { (Bitmap height is ) exch mergestr ( pixels.\n) mergestr print flush } if % Find padding % .BMP rows MUST end on a 32-bit boundary! Zero, one, two, or three 00 % padding bits are required depending upon the actual width. /padding hres 3 mul cvi 4 mod % find start of next 32-byte block [ 0 3 2 1 ] exch get % TLU correction def (Padding 8-bit bytes per line are ) padding 10 string cvs mergestr ( .\n\n) mergestr print flush (Active storage 8-bit RGB bytes per line are ) hres 3 mul dup cvi /activestore exch store 10 string cvs mergestr ( .\n) mergestr print flush activestore 4 div ceiling cvi 4 mul /totalbytesperline exch store % find data start readfile datastartposition setfileposition % access 4 {readfile read pop} repeat % get data start bytes error if not present 3 {256 mul add} repeat % calculate data start /actualdatastart exch store % define read strings /linestring hres 3 mul string store % read file line buffer %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % (A) BITMAP FILE CAPTURE ROUTINE /grabbitmap % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % /grabbitmap reads a disk file and converts its underlying bitmap to % a PostScript /instrarray image array of STRINGS. Each horizontal line % is one subarray, and the arrays build from the image BOTTOM UPWARDS... % In general, PostScript strings can be manipulated as arrays without % needing the overhead of string to array or array to string conversion. % The speed savings can be quite significant. % This is normally the FIRST step in any image manipulation. % Note that there is NO PADDING in instrarray. /grabbitmap { showtime { (\nReading initial bitmap from disk...) print flush } if -2 vmreclaim /instrarray mark % start input data array 0 = bottom 0 1 vres 1 sub { % begin line reading loop /vline exch store % start of next hires line vline hres 3 mul padding add mul actualdatastart add % position read file readfile exch setfileposition readfile linestring readstring % grab a line of characters not {Error_reading_input_file_data} if % error trap dup length string cvs % must dereference } for ] store % complete instrarray definition 2 vmreclaim 0 vmreclaim } store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % (C) BITMAP FILE STORAGE ROUTINE /savebitmap % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % /savebitmap saves the internal PostScript /outarray to disk in % the .BMP format a chosen disk file. % This is normally the LAST step in any image manipulation. % Note that input and output files can be different sizes for certain % operations such as cropping or rotations. % This version resaves the input string %%%%%%%%%%%%%%%% COPY HEADER TO TARGET FILE %%%%%%%%%%%%%%%%%% % The entire old header gets reused. outwidth and outlength is then % overwritten. /writeoutfileheader { readfile datastartposition setfileposition % access 4 {readfile read pop} repeat % get data start bytes error if not present 3 {256 mul add} repeat % calculate data start /actualdatastart exch store readfile 0 setfileposition readfile actualdatastart 1 sub string readstring not { sourcefilename ( has a short header; further action terminated.\n\n\n) mergestr print quit } if writefile exch writestring % write the entire header to new file writefile actualdatastart setfileposition % go to end of header } store % this version of savebitmap assumes it is the same size as the original /savebitmap { showtime {(\nSaving processed bitmap image to disk...) print flush } if instrarray length /outlength exch store % find output pixelslength instrarray 0 get length 3 div cvi % find output pixels width /outwidth exch store % note three RGB bytes per pixel writeoutfileheader % write the outfile header 0 1 instrarray length 1 sub { % for each data line instrarray exch get % get data line as string dup length 4 mod % add padding if needed dup 0 gt {[ (xxx) threepad twopad onepad] exch get mergestr}{pop}ifelse writefile exch writestring } for } store /onepad [ 0 ] makestring store % null padding strings used by /savebitmap /twopad [0 0] makestring store /threepad [ 0 0 0 ] makestring store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % (P) Revised Architect's Perspective /untilt % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%% new routine to minimize barrel distortion %%%%%%%%%%%%% % /calccurrowscale finds the current row shift /crs factor, given vfract and howmuchtilt % This subtle math gets executed once per row. /calccurrowscale {/crs 1 dup howmuchtilt 2 mul % define a new current row scale sub div 1 sub vfract reversetilt {1 exch sub} if % backwards if negative mul 1 add store /crs- crs neg store % may need for sneakiness } store %%%%%%%%%%%%%%%%% % /processrows normally compresses in the northwest and northeast and epands in the southwest and southeast % for a positive howmuchtilt /processrows { -2 vmreclaim % avoid excessive garbage collection % temp gs dictionary test here 20000 dict /newdict exch store newdict begin /woof 12345 store /howmuchtilt2 howmuchtilt 2 mul store % half adjust for half screen /max1 instrarray 0 get length 3 sub store % simplify for later /reverse howmuchtilt 0 le {true}{false} % flag for reverse (squash bottom) operation ifelse store /centerrow instrarray length htiltaxis % define center row for zero adjustment mul round cvi store /neut max1 vtiltaxis mul % find neutral vertical axis 1.5 add cvi 3 idiv 3 mul store % adjusted to nearest whole pixel northeast % treat each quadrant separately northwest southeast southwest 2 vmreclaim } bind store % the quadrants have to adjust for positive or negative corrections and for positive or negative data change fillin % underflows and overflows are precalculated to eliminate tests in inside loop /southwest { 0 1 centerrow { % build from bottom to center /currownum exch store % save ABSOLUTE row number /currowstring instrarray currownum get store % get current row string 0 3 neut {dup dup neut exch sub % begin pixel loop howmuchtilt2 mul currownum centerrow sub neg instrarray length div mul add 1.5 add cvi 3 idiv 3 mul % adjusted to nearest whole pixel currowstring exch dup 0 le {pop 0} if % bug trap? 3 getinterval % dup 2 139 put % attempt to discolor currowstring 3 -2 roll putinterval } for % end pixel fillin loop } for % end each row loop } bind store /southeast { 0 1 centerrow % pop pop pop centerrow 150 sub 1 centerrow { % build from bottom to center /currownum exch store % save ABSOLUTE row number % (\nsoutheast currownum is now ) print flush currownum == /currowstring instrarray currownum get store % get current row string instrarray 0 get length 3 sub -3 neut { % ( sepixel is ) print flush dup == dup dup neut exch sub % begin pixel loop howmuchtilt2 mul currownum centerrow sub neg instrarray length div mul add 1.5 add cvi 3 idiv 3 mul % adjusted to nearest whole pixel currowstring exch dup 0 le {pop 0} if % bug trap? 3 getinterval % dup 1 139 put % try to discolor? currowstring 3 -2 roll % currownum centerrow eq {pop (2K2) } if % currownum centerrow 149 sub eq {pop (2K2) } if putinterval } for % end pixel fillin loop } for % end each row loop } bind store %%%%%%%%%%%%%%% northwest /northwest { centerrow 1 instrarray length 1 sub { % build from center to top /currownum exch store % save ABSOLUTE row number /currowstring instrarray currownum get store % get current row string { /uprowcount currownum centerrow sub store % how many rows up from center? /uprowcountfract uprowcount % fraction of total updistance? instrarray length uprowcount sub % can be simplified but more obtuse div store neut howmuchtilt2 mul uprowcountfract mul /maxpixelshift exch store % maximum pixel shift for west end of this row } pop /nemaxuse neut howmuchtilt mul store /nefract currownum centerrow sub instrarray length 1 sub centerrow sub div store /maxpixelshift nemaxuse nefract mul store { (\n\ncurrownum is now ) print flush currownum == % (newide is now ) print flush newide == (nemaxuse is now ) print flush nemaxuse == (nnefract is now ) print flush nefract == (maxpixelshift is now ) print flush maxpixelshift == } pop neut -3 maxpixelshift {dup dup neut exch sub % start pixel fillin loop howmuchtilt2 mul currownum centerrow sub instrarray length div mul neg add 1.5 add cvi 3 idiv 3 mul % adjusted to nearest whole pixel currowstring exch { dup 100 le { (\nnorthwest oldpixel is now )print flush dup == } if } pop dup 0 le {pop 0} if % bug trap? 3 getinterval % dup 0 209 put % try to discolor? currowstring 3 -2 roll putinterval } for % end pixel fillin loop } for % end each row loop } bind store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /northeast { centerrow 1 instrarray length 1 sub { % build from center to top (\nnortheast currow mum is now ) print flush dup == /currownum exch store % save ABSOLUTE row number /currowstring instrarray currownum get store % get current row string { /uprowcount currownum centerrow sub store % how many rows up from center? /uprowcountfract uprowcount % fraction of total updistance? instrarray length uprowcount sub % can be simplified but more obtuse div store neut howmuchtilt2 mul uprowcountfract mul /maxpixelshift exch store % maximum pixel shift for west end of this row } pop /newide instrarray 0 get length neut sub store /nemaxuse newide howmuchtilt mul store /nefract currownum centerrow sub instrarray length 1 sub centerrow sub div store /maxpixelshift nemaxuse nefract mul 6 sub store % /maxpixelshift { maxpixelshift dup 0 le {pop 0 } if } store { (\n\ncurrownum is now ) print flush currownum == (newide is now ) print flush newide == (nemaxuse is now ) print flush nemaxuse == (nnefract is now ) print flush nefract == (maxpixelshift is now ) print flush maxpixelshift == } pop neut 3 instrarray 0 get length 57 sub maxpixelshift sub {dup dup neut exch sub % start pixel fillin loop howmuchtilt2 mul currownum centerrow sub instrarray length div mul neg add 1.5 add cvi 3 idiv 3 mul % adjusted to nearest whole pixel currowstring exch dup 0 le {pop 0} if % bug trap? 3 getinterval % dup 2 85 put % attempt to discolor for debug currowstring 3 -2 roll putinterval } for % end pixel fillin loop } for % end each row loop } bind store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /untilt { stopwatchon grabbitmap % build line by line RGB PS strings (\ngrabbing bitmap took ) print flush stopwatchoff /neut instrarray 0 get length 1 sub % find neutral pixel position vtiltaxis mul round cvi 3 idiv 3 mul store % must be a triad group edge reversetilt { stopwatchon flipimagevertically (\nflipping image took ) print flush stopwatchoff } if correcttilt { stopwatchon processrows % correct one line at a time (\n processing rows took ) print flush stopwatchoff } if adjustdistortion { stopwatchon fixdistortion % attempt full image distortion correction (\n attempting to fix distortion took ) print flush stopwatchoff } if addcrosshairs { stopwatchon addcrosshair (\nadding a crosshair took ) print flush stopwatchoff } if reversetilt { % second image flip if top needs expanded stopwatchon flipimagevertically (\nflipping image took ) print flush stopwatchoff } if stopwatchon savebitmap % rewrite bitmap (\nsaving bitmap took ) print flush stopwatchoff } store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % (K) Image Inversion for top compression /flipimagevertically % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % most perspective corrections involve compressing the top and % expanding the bottom. The rare reverse case can be done by a double % flip involving somewhat longer processing times. /flipimagevertically { /cenrow instrarray length % find center row or just lower 2 div floor cvi store 0 1 cenrow {/curlowrow exch store % present low row /curhighrow instrarray length 1 sub % and companion high row curlowrow sub store instrarray curlowrow get instrarray curhighrow get instrarray exch curlowrow exch put instrarray exch curhighrow exch put } for } store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % (L) Adjust Distortion % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % attempts to use table lookup to move intermediate rows up. % Table lookup based on 0.5 distortion correction for 800 rows of right diagonal... /distadj [ 0.000 0.500 1.000 1.499 1.997 2.495 2.992 3.488 3.984 4.480 4.974 5.461 5.962 6.454 6.946 7.438 7.928 8.419 8.908 9.397 9.885 10.37 10.86 11.34 11.83 12.31 12.80 13.28 13.76 14.24 14.73 15.21 15.69 16.17 16.65 17.12 17.60 18.08 18.56 19.03 19.51 19.98 20.45 20.93 21.40 21.87 22.34 22.81 23.28 23.75 24.22 24.69 25.15 25.62 26.08 26.55 27.01 27.48 27.94 28.40 28.86 29.32 29.78 30.24 30.70 31.16 31.61 32.07 32.52 32.98 33.43 33.89 34.34 34.79 35.24 35.69 36.14 36.59 37.04 37.49 37.93 38.38 38.83 39.27 39.71 40.16 40.60 41.04 41.48 41.92 42.36 42.80 43.24 43.68 44.11 44.55 44.98 45.42 45.85 46.28 46.72 47.15 47.58 48.01 48.44 48.86 49.29 49.72 50.14 50.57 50.99 51.42 51.84 52.26 52.68 53.10 53.52 53.94 54.36 54.78 55.19 55.61 56.01 56.44 56.85 57.26 57.67 58.09 58.50 58.90 59.31 59.72 60.13 60.53 60.94 61.34 61.75 62.15 62.55 62.95 63.35 63.75 64.15 64.55 64.95 65.34 65.74 66.13 66.53 66.92 67.31 67.70 68.09 68.48 68.87 69.26 69.64 70.03 70.41 70.80 71.18 71.57 71.95 72.33 72.71 73.09 73.47 73.84 74.22 74.59 74.97 75.34 75.72 76.09 76.46 76.83 77.20 77.57 77.94 78.30 78.67 79.03 79.40 79.76 80.12 80.48 80.85 81.20 81.56 81.92 82.28 82.63 82.99 83.34 83.70 84.05 84.40 85.10 85.45 85.80 86.14 86.49 86.83 87.18 87.52 87.86 88.20 88.54 88.88 89.22 89.56 89.89 90.23 90.56 90.90 91.23 91.56 91.89 92.22 92.55 92.88 93.20 93.53 93.85 94.18 94.50 94.82 95.14 95.46 95.78 96.10 96.41 96.73 97.04 97.36 97.67 97.98 98.29 98.60 98.91 99.22 99.53 99.83 100.1 100.4 100.7 101.0 101.3 101.6 101.9 102.2 102.5 102.8 103.1 103.4 103.7 104.0 104.2 104.5 104.8 105.1 105.4 105.7 106.0 106.2 106.5 106.8 107.1 107.4 107.6 107.9 108.2 108.5 108.7 109.0 109.3 109.5 109.8 110.1 110.3 110.6 110.9 111.1 111.4 111.7 111.9 112.2 112.4 112.7 112.9 113.2 113.4 113.7 114.0 114.2 114.4 114.7 114.9 115.2 115.4 115.7 115.9 116.1 116.4 116.6 116.9 117.1 117.3 117.6 117.8 118.0 118.3 118.5 118.7 118.9 119.2 119.4 119.6 119.8 120.0 120.3 120.5 120.7 120.9 121.1 121.3 121.5 121.7 122.0 122.2 122.4 122.6 122.8 123.0 123.2 123.4 123.6 123.8 124.0 124.2 124.4 124.5 124.7 124.9 125.1 125.3 125.5 125.7 125.8 126.0 126.2 126.4 126.6 126.7 126.9 127.1 127.3 127.4 127.6 127.8 127.9 128.1 128.3 128.4 128.6 128.7 128.9 129.1 129.2 129.4 129.5 129.7 129.8 130.0 130.1 130.3 130.4 130.6 130.7 130.8 131.0 131.1 131.2 131.4 131.5 131.6 131.8 131.9 132.0 132.2 132.3 132.4 132.5 132.6 132.8 132.9 133.0 133.1 133.2 133.3 133.4 133.6 133.7 133.8 133.9 134.0 134.1 134.2 134.3 134.4 134.5 134.6 134.6 134.7 134.8 134.9 135.0 135.1 135.2 135.1 135.3 135.4 135.5 135.6 135.6 135.7 135.8 135.8 135.9 136.0 136.0 136.1 136.2 136.2 136.3 136.3 136.4 136.4 136.5 136.5 136.6 136.6 136.7 136.7 136.7 136.8 136.8 136.9 136.9 136.9 137.0 137.0 137.0 137.0 137.1 137.1 137.1 137.1 137.1 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.2 137.1 137.1 137.1 137.1 137.1 137.0 137.0 137.0 137.0 136.9 136.9 136.8 136.8 136.8 136.7 136.7 136.6 136.6 136.5 136.5 136.4 136.4 136.3 136.3 136.2 136.2 136.1 136.0 136.0 135.9 135.8 135.7 135.7 135.6 135.5 135.4 135.1 135.3 135.2 135.1 135.0 134.9 134.8 134.7 134.6 134.5 134.4 134.3 134.2 134.1 134.0 133.8 133.7 133.6 133.5 133.4 133.2 133.1 133.0 132.9 132.7 132.6 132.4 132.3 132.2 132.0 131.9 131.7 131.6 131.4 131.3 131.1 131.0 130.8 130.6 130.5 130.3 130.1 130.0 129.8 129.6 129.4 129.2 129.1 128.9 128.7 128.5 128.3 128.1 127.9 127.7 127.5 127.3 127.1 126.9 126.7 126.4 126.2 126.0 125.8 125.6 125.1 125.1 124.9 124.6 124.4 124.2 123.9 123.7 123.4 123.2 122.9 122.7 122.4 122.2 121.9 121.7 121.4 121.1 120.8 120.6 120.3 120.0 119.7 119.5 119.2 118.9 118.6 118.3 118.0 117.7 117.4 117.1 116.8 116.5 116.2 115.8 115.5 115.2 114.9 114.6 114.1 113.9 113.6 113.2 112.9 112.6 112.2 111.9 111.5 111.2 110.8 110.4 110.1 109.7 109.3 109.0 108.6 108.2 107.8 107.5 107.1 106.7 106.3 105.9 105.5 105.1 104.7 104.3 103.9 103.5 103.1 102.7 102.2 101.8 101.4 101.0 100.5 100.1 99.70 99.26 98.82 98.37 97.92 97.47 97.01 96.55 96.09 95.62 95.15 94.68 94.21 93.73 93.25 92.76 92.27 91.78 91.29 90.79 90.29 89.79 89.28 88.77 88.25 87.74 87.22 86.69 86.16 85.63 85.10 84.56 84.02 83.48 82.93 82.38 81.82 81.27 80.70 80.14 79.57 79.00 78.42 77.85 77.26 76.68 76.09 75.11 74.90 74.30 73.69 73.09 72.48 71.86 71.24 70.62 70.00 69.37 68.73 68.10 67.46 66.81 66.17 65.51 64.86 64.20 63.54 62.87 62.20 61.53 60.85 60.17 59.48 58.79 58.10 57.40 56.70 55.99 55.28 54.57 53.85 53.13 52.41 51.68 50.94 50.21 49.47 48.72 47.97 47.22 46.46 45.70 44.93 44.16 43.39 42.61 41.83 41.04 40.25 39.45 38.65 37.85 37.04 36.23 35.41 34.59 33.76 32.93 32.10 31.26 30.42 29.57 28.72 27.86 27.00 26.13 25.26 24.39 23.51 22.62 21.74 20.84 19.94 19.04 18.14 17.22 16.31 15.39 14.46 13.53 12.59 11.65 10.71 9.764 8.810 7.851 6.887 5.917 4.944 3.965 2.981 1.992 0.991 0.000 ] store /fixdistortion { instrarray length 1 sub -1 0 { % work down from top /curnewrow exch store % scale to lookup curnewrow curnewrow instrarray length div distadj length mul floor cvi dup 800 ge {pop 799} if distadj exch get howmuchtilt 0.5 div mul % scale to adjustment distadjadj mul % optional fudge round cvi /adj exch store instrarray curnewrow adj sub get instrarray exch curnewrow exch put } for } store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % % % (M) Adding an optional crosshair at vtiltaxis htiltaxis % % % %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% /addcrosshair { (\nstarting to add crosshair ) print flush /redpix (xxx) store redpix 2 250 put redpix 1 0 put redpix 0 0 put /absvtiltaxis {instrarray length htiltaxis mul round cvi } store (\n\ninstrarray length is ) print flush instrarray length == (vtiltaxis is ) print flush vtiltaxis == (absvtiltaxis is ) print flush absvtiltaxis == (\n\n\n==============================\n\n) print flush /abshtiltaxis {instrarray 0 get length vtiltaxis mul 1.5 add cvi 3 idiv 3 mul % adjusted to nearest whole pixel } store (\abstiltaxises are ) print flush absvtiltaxis == ( and ) print flush abshtiltaxis == (\nredpix as integers is ) print flush redpix {==} forall absvtiltaxis 50 sub dup 0 lt {pop 0} if 1 absvtiltaxis 50 add dup instrarray length 1 sub ge {pop instrarray length 1 sub} if {/curvpix exch store (\ncurvpix is now ) print flush curvpix == instrarray curvpix get abshtiltaxis redpix putinterval } for abshtiltaxis 50 3 mul sub dup 0 lt {pop 0} if 3 abshtiltaxis 50 3 mul add dup instrarray 0 get length 1 sub ge {pop instrarray length 1 sub} if % (\n curhpix range is ) print flush 3 copy == == == % (\n\n) print flush { /curhpix exch store % curhpix == % absvtiltaxis == instrarray absvtiltaxis get curhpix redpix putinterval } for } store %%%%%%%%%%% demo - alter above values before reuse %%%%%%%%%%%%%%%%% % stopwatchon untilt % this does it all % stopwatchoff (\nFinished.\n) print % report readfile closefile writefile closefile % EOF