Printing Gif Pictures from Macintosh to LaserWriter - John Jeppson Gif Developers with DL17 access have my permission to use this material in their own programs. \ Last Revision: 11/21/87 10:30:32 PM JRJ - discusses necessity, during _OpenPicture, of breaking up the PostScript program/image into a series of 32K chunks in sequential PicComments. This file describes one technique for printing Gif images on the LaserWriter using up to 256 gray tones. This version prints the picture centered on an 8.5 x 11 inch page. The picture is rotated if necessary. The overall strategy is to create and transmit to the LaserWriter the following PostScript program. The program is an ascii text file. Lines of text should be separated by a newline character (ascii 13). POSTSCRIPT PROGRAM: gsave initmatrix % leave out these comments /width paramW def % we supply 4 parameters /height paramH def % usually width = xPix /xPix paramX def % and height = yPix /yPix paramY def /-yPix yPix neg def /inches {72 mul} def /centerPicture % procedure definition {4.25 inches 5.5 inches translate % center the coord.system width 6.5 inches gt {90 rotate} if % rotate if width > 6.5 inches width 2 div neg height 2 div neg % lower left corner of picture translate} def /scalePicture {width height scale} def /picstr % temporary string variable xPix 256 le % length = xPix {xPix} {256} ifelse % or maximum 256 string def /pixImage % actually reads image data {xPix yPix 8 [xPix 0 0 -yPix 0 yPix] % "transform matrix" {currentfile picstr readhexstring pop} image} def centerPicture % do these procedures now scalePicture pixImage % read the image <*** actual image data goes here ***> showpage grestore % print and clean up The image data must follow immediately after the ascii word "pixImage", separated by a single carriage return. The image data is a stream of ascii hexadecimal characters. Characters not in ['0'..'9','A'..'F','a'..'f'] are ignored. Each PAIR of characters represents one 8-bit pixel value. Thus the image is coded as a single hex string consisting of exactly (xPix * yPix * 2) hexadecimal characters. "pixImage" will be invoked repeatedly, each time reading length(pixstr) pixels into pixstr, and thereby consumming twice that many hexstring characters from the image data. On the last read it is possible that only a few pixels will remain. Nevertheless the "readhexstring" operator will read 2*length(pixstr) characters from the incoming data stream, entirely filling pixstr each time. It is essential to end this read with the PostScript file mark just past the image data so that the following commands "showpage grestore" will be correctly interpreted. Therefore it may be necessary to pad the image data with extra hexadecimal characters in order to come out even. That occurs in this particular program when: xPix > 256 ; narrower pictures are read by full rows AND extra pixels > 0 where extra pixels = total.pixels MOD 256 Remember to add TWO extra hexadecimal characters for each "extra" pixel. This requirement stems from limiting the length of pixstr to 256, which is NOT required by PostScript. The LaserWriter, however, has only marginal amount of memory for its task. The four parameters: width, height, xPix, and yPix must be supplied as ascii text strings substituted for the characters: "paramW", "paramH", "paramX", and "paramY", respectively. I simply move the PostScript text into a handle, convert ScreenWidth (etc.) into ascii text, and replace the characters "paramW" using _Munger. Best to do this before adding the image data so that Munger doesn't have to move so many bytes each time. Don't forget to add the final commands: "showpage grestore" after the image data. TRANSMITTING TO LASERWRITER: I'm using the easy (but memory intensive) method of creating a QuickDraw picture and including the entire text (PostScript program + image data) in a Picture Comment. It is probably possible save large amounts of memory by sending the stuff via direct calls to AppleTalk or via "Low Printing" commands as found on page 26 of LaserWriter Manual. I haven't yet tried those methods. The Picture Comment technique is outlined on page 48 of LaserWriter Manual. Since most pictures exceed 32K in size it is necessary to use a version-2 picture. This is made automatically when _OpenPicture is called while the port is set to a color window. It is not necessary to use the new trap _OpenCPicture since we are not actually drawing color stuff in the Picture. In fact we don't draw anything, we just include PicComments. Unfortunately, even in version-2 pictures the PicComment can handle only 32K bytes at a time. It is therefore necessary to break up the completed PostScriptProgam+image into a sequence of smaller handles each less than 32K in size. These separate pieces are simply incorporated into a series of PicComments sent one after another in the correct order. thePicture := OpenPicture(theWorld); (* DO THIS WITH A COLOR WINDOW CURRENT *) ClipRect(theWorld); (* I'm using: 0 0 1000 1000 *) PicComment(PostScriptBegin,0,nil); begin PicComment(PostScriptHandle,length(thisPiece),thisPieceHandle); end PicComment(PostScriptEnd,0,nil); ClosePicture; Then I send it from a Hi-Printing loop (in Forth) : uploadText printing.prep \ essentially _PrOpen open.document \ _PrOpenDoc open.page \ _PrOpenPage thePicture theWorld draw.picture \ _DrawPicture close.page \ _PrClosePage close.document \ _PrCloseDoc printing.done ; \ _PrClose NOTE: The PostScipt program expects 8-bit "pixels" in the image data as directed by the "8" parameter in {xPix yPix 8 [xPix 0 0 -yPix 0 yPix] % "transform matrix" If you have only 16 or so graytones you can pack the image data (left to right) and change the number of bits in the transform matrix. You would then have to adjust the size of "picstr" and the padding procedures to make things come out even. Doesn't seem worth the trouble.