home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / misc / volume2 / sun2ps / part01 / sun2ps.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-08-07  |  12.6 KB  |  538 lines

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