home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / fbm / src / pbm2ps.c < prev    next >
C/C++ Source or Header  |  1990-06-24  |  8KB  |  257 lines

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