home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume17 / calentool / part09 / ras2ps.c
C/C++ Source or Header  |  1991-04-07  |  12KB  |  453 lines

  1. /*
  2.  * $Header: ras2ps.c,v 2.3 89/12/15 17:18:07 billr Exp $
  3.  */
  4. /*
  5.  * ras2ps - convert Sun raster file to RLL Postscript file
  6.  *
  7.  * Based on the sun2ps program by Glenn Boysko and modified slightly
  8.  * by Bill Randle, Tektronix, Inc.
  9.  * Original source of unknown copyright status; modifications Copyright
  10.  * 1989, Tektronix, Inc.
  11.  */
  12. #include "ct.h"        /* for the NO_PRINTER #define */
  13. #ifndef NO_PRINTER
  14. /******************************************************************************
  15. *                                          *
  16. *    File:         sun2ps.c                              *
  17. *    Author:       Glenn Boysko                          *
  18. *    Organization: Case Western Reserve University                  *
  19. *    EMail:          {decvax, sun}!mandrill!boysko                  *
  20. *              boysko@mandrill.cwru.edu                      *
  21. *    Created:      Wed Mar 23 9:25pm                          *
  22. *    Contents:     Sun Rasterfile to PostScript image (using a run-length  *
  23. *            encoding scheme.)                      *
  24. *                                          *
  25. *    (Adapted from "postimage" filter by J. R. Bammi.)              *
  26. *                                          *
  27. *    @(#)sun2ps.c    1.8
  28. ******************************************************************************/
  29.  
  30. /* Sun standard raster file format (as obtained by screendump(1)).
  31.  *
  32.  * Header    (8 16-bit quantities)
  33.  * Color Map
  34.  * Image
  35.  *
  36.  */
  37.  
  38. /* Header Format:
  39.  * 
  40.  * ras_magic        (int)    Raster Magic number 0x59a66a95
  41.  * ras_width        (int)    Width of image in pixels.
  42.  * ras_height        (int)    Height of image in pixels.
  43.  * ras_depth        (int)    Bits per pixel.    Either 1 or 8 bits.
  44.  * ras_length        (int)    Length of image in bytes, after line padding.
  45.  * ras_type        (int)    Type of file. Assumed to be RT_STANDARD (1) if
  46.  *                produced by a screendump command.
  47.  * ras_maptype        (int)    Type of color map. 
  48.  * ras_maplength    (int)    Length of color map in bytes.
  49.  *
  50.  */
  51.  
  52. /* Ras_maplength bytes of Color map data. */
  53.  
  54. /* Ras_length bytes of Image data. */
  55.  
  56. #include <stdio.h>
  57. #include <pixrect/pixrect_hs.h>
  58.  
  59. /* Buffer and Input Modes... */
  60. #define LITERAL    0
  61. #define COPY    1
  62. #define IGNORE    2
  63.  
  64. /* Transmission Variables. */
  65. int BufCount;
  66.  
  67. unsigned char Buffer[128],
  68.                CurrByte,
  69.                NextByte,
  70.                *BufferP = Buffer;
  71.  
  72. FILE *ofile;
  73.  
  74. /* Diagnostic Variables. */
  75. int    DiagNLongRuns = 0,
  76.          DiagMaxRunLength = 0,
  77.          DiagNumRuns = 0;
  78. double    DiagSumRunLength = 0;
  79.  
  80. ras2ps(infile, outfile)
  81. FILE *infile, *outfile;
  82. {
  83.      double     sizex, sizey, transx, transy, rotate;
  84.      struct rasterfile rh;
  85.      int i, BS, pad,inv;
  86.      
  87.  
  88.      extern double atof();
  89.      
  90.      sizex = 7.5;
  91.      sizey = 10.0;
  92.      transx = transy = 0.5;
  93.      inv = 0;
  94.      rotate = 0.0;
  95.      ofile = outfile;
  96.      
  97.      if (pr_load_header(infile, &rh) != 0)
  98.       Error("Can't read rasterfile header\n");
  99.  
  100. #ifdef EXTRADIAGS
  101.      fprintf(stderr, "Ras_width = %d, Ras_height = %d, Ras_depth = %d\n", 
  102.          rh.ras_width, rh.ras_height, rh.ras_depth);
  103.      fprintf(stderr, "Ras_length = %d, Ras_type = %d, Ras_maplength = %d\n",
  104.          rh.ras_length, rh.ras_type, rh.ras_maplength);
  105. #endif
  106.      
  107.      if (rh.ras_magic != RAS_MAGIC)
  108.      {    
  109.       Error("Input file is not a Sun Rasterfile!\n");
  110.      }
  111.      
  112.      if (rh.ras_type != RT_STANDARD)
  113.      {
  114.       Error("Input file is not in Sun Standard Rasterfile format.\n");
  115.      }
  116.      
  117.      /* Scan off color table */
  118.      if (rh.ras_maptype != RMT_NONE && rh.ras_maplength > 0)
  119.     pr_load_colormap(infile, &rh, NULL);
  120.      
  121.      if ( pad = 16 - (rh.ras_width%16) ) {
  122.      rh.ras_width += pad;
  123. #ifdef EXTRADIAGS
  124.     fprintf(stderr, "Ras_width changed to %d\n",rh.ras_width);
  125. #endif
  126.      }
  127.  
  128.      PrintPostScriptRoutines(rh.ras_height, rh.ras_width, rh.ras_depth,
  129.                  transx, transy, sizex, sizey, rotate);
  130.      
  131.      BS = Encode(infile, rh.ras_length, inv);
  132.      
  133. #ifdef DIAGS
  134.      fprintf(stderr, "Encoded %d bytes into %d. (Ratio=%d%%)\n",
  135.          rh.ras_length, BS, 100 - (100 * BS) / rh.ras_length);
  136.      Diags();
  137. #endif     
  138.      fclose(infile);
  139.  
  140.      PrintPostScriptClosing();
  141.      fclose(outfile);
  142. }
  143.      
  144. /******************************************************************************
  145. *    I/O Routines.                                  *
  146. ******************************************************************************/
  147. int
  148. gb(Fp)        /* Get a byte from Fp. */
  149. FILE *Fp;
  150. {
  151.      int byte;
  152.      
  153.      if (!feof(Fp))
  154.       byte = getc(Fp);
  155.      else
  156.       Error("Premature EOF.\n");
  157.      if (ferror(Fp))
  158.       Error("I/O Error.\n");
  159.      return(byte);
  160. }
  161.  
  162. int
  163. gw(Fp)        /* Get a word (int) from Fp. */
  164. FILE *Fp;
  165. {
  166.      int word;
  167.      
  168.      if (!feof(Fp))
  169.       word = getw(Fp);
  170.      else
  171.       Error("Premature EOF.\n");
  172.      if (ferror(Fp))
  173.       Error("I/O Error.\n");
  174.      return(word);
  175. }
  176.  
  177. SendHex(Byte)        /* Send a Hex char to Stdout. */
  178. unsigned char Byte;
  179. {
  180.      static int LineCount = 0;
  181.  
  182.      fprintf(ofile, "%02x",  0xff & Byte);
  183.      if (++LineCount == 16)
  184.      {
  185.       fputc('\n', ofile);
  186.       LineCount = 0;
  187.      }
  188. }
  189.      
  190. int
  191. SendBuffer(Inv)        /* Send a buffer to Stdout. Return BytesSent. */
  192. int Inv;
  193. {
  194.      int i, BytesSent;
  195.      
  196.      if (BufferMode() == LITERAL)
  197.      {
  198.       SendHex( (unsigned char) 0xff & BufCount );
  199.       for (i = 0; i < BufCount+1; i++)
  200.       {
  201.            SendHex( (Inv) ? Buffer[i] : ~Buffer[i]);
  202.       }
  203.       BytesSent = BufCount+2;
  204.      }
  205.      else if (BufferMode() == COPY)
  206.      {
  207.       SendHex( (unsigned char) 0xff & (0x100 + BufCount) );
  208.       SendHex( (Inv) ? Buffer[0] : ~Buffer[0]);
  209.       BytesSent = 2;
  210.       DiagRecLRun(mag(BufCount)+1);
  211.      }
  212.      return(BytesSent);
  213. }
  214.  
  215. /******************************************************************************
  216. *    Utility Routines.                              *
  217. ******************************************************************************/
  218. int
  219. mag(Byte)    /* Magitude of a signed char. */
  220. int Byte;
  221. {
  222.      if (Byte & 0x80)
  223.      {
  224.       /* Signed */
  225.       Byte = ~(--Byte);
  226.      }
  227.      return( 0xff & Byte );
  228. }
  229.       
  230. /******************************************************************************
  231. *    Buffer Management Routines.                          *
  232. ******************************************************************************/
  233. int
  234. InputMode()
  235. {
  236.      if (CurrByte == NextByte)
  237.       return(COPY);
  238.      return(LITERAL);
  239. }
  240.  
  241. int
  242. BufferMode()
  243. {
  244.      if (BufCount >= 0 && BufCount <= 127)
  245.       return(LITERAL);
  246.      else if (BufCount >= -127 && BufCount <= -1)
  247.       return(COPY);
  248.      return(IGNORE);
  249. }
  250.  
  251. InitLitMode(Fp, NBytes, Inv)
  252. FILE *Fp;
  253. int *NBytes, Inv;
  254. {
  255.      BufferP    = Buffer;
  256.      BufCount   = -1;
  257.      ContLitMode(Fp, NBytes, Inv);
  258. }
  259.  
  260. ContLitMode(Fp, NBytes, Inv)
  261. FILE *Fp;
  262. int *NBytes, Inv;
  263. {
  264.      if (BufCount == 127)
  265.      {
  266.       SendBuffer(Inv);
  267.       BufferP  = Buffer;
  268.       BufCount = -1;
  269.      }
  270.      *BufferP++ = CurrByte;
  271.      BufCount++;
  272.      CurrByte   = NextByte;
  273.      NextByte   = (unsigned char) gb(Fp);
  274.      (*NBytes)--;
  275. }
  276.      
  277. InitCopyMode(Fp, NBytes, Inv)
  278. FILE *Fp;
  279. int *NBytes, Inv;
  280. {
  281.      BufferP    = Buffer;
  282.      *BufferP++ = CurrByte;
  283.      BufCount   = -1;
  284.      CurrByte   = (unsigned char) gb(Fp);
  285.      NextByte   = (unsigned char) gb(Fp);
  286.      *NBytes   -= 2;
  287. }
  288.  
  289. ContCopyMode(Fp, NBytes, Inv)
  290. FILE *Fp;
  291. int *NBytes, Inv;
  292. {
  293.      if (BufCount == -127)
  294.      {
  295.       SendBuffer(Inv);
  296.       InitCopyMode(Fp, NBytes, Inv);
  297.       DiagNLongRuns++;
  298.      }
  299.      BufCount--;
  300.      CurrByte   = NextByte;
  301.      NextByte   = gb(Fp);
  302.      (*NBytes)--;
  303. }
  304.  
  305. /******************************************************************************
  306. *    Encoding Algorithm.                              *
  307. ******************************************************************************/
  308. int
  309. Encode(Fp, NBytes, Inv)
  310. FILE *Fp;
  311. int NBytes, Inv;
  312. {
  313.      int BytesSent = 0;
  314.      
  315.      /* Initialize Buffer, BufCount, NextByte, CurrByte */
  316.      CurrByte = (unsigned char) gb(Fp);
  317.      NextByte = (unsigned char) gb(Fp);
  318.      if (InputMode() == LITERAL)
  319.      {
  320.       InitLitMode(Fp, &NBytes, Inv);
  321.      }
  322.      else
  323.      {
  324.       InitCopyMode(Fp, &NBytes, Inv);
  325.      }
  326.      while (NBytes > 3)
  327.      {
  328.       switch(BufferMode())
  329.       {
  330.         case LITERAL:
  331.            if (InputMode() == COPY)
  332.            {
  333.             BytesSent += SendBuffer(Inv);
  334.             InitCopyMode(Fp, &NBytes, Inv);
  335.            }
  336.            else
  337.            {
  338.             ContLitMode(Fp, &NBytes, Inv);
  339.            }
  340.            break;
  341.         case COPY:
  342.            if (CurrByte == Buffer[0])
  343.            {
  344.             ContCopyMode(Fp, &NBytes, Inv);
  345.            }
  346.            else
  347.            {
  348.             BytesSent += SendBuffer(Inv);
  349.             if (InputMode() == COPY)
  350.             {
  351.              InitCopyMode(Fp, &NBytes, Inv);
  352.             }
  353.             else
  354.             {
  355.              InitLitMode(Fp, &NBytes, Inv);
  356.             }
  357.            }
  358.            break;
  359.         default:
  360.            Error("Bad Buffer Mode... Sorry\n");
  361.            break;
  362.       }
  363.      }
  364.      BytesSent += SendBuffer(Inv);
  365.      /* Send out rem'g 2-3 bytes in LITERAL mode. */
  366.      Buffer[0] = CurrByte;
  367.      Buffer[1] = NextByte;
  368.      if (NBytes == 3)
  369.       Buffer[2] = gb(Fp);
  370.      BufCount = NBytes-1;
  371.      BytesSent += SendBuffer(Inv);
  372.      return(BytesSent);
  373. }
  374.  
  375. /******************************************************************************
  376. *    Diagnostic Routines.                              *
  377. ******************************************************************************/
  378. DiagRecLRun(Rlength)
  379. int Rlength;
  380. {
  381. #ifdef DIAGS
  382.      if (Rlength > DiagMaxRunLength)
  383.       DiagMaxRunLength = Rlength;
  384.      DiagSumRunLength += Rlength;
  385.      DiagNumRuns++;
  386. #endif
  387. }
  388.  
  389. Diags()
  390. {
  391. #ifdef DIAGS
  392.      fprintf(stderr, "Longest Run (<= 128) = %d\n", DiagMaxRunLength);
  393.      fprintf(stderr, "Number of Runs over 128 = %d\n", DiagNLongRuns);
  394.      fprintf(stderr, "Average Run Length of %d. (%d Runs)\n",
  395.          (int) DiagSumRunLength / DiagNumRuns, DiagNumRuns);
  396. #endif
  397. }
  398.  
  399. /******************************************************************************
  400. *    PostScript Output Routines.                           *
  401. ******************************************************************************/
  402. PrintPostScriptRoutines(ras_h, ras_w, ras_d, tx, ty, sx, sy, rot)
  403. int ras_h, ras_w, ras_d;
  404. double tx, ty, sx, sy, rot;
  405. {
  406.      fprintf(ofile, "%%!\n/inch {72 mul} def\n");
  407.      fprintf(ofile, "/bpp %d def\n", ras_d);
  408.      fprintf(ofile, "/scanlines %d def\n", ras_h);
  409.      fprintf(ofile, "/scansize %d def\n", ras_w);
  410.      fprintf(ofile, "/bitmapx\n{");
  411.      fprintf(ofile, " %d %d %d [%d 0 0 %d 0 %d] ", ras_w, ras_h, ras_d, ras_w, 
  412.         -ras_h, ras_h);
  413.      fprintf(ofile, "{currentfile readrlehexstring pop } image\n} def\n");
  414.      fprintf(ofile, "gsave\n");
  415.      fprintf(ofile, "%f inch %f inch translate\n",tx, ty);
  416.      fprintf(ofile, "%f rotate\n", rot );
  417.      fprintf(ofile, "%f inch %f inch scale\n", sx, sy);
  418.      fprintf(ofile, "/readrlehexstring\t%% rle_file => decoded_string boolean\n");
  419.      fprintf(ofile, "{\n\t/fileptr exch def\n\tfileptr 1 string readhexstring {");
  420.      fprintf(ofile, "\n\t\t0 get dup 128 and 0 eq\n");
  421.      fprintf(ofile, "\t\t{ 1 add /Buffer exch string def\n");
  422.      fprintf(ofile, "\t\t\tfileptr Buffer readhexstring\n\t\t}\n\t\t{");
  423.      fprintf(ofile, " 256 exch sub /BufCount exch def\n");
  424.      fprintf(ofile, "\t\t\t/Buffer BufCount 1 add string def\n");
  425.      fprintf(ofile, "\t\t\t/RunInt fileptr 1 string readhexstring");
  426.      fprintf(ofile, " pop 0 get def\n");
  427.      fprintf(ofile, "\t\t\t0 1 BufCount { RunInt Buffer 3 1 roll put } for\n");
  428.      fprintf(ofile, "\t\t\tBuffer true\n\t\t} ifelse\n\t}\n\t{ false } ifelse\n");
  429.      fprintf(ofile, "} def\n");
  430.      fprintf(ofile, "/clipathx\n{\tnewpath\n\t0 0 moveto\n\t%f inch 0", sx);
  431.      fprintf(ofile, " lineto\n\t%f inch %f inch lineto\n\t0 %f inch lineto\n",
  432.         sx, sy, sy);
  433.      fprintf(ofile, "\tclosepath\n} def\nclipathx clip\n");
  434.      fprintf(ofile, "bitmapx\n");
  435. }
  436.  
  437. PrintPostScriptClosing()
  438. {     
  439.      fprintf(ofile, "\ngrestore\n");
  440.      fprintf(ofile, "showpage\n");
  441. }
  442.  
  443. /******************************************************************************
  444. *    Error Routine.                                  *
  445. ******************************************************************************/
  446. Error(S1)
  447. char *S1;
  448. {
  449.      *(S1 + strlen(S1)) = '\0';    /* delete trailing \n */
  450.      err_rpt(S1, FATAL);
  451. }
  452. #endif    /* NO_PRINTER */
  453.