home *** CD-ROM | disk | FTP | other *** search
/ BBS in a Box 3 / BBS in a box - Trilogy III.iso / Files / Prog / U-Z / VideoToolBox Folder / VideoToolboxSources / PixMapToPostScript.c < prev    next >
Encoding:
Text File  |  1993-03-04  |  8.3 KB  |  196 lines  |  [TEXT/KAHL]

  1. /*
  2. PixMapToPostScript.c
  3. Copyright © 1991,1992 Denis G. Pelli
  4.     This is a simple but reasonably general routine to convert a grayscale PixMap to
  5. a PostScript file that may be transmitted to a LaserWriter or Linotype to produce
  6. a halftone image on paper.
  7.     The filename, by convention, should end in ".ps" to indicate that it is a postscript
  8. file, but this is not enforced. The file's type is set to 'TEXT' with creator
  9. '4PSU', so that it can be double-clicked to open my favorite PostScript
  10. downloading program, PostHaste. However, since it's a plain text file, any downloader
  11. will work, and if you're using a Linotype, you're probably just sending the file
  12. by modem.
  13.     The PixMap must have 8 bits per pixel. No color tables are used. The raw pixel
  14. value (Apple calls it an "index") is sent directly to the printer with no
  15. transformation. PostScript assumes that the number, from 0 to 255 is proportional to
  16. desired reflectance, from zero to 1. The *rectPtr indicates what part of your
  17. PixMap is to be used. 
  18.     The *pageRectPtr is subtle. It describes, in typographers points (1/72"),
  19. the rectangle that your image will be mapped onto on the printed page. It is essential
  20. that you keep in mind that Apple and Adobe use different coordinate systems. 
  21. Both Apple and Adobe increase x from left to right.
  22. However, Apple has y increasing from top to bottom, whereas Adobe increases y from
  23. bottom to top. Adobe's origin is the lower left corner of the paper, even though
  24. that point is usually not printable, since most printers can only print to within
  25. about a half inch of the edge. The pageRect, though supplied in Apple's Rect data
  26. structure, must be in Adobe's coordinates, respecting the names of the Rect structure's
  27. fields: left, top, right, bottom. So, for an image
  28. to fill most of an 8.5x11 page, with 1" margins, you might use the following:
  29. SetRect(&pageRect,1*72,10*72,7.5*72,1*72);
  30.     The cellsPerInch parameter is optional in the sense that if cellsPerInch is zero
  31. it is ignored, leaving the printer at its default setting, which is usually a
  32. good choice. If you set cellsPerInch to a
  33. nonzero value then the printer will be asked to print its halftone with that
  34. many halftone cells per inch. Note that there is no correspondence between pixels in your
  35. image and cells in the halftone; PostScript automatically resamples your image to
  36. produce its halftone. There are two common reasons for fiddling with cellsPerInch.
  37. If you're trying to get a reasonable gray scale out of a LaserWriter (which
  38. has 300 dots per inch) you'll need to make the cell size big enough to hold at least
  39. 256 pixels if you want 256 gray levels. This requires 300/sqrt(256)=18.75 cells per
  40. inch. The other situation is producing a half tone as an original for subsequent
  41. reproduction in a journal, where you'll want the cells to be coarse enough for
  42. them to reproduce without re-screening, e.g. 100 cells per inch.
  43.     You should remove(filename) any pre-existing old file of the same name, unless 
  44. you want to append to it. PixMapToPostScript always appends to an existing file with
  45. the same name, if one exists, to allow you to place several images onto a page. 
  46. (You should offset their pageRects unless you want the images to superimpose.) 
  47.     You will need to add a "showpage\n" command at the end of the postscript file. 
  48. This is the command that tells the printer to actually go ahead and print the page. 
  49. Use the command AppendToFile(filename,"showpage\n"), supplied for this purpose. Naturally, 
  50. you could also use to this to add your own postscript commands before or after the
  51. imaging code inserted by PixMapToPostScript. 
  52.     Here's a minimal example of the three commands:
  53. remove("test.ps");
  54. PixMapToPostScript("test.ps",*pixMapHandle,&rect,&pageRect,0.0,0);
  55. AppendToFile("test.ps","showpage\n");
  56.     In case your PostScript manual isn't handy, the easy way to obtain multiple copies
  57. of the same page is to use the #copies variable that's built into Postscript. Anywhere
  58. in your file before "showpage", set #copies to the desired value. E.g.
  59. AppendToFile("test.ps","/#copies 3 def\n");
  60.     There are many free PostScript downloaders, but I find them clumsy to use, especially
  61. the ones that don't inform you of errors, should they occur. I bought and use
  62. PostHaste
  63. from:
  64. Micro Dynamics, Ltd.
  65. 8555 16th St., Suite 802
  66. Silver Spring, MD 20910
  67. (301)-589-6300
  68. or
  69. LaserStatus, a desk accessory that is included in the 
  70. MockPackage Plus Utilities
  71. from:
  72. CE Software
  73. 1854 Fuller Road
  74. PO Box 65580
  75. West Des Moines, Iowa 50265
  76. (515)-224-1995
  77.     You may also want to read:
  78. Adobe Systems (1985) PostScript Language Reference Manual. Reading, MA: Addison-Wesley.
  79. Pelli, D. G. (1987) Programming in PostScript: Imaging on paper from a mathematical
  80. description. BYTE, 12 (5), 185-202.
  81.  
  82. HISTORY:
  83. 4/21/91    dgp    wrote it
  84. 7/24/91 dgp added comment about shifting pageRect
  85. 8/24/91    dgp    Made compatible with THINK C 5.0
  86. 12/7/91    dgp    minor editing of comments
  87. 10/10/92 dgp Added support for Pixmap's that require 32-bit addressing.
  88.             Much faster now, using table-lookup instead of sprintf for 
  89.             the hex encoding.
  90.             Deleted obsolete support for THINK C 4.
  91. */
  92. #include "VideoToolbox.h"
  93. #include <assert.h>
  94. #include <math.h>
  95. #include <Errors.h>
  96.  
  97. void PixMapToPostScript(char *filename,PixMap *pm,Rect *rectPtr
  98.     ,Rect *pageRectPtr,double cellsPerInch,int grayLevels)
  99. {
  100.     FILE *file;
  101.     unsigned char *addr;
  102.     long y,bytes,width;
  103.     register long i;
  104.     register unsigned short *buffer,hex[256];
  105.     register unsigned char *byte;
  106.     short pixelSize;
  107.     short rowBytes;
  108.     time_t ANSITime;
  109.     char string[100];
  110.     char mode;
  111.         
  112.     if(cellsPerInch!=0.0 && grayLevels!=0.0){
  113.         PrintfExit("PixMapToPostScript: you may not specify BOTH cellsPerInch & grayLevels\n\007"
  114.             "Set one to zero.\n");
  115.     }
  116.     file=fopen(filename,"a");
  117.     if(file==NULL)PrintfExit("PixMapToPostScript: Error in opening file \"%s\"\n",filename);
  118.     addr=RectToAddress(pm,rectPtr,&rowBytes,&pixelSize,NULL);
  119.     if(addr==NULL || pixelSize!=8)
  120.         PrintfExit("PixMapToPostScript: Can't deal with this PixMap.\n");
  121.     time(&ANSITime);
  122.     strftime(string,sizeof(string),"%I:%M %p %A, %B %d, %Y",localtime(&ANSITime));
  123.     fprintf(file,
  124.         "\nsave                    %% %s, %s\n",filename,string);
  125.     fprintf(file,
  126.         "/nx %d def                %% pixels per raster line\n",rectPtr->right-rectPtr->left);
  127.     fprintf(file,
  128.         "/ny %d def                %% lines in image\n",rectPtr->bottom-rectPtr->top);
  129.     fprintf(file,
  130.         "%d %d translate        %% locate lower left of image\n",pageRectPtr->left
  131.         ,pageRectPtr->bottom);
  132.     fprintf(file,
  133.         "%d %d scale            %% print image with these dimensions on page\n"
  134.         ,pageRectPtr->right-pageRectPtr->left,pageRectPtr->top-pageRectPtr->bottom);
  135.     fprintf(file,
  136.         "/hypotenuse {dup mul exch dup mul add sqrt} bind def\n"
  137.         "/pixelsPerInch gsave initmatrix 72 0 dtransform hypotenuse grestore def\n");
  138.     if(cellsPerInch!=0.0){
  139.         fprintf(file,
  140.             "/cellsPerInch %.2f def    %% halftone dot frequency\n",cellsPerInch);
  141.         fprintf(file,
  142.             "cellsPerInch currentscreen 4 -2 roll pop 3 1 roll setscreen\n");
  143.     }
  144.     if(grayLevels!=0.0){
  145.         fprintf(file,
  146.             "/cellsPerInch pixelsPerInch %.2f div def    %% halftone dot frequency\n",sqrt(grayLevels));
  147.         fprintf(file,
  148.             "cellsPerInch currentscreen 4 -2 roll pop 3 1 roll setscreen\n");
  149.     }
  150.     fprintf(file,
  151.         "/s nx string def        %% string to hold one raster line\n"
  152.         "nx ny 8                    %% dimensions and bits/pixel of source image\n"
  153.         "[nx 0 0 ny neg 0 ny]    %% map unit square to PixMap data\n"
  154.         "{currentfile s readhexstring pop}    %% read data\n"
  155.         "bind                    %% speed up reading\n"
  156.         "image\n");
  157.     assert(sizeof(hex[0])==2);    // assumed by our algorithm
  158.     assert(sizeof(buffer[0])==2);// assumed by our algorithm
  159.     for(i=0;i<256;i++){
  160.         sprintf(string,"%02x",(int)i);
  161.         hex[i]=*(unsigned short *)string;
  162.     }
  163.     width=rectPtr->right-rectPtr->left;
  164.     bytes=(width+1)*sizeof(*buffer);
  165.     buffer=(unsigned short *)NewPtr(bytes);
  166.     if(buffer==NULL){
  167.         printf("PixMapToPostScript: no room for %ld byte buffer.\n\007",bytes);
  168.         return;
  169.     }
  170.     for(y=rectPtr->top;y<rectPtr->bottom;y++){
  171.         mode=true32b;
  172.         SwapMMUMode(&mode);
  173.         byte=addr;
  174.         for(i=0;i<width;i++){
  175.             buffer[i]=hex[byte[i]];
  176.         }
  177.         buffer[i]=0;
  178.         SwapMMUMode(&mode);
  179.         fprintf(file,"%s\n",(char *)buffer);
  180.         addr+=rowBytes;
  181.     }
  182.     DisposPtr((Ptr)buffer);
  183.     fprintf(file,"restore\n");
  184.     fclose(file);
  185.     SetFileInfo(filename,'TEXT','4PSU');
  186. }
  187.  
  188. void AppendToFile(char *filename,char *string)
  189. {
  190.     FILE *file;
  191.     
  192.     file=fopen(filename,"a");
  193.     if(file==NULL)PrintfExit("AppendToFile: Error in opening file \"%s\"\n",filename);
  194.     fprintf(file,"%s",string);
  195.     fclose(file);
  196. }