%!PS % Two PostScript Pixel Interpolation Routines % =========================================== % by Don Lancaster PIXINTPL1.PSL %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Copyright c 2003 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 % ========= % IMPORTANT NOTE: Don Lancaster's file gonzo.ps is recommended for this program. % After obvious location mods, uncomment ONE of the following two lines: (C:\\Documents and Settings\\don\\Desktop\\gonzo\\gonzo.ps) run % use internal gonzo % (A:\\gonzo.ps) run % use external gonzo % At present, Gonzo is not required for the actual interpolation routines % but the setgrid/showgrid procs are required for the graphic demos and % the stopwatchon/off procs for the timing demos % NOTE THAT ALL PS FILENAME STRINGS !!!DEMAND!!! DOUBLE REVERSE SLASHES. % GONZO20A Guru Gonzo PostScript power tools (Interim release) % Includes gonzo justification and layout utilities. % Copyright c 1990, 1996, 2001 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. % Stopwatch routines excerpted from the Gonzo Utilities... %%% excerpted gonzo routines % 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 (\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 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% A pair of partially optimized pixel interpolation algorithms appears here. %% The faster one does a bilineal interpolation; the beter one a bicubic %% interpolation. The latter is typically slower by a factor of 10 but still usable. %% A detailed tutorial appears as http://www.tinaja.com/glib/pixintpl.pdf %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % a rainbow and false color corrector described in http://www.tinaja.com/glib/falseclr.pdf /nicerainbowdatapatchedx [ [0.0 0.71 1.0] [0.002668 0.712655 1.0] [0.006003 0.715973 1.0] [0.00867101 0.718628 1.0] [0.012006 0.721946 1.0] [0.015341 0.725265 1.0] [0.018009 0.727919 1.0] [0.021344 0.731238 1.0] [0.024012 0.733893 1.0] [0.027347 0.737211 1.0] [0.030015 0.739866 1.0] % color 10 [0.03335 0.743184 1.0] [0.036018 0.745839 1.0] [0.039353 0.749157 1.0] [0.042021 0.751812 1.0] [0.045356 0.75513 1.0] [0.048024 0.757785 1.0] [0.050692 0.76044 1.0] [0.054027 0.763758 1.0] [0.056695 0.766413 1.0] % color 20 [0.06003 0.769731 1.0] [0.062698 0.772386 1.0] [0.066033 0.775705 1.0] [0.068701 0.778359 1.0] [0.072036 0.781678 1.0] [0.074704 0.784332 1.0] [0.078039 0.787651 1.0] [0.080707 0.790305 1.0] [0.084042 0.793624 1.0] [0.08671 0.796279 1.0] [0.090045 0.799597 1.0] [0.09338 0.802915 1.0] [0.096048 0.80557 1.0] [0.099383 0.808889 1.0] [0.102051 0.811543 1.0] [0.105386 0.814862 1.0] [0.107387 0.816853 1.0] [0.110722 0.820171 1.0] [0.112056 0.821498 1.0] [0.115391 0.824817 1.0] [0.116058 0.825481 1.0] [0.119393 0.828799 1.0] [0.119393 0.828799 1.0] [0.122728 0.832117 1.0] [0.122061 0.831454 1.0] [0.125396 0.834772 1.0] [0.124062 0.833445 1.0] [0.127397 0.836763 1.0] [0.125396 0.834772 1.0] [0.128731 0.83809 1.0] [0.12673 0.836099 1.0] [0.130065 0.839418 1.0] [0.128064 0.837427 1.0] [0.131399 0.840745 1.0] [0.129398 0.838754 1.0] [0.132733 0.842073 1.0] [0.131113 0.840461 1.0] [0.134448 0.843779 1.0] [0.133209 0.842547 1.0] [0.136544 0.845865 1.0] [0.135687 0.845012 1.0] [0.139022 0.84833 1.0] [0.138545 0.847856 1.0] [0.14188 0.851174 1.0] [0.141785 0.85108 1.0] [0.14512 0.854398 1.0] [0.145406 0.854682 1.0] [0.148741 0.858001 1.0] [0.149408 0.858665 1.0] [0.152743 0.861983 1.0] [0.15341 0.862647 1.0] [0.156745 0.865965 1.0] [0.157412 0.866629 1.0] [0.160747 0.869947 1.0] [0.161414 0.870611 1.0] [0.164749 0.873929 1.0] [0.165416 0.874593 1.0] [0.168751 0.877911 1.0] [0.169418 0.878575 1.0] [0.172753 0.881893 1.0] [0.17342 0.882557 1.0] [0.176755 0.885875 1.0] [0.177422 0.886539 1.0] [0.180757 0.889858 1.0] [0.181424 0.890521 1.0] [0.184759 0.89384 1.0] [0.185426 0.894503 1.0] [0.188761 0.897822 1.0] [0.189428 0.898485 1.0] [0.192763 0.901804 1.0] [0.193239 0.902278 1.0] [0.196574 0.905596 1.0] [0.197241 0.90626 1.0] [0.200576 0.909578 1.0] [0.201243 0.910242 1.0] [0.204578 0.91356 1.0] [0.206579 0.915551 1.0] [0.209914 0.91887 1.0] [0.214678 0.92361 1.0] [0.218013 0.926929 1.0] [0.225541 0.995372 1.0] [0.228876 0.991897 1.0] [0.238691 0.98167 1.0] [0.242026 0.978194 1.0] [0.254317 0.965385 1.0] [0.257652 1.0 1.0] [0.271183 1.0 1.0] [0.274518 1.0 1.0] [0.289478 0.928746 1.0] [0.292813 0.925271 1.0] [0.307868 0.909582 1.0] [0.311203 0.906107 1.0] [0.324924 0.891809 1.0] [0.328259 0.888334 1.0] [0.340551 0.875525 1.0] [0.343886 0.872049 1.0] [0.35452 0.860968 1.0] [0.357855 0.857493 1.0] [0.366831 0.84814 1.0] [0.370166 0.844664 1.0] [0.378341 0.836145 1.0] [0.381676 0.83267 1.0] [0.389051 0.824984 1.0] [0.392386 0.821509 1.0] [0.398961 0.814658 1.0] [0.402296 0.811182 1.0] [0.40807 0.805165 1.0] [0.411405 0.80169 1.0] [0.416474 0.796408 1.0] [0.419809 0.792932 1.0] [0.424879 0.78765 1.0] [0.428214 0.784175 1.0] [0.433283 0.778892 1.0] [0.436618 0.775417 1.0 0.01 sub ] [0.441782 0.770035 1.0 0.02 sub ] [0.445117 0.76656 1.0 0.03 sub ] [0.450187 0.761278 1.0 0.04 sub ] [0.453522 0.757802 1.0 0.05 sub ] [0.458591 0.75252 1.0 0.06 sub ] [0.461926 0.749045 1.0 0.07 sub ] [0.466995 0.743762 1.0 0.08 sub ] [0.47033 0.740287 1.0 0.09 sub ] [0.475552 0.734846 1.0 0.10 sub ] [0.478887 0.73137 1.0 0.11 sub ] [0.484061 0.725979 1.0 0.12 sub ] [0.487396 0.722503 1.0 0.125 sub ] [0.492589 0.717092 1.0 0.13 sub ] [0.495924 0.713617 1.0 0.125 sub ] [0.501041 0.708285 1.0 0.12 sub ] [0.504376 0.704809 1.0 0.11 sub ] [0.509511 0.699457 1.0 0.10 sub ] [0.512846 0.695982 1.0 0.09 sub] [0.518001 0.69061 1.0 0.08 sub ] [0.521336 0.687135 1.0 0.07 sub ] [0.526606 0.681644 1.0 0.06 sub ] [0.529941 0.678169 1.0 0.05 sub ] [0.534591 0.673323 1.0 0.04 sub ] [0.537926 0.669848 1.0 0.02 sub ] [0.542252 0.66534 1.0 0.01 sub ] [0.545587 0.661865 1.0 0.00 sub ] [0.549522 0.657764 1.0 0.00 sub ] [0.552857 0.654289 1.0] [0.556401 0.650595 1.0] [0.559736 0.64712 1.0] [0.562986 0.643734 1.0] [0.566321 0.640259 1.0] [0.56916 0.6373 1.0] [0.572495 0.633824 1.0] [0.574839 0.631382 1.0] [0.578174 0.627906 1.0] [0.580604 0.625374 1.0] [0.583939 0.621899 1.0] [0.586359 0.619377 1.0] [0.589694 0.615902 1.0] [0.592153 0.61334 1.0] [0.595488 0.609865 1.0] [0.597936 0.607313 1.0] [0.601271 0.603838 1.0] [0.603711 0.601296 1.0] [0.607046 0.59782 1.0] [0.609495 0.595269 1.0] [0.61283 0.591793 1.0] [0.615278 0.589242 1.0] [0.618613 0.585766 1.0] [0.621062 0.583214 1.0] [0.624397 0.579739 1.0] [0.626846 0.577187 1.0] [0.630181 0.573712 1.0] [0.632582 0.57121 1.0] [0.635917 0.567735 1.0] [0.638319 0.565232 1.0] [0.641654 0.561757 1.0] [0.644055 0.559255 1.0] [0.64739 0.55578 1.0] [0.649791 0.553277 1.0] [0.653126 0.549802 1.0] [0.655527 0.5473 1.0] [0.658862 0.543825 1.0] [0.661263 0.541322 1.0] [0.664598 0.537847 1.0] [0.667 0.535345 1.0] ] store % A sampled data set for the graphic demos. Only the middle 16 values are used % for a 3x3 array. The additional edge values are needed for bicubic slopes. /data [ [0.60 0.60 0.48 0.24 0.60 0.60] [0.60 0.60 0.48 0.24 0.60 0.60] [0.00 0.00 0.36 0.12 0.48 0.48] [0.24 0.24 0.48 0.60 0.12 0.12] [0.12 0.12 0.24 0.48 0.36 0.36] [0.12 0.12 0.24 0.48 0.36 0.36] ] store %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Bilineal interpolation routine... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % the code.. % /intbilinear requires a predefined data array of form [[x x x][x x x] ...] % y is the outside column array. x are the internal row arrays. % x and y values are passed on the stack and separated into integer (find the unit % square) and residue (find the interpolated value inside that square) % the bilinear interpolated value appears on the stack /intbilinear { dup cvi dup /yi exch store sub /yr exch store % convert to integer and dup cvi dup /xi exch store sub /xr exch store % residues data yi get dup xi get 1 xr sub mul exch xi 1 add % lower left and right get xr mul add 1 yr sub mul data yi 1 add get dup xi get 1 xr sub mul exch xi % upper left and right 1 add get xr mul add yr mul add } bind def % a use demo 2.345 3.563 intbilinear == % should return 0.409 % a timing demo... (REQUIRES GONZO) returns 11.8 microseconds on a slower machine. stopwatchon 100000 {2.345 4.563 intbilinear pop} repeat stopwatchoff % a graphic plot... (REQUIRES GONZO) /plotbilin { 50 50 10 setgrid 50 50 showgrid 1 1 3 {/xint exch store 1 1 3 {/yint exch store 0 0.02 1 {/xres exch store 0 0.02 1 {/yres exch store xint xres add yint yres add intbilinear 200 mul 0.67 div cvi dup 200 gt {pop 200} if % trap out overflows dup 0 lt {pop 0} if nicerainbowdatapatchedx exch get aload pop sethsbcolor xint xres add 10 mul yint yres add 10 mul mt 0.2 pu 0.2 pr 0.2 pd closepath fill } for } for } for } for showpage } bind store plotbilin % uncomment to plot %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %% Bicubic interpolation routine... %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % the code.. % /intbicubic requires a predefined data array of form [[x x x][x x x] ...] % y is the outside column array. x are the internal row arrays. % A "border" must exist around the live rows for slope extraction. % x and y values are passed on the stack and separated into integer (find the unit % square) and residue (find the interpolated value inside that square) % the bilinear interpolated value appears on the stack % /grabdata is the first bicubic service proc. It finds wo through z3... /grabdata { dup cvi dup /yi exch store sub /yr exch store % integer and residue dup cvi dup /xi exch store sub /xr exch store /w0 data yi get xi get store % these evaluate data /w1 data yi get xi 1 add get store /w2 data yi 1 add get xi get store /w3 data yi 1 add get xi 1 add get store /x0 w1 data yi get xi 1 sub get sub 2 div store % x slopes /x1 data yi get xi 2 add get w0 sub 2 div store /x2 w3 data yi 1 add get xi 1 sub get sub 2 div store /x3 data yi 1 add get xi 2 add get w2 sub 2 div store /y0 w2 data yi 1 sub get xi get sub 2 div store % y slopes /y1 w3 data yi 1 sub get xi 1 add get sub 2 div store /y2 data yi 2 add get xi get w0 sub 2 div store /y3 data yi 2 add get xi 1 add get w1 sub 2 div store /z0 x0 y0 mul store /z1 x1 y1 mul store /z2 x2 y2 mul store /z3 x3 y3 mul store } bind store % /mergedbicubiccalc combines grabbing a coefficients with the bicubic calcs to % eliminate variable definition and provide a slight speedup... /mergedbicubiccalc { % creates a surface from sixteen cubic equations % combines a coeffs without defs /xx2 xr dup mul store % faster than using exp /xx3 xx2 xr mul store /yy2 yr dup mul store /yy3 yr yy2 mul store w0 % a00 y0 yr mul add % a01 w0 -3 mul w2 3 mul add y0 -2 mul add y2 sub yr 2 exp mul add % a02 w0 2 mul w2 -2 mul add y0 add y2 add yr 3 exp mul add % a03 x0 xr mul add % a10 z0 xr mul yr mul add % a11 x0 -3 mul x2 3 mul add z0 -2 mul add z2 sub xr mul yy2 mul add % a12 x0 2 mul x2 -2 mul add z0 add z2 add xr mul yy3 mul add % a13 w0 -3 mul w1 3 mul add x0 -2 mul add x1 sub xx2 mul add % a20 y0 -3 mul y1 3 mul add z0 -2 mul add z1 sub xx2 mul yr mul add % a21 w0 9 mul w1 -9 mul add w2 -9 mul add w3 9 mul add x0 6 mul add x1 3 mul add x2 -6 mul add x3 -3 mul add y0 6 mul add y1 -6 mul add y2 3 mul add y3 -3 mul add z0 4 mul add z1 2 mul add z2 2 mul add z3 add xx2 mul yy2 mul add % a22 w0 -6 mul w1 6 mul add w2 6 mul add w3 -6 mul add x0 -4 mul add x1 -2 mul add x2 4 mul add x3 2 mul add y0 -3 mul add y1 3 mul add y2 -3 mul add y3 3 mul add z0 -2 mul add z1 neg add z2 -2 mul add z3 neg add xx2 mul yy3 mul add % a23 w0 2 mul w1 -2 mul add x0 add x1 add xx3 mul add % a30 y0 2 mul y1 -2 mul add z0 add z1 add xx3 mul yr mul add % a31 w0 -6 mul w1 6 mul add w2 6 mul add w3 -6 mul add x0 -3 mul add x1 -3 mul add x2 3 mul add x3 3 mul add y0 -4 mul add y1 4 mul add y2 -2 mul add y3 2 mul add z0 -2 mul add z1 -2 mul add z2 neg add z3 neg add xx3 mul yy2 mul add % a32 w0 4 mul w1 -4 mul add w2 -4 mul add w3 4 mul add x0 2 mul add x1 2 mul add x2 -2 mul add x3 -2 mul add y0 2 mul add y1 -2 mul add y2 2 mul add y3 -2 mul add z0 add z1 add z2 add z3 add xx3 mul yy3 mul add % a33 } bind store /intbicubic { grabdata mergedbicubiccalc } bind store % a use demo 2.345 3.563 intbicubic == % should return 0.435 (better than bilineal) % a timing demo... (REQUIRES GONZO) returns 10.21 microseconds on a slower machine. stopwatchon 100000 {2.345 3.563 intbicubic pop} repeat stopwatchoff % a graphic plot... (REQUIRES GONZO) /plotbicub { 50 50 10 setgrid 50 50 showgrid 1 1 3 {/xint exch store 1 1 3 {/yint exch store 0 0.02 1 {/xres exch store 0 0.02 1 {/yres exch store xint xres add yint yres add intbicubic 200 mul 0.67 div cvi dup 200 gt {pop 200} if % trap out overflows dup 0 lt {pop 0} if nicerainbowdatapatchedx exch get aload pop sethsbcolor xint xres add 10 mul yint yres add 10 mul mt 0.2 pu 0.2 pr 0.2 pd closepath fill } for } for } for } for showpage } bind store plotbicub % uncomment to plot % EOF