home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume19 / fbm / part05 / pbm2ps.c < prev   
Encoding:
C/C++ Source or Header  |  1989-06-08  |  7.1 KB  |  251 lines

  1. /*****************************************************************
  2.  * pbm2ps.c: FBM Library 0.9 (Beta test) 07-Mar-89  Michael Mauldin
  3.  *
  4.  * Copyright (C) 1989 by Michael Mauldin.  Permission is granted to
  5.  * use this file in whole or in part provided that you do not sell it
  6.  * for profit and that this copyright notice is retained unchanged.
  7.  *
  8.  * pbm2ps.c: 
  9.  *
  10.  * USAGE
  11.  *    % pbm2ps [ flags ] arguments
  12.  *
  13.  * BUGS
  14.  *    Will blow up if the title has PostScript special characters
  15.  *    in it (especially unbalanced parens)
  16.  *
  17.  * EDITLOG
  18.  *    LastEditDate = Wed Mar  8 14:23:08 1989 - Michael Mauldin
  19.  *    LastFileName = /usr2/mlm/src/misc/fbm/pbm2ps.c
  20.  *
  21.  * HISTORY
  22.  * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
  23.  *    Beta release (version 0.9) mlm@cs.cmu.edu
  24.  *
  25.  * 14-Sep-88  Michael Mauldin (mlm) at Carnegie-Mellon University
  26.  *    Created.
  27.  *****************************************************************/
  28.  
  29. # include <stdio.h>
  30. # include <ctype.h>
  31.  
  32. # define MAXBAD 10
  33.  
  34. # define USAGE "Usage: pbm2ps [ -s ] [ scale ] < pbm > postscript"
  35.  
  36. unsigned char    *bits;
  37. int         w, h;
  38. char         title[80];
  39.  
  40. /****************************************************************
  41.  * main: Read a pbm format file and write it out as PostScript
  42.  ****************************************************************/
  43.  
  44. #ifndef lint
  45. static char *fbmid =
  46.     "$FBM pbm2ps.c <0.9> 07-Mar-89  (C) 1989 by Michael Mauldin$";
  47. #endif
  48.  
  49. main (argc, argv)
  50. char *argv[];
  51. { int scale = -1, scribe = 0;
  52.  
  53.   /* Get option */
  54.   while (--argc > 0 && (*++argv)[0] == '-')
  55.   { while (*++(*argv))
  56.     { switch (**argv)
  57.       { case 's':    scribe++; break;
  58.     default:    fprintf (stderr, USAGE);
  59.             exit (1);
  60.       }
  61.     }
  62.   }
  63.  
  64.   if (argc > 0 && (scale = atoi (argv[0])) < 1)
  65.   { fprintf (stderr, USAGE); exit (1); }
  66.  
  67.   if (read_pbm (stdin) && write_ps (scale, scribe)) exit (0);
  68.  
  69.   exit (1);
  70. }
  71.  
  72. /****************************************************************
  73.  * read_pbm: Read a pbm bitmap into character array 'bits', setting
  74.  *         width, height, and title
  75.  ****************************************************************/
  76.  
  77. read_pbm (rfile)
  78. FILE *rfile;
  79. { int ch;
  80.   register unsigned char *bmp, *tail;
  81.   int badcnt=0;
  82.  
  83.   if ((ch = getc (rfile)) != 'P' || (ch = getc (rfile)) != '1')
  84.   { fprintf (stderr, "bad magic number, input not PBM file\n");
  85.     return (0);
  86.   }
  87.  
  88.   title[0] = '\0';
  89.  
  90.   if ((w = pbm_getint (stdin)) < 0 || (h = pbm_getint (stdin)) < 0)
  91.   { return (0); }
  92.  
  93.   bits = (unsigned char *) malloc (w*h);
  94.   
  95.   bmp = bits;
  96.   tail = &bmp[h*w];
  97.   
  98.   /* Read bits, inverting so that 1=white and 0=black */
  99.   while (bmp < tail && (ch = getc (rfile)) != EOF)
  100.   { if (ch == '0') *bmp++ = 1;
  101.     else if (ch == '1') *bmp++ = 0;
  102.     else if (ch == '#') eatcomment ();
  103.     else if (isspace (ch)) /* ignore it */ ;
  104.     else if (++badcnt < MAXBAD)
  105.     { fprintf (stderr, "Ignoring junk character '%c'\n", ch); }
  106.     else
  107.     { fprintf (stderr, "Too many junk characters, bye!\n"); exit (1); }
  108.   }
  109.  
  110.   if (ch == EOF)
  111.   { fprintf (stderr, "premature EOF, read %d of %d bits in [%dx%d]\n",
  112.         (bmp - bits), (tail - bits), w, h);
  113.     return (0);
  114.   }
  115.   
  116.   return (1);
  117. }
  118.  
  119. /*****************************************************************
  120.  * pbm_getint: Read a number from a PBM file, ignoring comments
  121.  *****************************************************************/
  122.  
  123. pbm_getint (rfile)
  124. FILE *rfile;
  125. { register int ch;
  126.   register int val = 0;
  127.  
  128.   while ((ch = getc (rfile)) != EOF)
  129.   { if (ch == '#') eatcomment ();
  130.     else if (isspace (ch)) /* ignore it */ ;
  131.     else if (isdigit (ch)) break;
  132.     else
  133.     { fprintf (stderr, "Found junk character '%c' in header\n", ch);
  134.       return (-1);
  135.     }
  136.   }
  137.  
  138.   while (isdigit (ch))
  139.   { val = val*10 + ch - '0';
  140.     ch = getc (rfile);
  141.   }
  142.   
  143.   return (val);
  144. }
  145.  
  146. /*****************************************************************
  147.  * eatcomment: Read comments and look for titles
  148.  *****************************************************************/
  149.  
  150. eatcomment ()
  151. { char cmtbuf[80];
  152.   register char *s;
  153.  
  154.   /* Read rest of line, remove trailing newline and skip over leading spaces */
  155.   fgets (cmtbuf, sizeof (cmtbuf), stdin);
  156.   cmtbuf[strlen (cmtbuf) - 1] = '\0';
  157.   for (s=cmtbuf; isspace (*s); s++) ;
  158.  
  159.   /* If the comment contains the title, squirrel it away */
  160.   if (!strncmp (s, "Title: ", 7)) strcpy (title, s+7);
  161.   fprintf (stderr, "Reading '%s'\n", title);
  162. }
  163.  
  164. /****************************************************************
  165.  * write_ps: Write out a 1 bit deep bitmap as a PostScript file
  166.  *
  167.  * Output is centered with at least 1" left margin, 1/2" right,
  168.  * top and bottom margins.
  169.  *
  170.  * The title is printed in 14 pt Times-Bold centered at the top.
  171.  * One half inch at the top is reserved for the title
  172.  ****************************************************************/
  173.  
  174. # define BYTESPERLINE 32
  175. # define PSRES 300    /* printer resolution, dots per inch */
  176. # define PPINCH 72    /* Points per inch */
  177. # define PAGW 8.5    /* page width 8.5 inches */
  178. # define PAGH 11.0    /* page height 11 inches */
  179. # define MAXW 7.0    /* maximum image width 7 inches */
  180. # define MAXH 9.5    /* maximum image height 9.5 inches */
  181. # define LMRG 1.0    /* left margin 1 inche */
  182. # define BMRG 0.5    /* bottom margin 1/2 inche */
  183. # define TMRG 0.125    /* Title margin, 1/8 inch */
  184. # define FSIZ 14    /* Font size for title (before scaling to 300 dpi) */
  185.  
  186. write_ps (scale, scribe)
  187. int scale, scribe;
  188. { register int x, y, k, byte, bytes=0;
  189.   register unsigned char *bmp = bits;
  190.   int dotsx, dotsy;
  191.   double pwidth, pheight, ctrx, ctry;
  192.  
  193.   /* Pick the largest scale factor that makes the image fit */
  194.   if (scale < 1)
  195.   { dotsx = (int) MAXW * PSRES / w;
  196.     dotsy = (int) MAXH * PSRES / h;
  197.     scale = (dotsx < dotsy) ? dotsx : dotsy;
  198.     if (scale < 1) scale = 1;
  199.   }
  200.  
  201.   fprintf (stderr, "pbm2ps: scale %d\n", scale);
  202.  
  203.   /* Determine width and height of output in inches */  
  204.   pwidth = (double) w * scale;
  205.   pheight = (double) h * scale;
  206.   ctrx = ((double) MAXW / 2.0 + LMRG) * PSRES;
  207.   ctry = ((double) MAXH / 2.0 + BMRG) * PSRES;
  208.  
  209.   printf ("%%%! %s\n\n", title[0] ? title : "PBM to PostScript");
  210.   printf ("%lg %lg scale\n", (double) PPINCH / PSRES, (double) PPINCH / PSRES);
  211.   if (title[0])
  212.   { printf ("/centershow { dup stringwidth pop");
  213.     printf (" 2 div 0 exch sub 0 rmoveto show } def\n");
  214.     printf ("/Times-Bold findfont %lg scalefont setfont\n",
  215.         (double) FSIZ * PSRES / PPINCH);
  216.     printf ("%lg %lg moveto\n",
  217.         ctrx, ctry + pheight / 2.0 + TMRG*PSRES);
  218.     printf ("(%s) centershow\n\n", title);
  219.   }
  220.  
  221.   printf ("/picstr 32 string def\n");
  222.  
  223.   if (!scribe)
  224.   { printf ("%lg %lg translate\n", ctrx - pwidth / 2, ctry - pheight / 2); }
  225.   printf ("%lg %lg scale\n", pwidth, pheight);
  226.   printf ("%d %d 1 [ %d 0 0 -%d 0 %d ] ", w, h, w, h, h);
  227.   printf ("{ currentfile picstr readhexstring pop }\n");
  228.   printf ("image\n");
  229.  
  230.   for (y=0; y<h; y++)
  231.   { for (x=0; x<w; x += 8)
  232.     { byte = 0;
  233.       for (k=0; k<8; k++)
  234.       { byte = (byte << 1) | (((x+k) < w) ? *bmp++ : 0); }
  235.  
  236.       printf ("%02x", byte);
  237.       if (++bytes % BYTESPERLINE == 0) printf ("\n");
  238.     }
  239.   }
  240.   
  241.   /* Pad so there are exactly BYTESPERLINE bytes in each line */
  242.   if (bytes % BYTESPERLINE)
  243.   { while (bytes++ % BYTESPERLINE) printf ("00");
  244.     printf ("\n");
  245.   }
  246.  
  247.   if (!scribe) printf ("showpage\n");
  248.  
  249.   return (1);  
  250. }
  251.