%!PS % PS Bitmap Saturation Adjuster % =================================== % by Don Lancaster % 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.1 % PostScript-as-language utility reads a 24-bit uncompressed bitmap file and % adjusts the saturation of each color triad. Useful for gray conversion or % correcting over and undersaturation. May be expanded for selective adjustment. % Note: oversaturation color fidelty preserved only if no color over or undersaturates. % To use, load into wp or editor, change filenames and shading values below and % send to Distiller. A "no Acrobat PDF file produced" error is normal and expected. % ========= % IMPORTANT NOTE: Don Lancaster's file gonzo.ps is required for this program. % After obvious location mods, uncomment ONE of the following two lines: (C:\\windows\\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. % 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. % ======== /guru { gonzo begin ps.util.1 begin printerror nuisance begin} def guru % activate gonzo utilities % ========= % define color weights here .11 .59 .30 is tv and PostScript standard. /redweight 0.30 store % red component of luminance /greenweight 0.59 store % green component of luminance /blueweight 0.11 store % blue component of luminance /sat 0.33 store % desired saturation 1 = same 0 = gray % input name of bmp file to be evaluated here... /diskfileheader (C:\\WINDOWS\\Desktop\\aaraw_pix\\) store /diskfilesourcename (terms7.bmp) store /diskfiletargetname (termh7.bmp) store /sourcefilename diskfileheader diskfilesourcename mergestr store /targetfilename diskfileheader diskfiletargetname mergestr store /readfile sourcefilename (r) file store % establish input read file /writefile targetfilename (w+) file store % establish output target file /whiteref (XXX) def % truewhite reference whiteref 0 255 put whiteref 1 255 put whiteref 2 255 put /bitsperpixelposition 28 store % BMP header positioning info /datastartposition 10 store /horizontalpixels 18 store /verticalpixels 22 store /backcount 0 store %%%%%%%%% 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 (Bitmap width is ) exch mergestr ( pixels.\n) mergestr print flush % 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 (Bitmap height is ) exch mergestr ( pixels.\n) mergestr print flush % 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 %%%%%%%%%%%%%%%% COPY HEADER TO TARGET FILE %%%%%%%%%%%%%%%%%% % 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 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 %%%%%%%%%%%%%% SERVICE UTILS %%%%%%%%%% % clipcheck restricts color values to 0-255 range /clipcheck { dup 255 ge {pop 255} if dup 0 le {pop 0 } if } store %%%%%%%%%%%%%%%% COPY DATA TO TARGET FILE, RESATURATING AS NEEDED %%%%%%%%%%%%%%%%%% /linestring hres 3 mul string store % read file line buffer /targetstring hres 3 mul padding add string store % write file line buffer targetstring dup length 1 sub 0 put % zero max padding targetstring dup length 2 sub 0 put targetstring dup length 3 sub 0 put /oldcolor (ZZZ) def /whitecount 0 store /mainloop { 0 1 vres 1 sub { /vline exch store % start of next hires line vline 24 mod 0 eq % pretty print progress {(.) print flush} if vline hres 3 mul padding add mul actualdatastart add dup % position read and write identically readfile exch setfileposition writefile exch setfileposition readfile linestring readstring % grab a line of characters not {big_time_read_error} if /sourcestring exch store 0 3 hres 1 sub 3 mul { /posn exch store % start line pixel loop sourcestring posn 3 getinterval /curpixelstring exch store /curgray curpixelstring 0 get blueweight mul curpixelstring 1 get greenweight mul add curpixelstring 2 get redweight mul add store curpixelstring 0 get curgray sub % correct blue sat mul curgray add clipcheck cvi curpixelstring exch 0 exch put curpixelstring 1 get curgray sub % correct green sat mul curgray add clipcheck cvi curpixelstring exch 1 exch put curpixelstring 2 get curgray sub % correct red sat mul curgray add clipcheck cvi curpixelstring exch 2 exch put curpixelstring targetstring exch posn exch putinterval } for % next line MUST start on an even 32-bit boundary writefile targetstring writestring } for % (\nA total of ) backcount 12 string cvs mergestr % ( pixels have been substituted\n\n) mergestr print flush } bind def stopwatchon mainloop % this does it all stopwatchoff (\nFinished.\n) print % report % EOF