/***************************************************************** * pbm2ps.c: FBM Release 1.0 25-Feb-90 Michael Mauldin * * Copyright (C) 1989,1990 by Michael Mauldin. Permission is granted * to use this file in whole or in part for any purpose, educational, * recreational or commercial, provided that this copyright notice * is retained unchanged. This software is available to all free of * charge by anonymous FTP and in the UUNET archives. * * pbm2ps.c: * * USAGE * % pbm2ps [ flags ] arguments * * BUGS * Will blow up if the title has PostScript special characters * in it (especially unbalanced parens) * * EDITLOG * LastEditDate = Sun Jun 24 23:55:37 1990 - Michael Mauldin * LastFileName = /usr2/mlm/src/misc/fbm/pbm2ps.c * * HISTORY * 25-Jun-90 Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon * Package for Release 1.0 * * 16-Jun-89 Michael Mauldin (mlm) at Carnegie Mellon University * Beta release (version 0.95) mlm@cs.cmu.edu * * 14-Sep-88 Michael Mauldin (mlm) at Carnegie-Mellon University * Created. *****************************************************************/ # include # include # define MAXBAD 10 # define USAGE "pbm2ps [ -s ] [ scale ] < pbm > postscript" unsigned char *bits; int w, h; char title[80]; /**************************************************************** * main: Read a pbm format file and write it out as PostScript ****************************************************************/ #ifndef lint static char *fbmid = "$FBM pbm2ps.c <1.0> 25-Jun-90 (C) 1989,1990 by Michael Mauldin, source \ code available free from MLM@CS.CMU.EDU and from UUNET archives$"; #endif main (argc, argv) char *argv[]; { int scale = -1, scribe = 0; /* Get option */ while (--argc > 0 && (*++argv)[0] == '-') { while (*++(*argv)) { switch (**argv) { case 's': scribe++; break; default: fprintf (stderr, "Usage: %s\n", USAGE); exit (1); } } } if (argc > 0 && (scale = atoi (argv[0])) < 1) { fprintf (stderr, USAGE); exit (1); } if (read_pbm (stdin) && write_ps (scale, scribe)) exit (0); exit (1); } /**************************************************************** * read_pbm: Read a pbm bitmap into character array 'bits', setting * width, height, and title ****************************************************************/ read_pbm (rfile) FILE *rfile; { int ch; register unsigned char *bmp, *tail; int badcnt=0; if ((ch = getc (rfile)) != 'P' || (ch = getc (rfile)) != '1') { fprintf (stderr, "bad magic number, input not PBM file\n"); return (0); } title[0] = '\0'; if ((w = pbm_getint (stdin)) < 0 || (h = pbm_getint (stdin)) < 0) { return (0); } bits = (unsigned char *) malloc (w*h); bmp = bits; tail = &bmp[h*w]; /* Read bits, inverting so that 1=white and 0=black */ while (bmp < tail && (ch = getc (rfile)) != EOF) { if (ch == '0') *bmp++ = 1; else if (ch == '1') *bmp++ = 0; else if (ch == '#') eatcomment (); else if (isspace (ch)) /* ignore it */ ; else if (++badcnt < MAXBAD) { fprintf (stderr, "Ignoring junk character '%c'\n", ch); } else { fprintf (stderr, "Too many junk characters, bye!\n"); exit (1); } } if (ch == EOF) { fprintf (stderr, "premature EOF, read %d of %d bits in [%dx%d]\n", (bmp - bits), (tail - bits), w, h); return (0); } return (1); } /***************************************************************** * pbm_getint: Read a number from a PBM file, ignoring comments *****************************************************************/ pbm_getint (rfile) FILE *rfile; { register int ch; register int val = 0; while ((ch = getc (rfile)) != EOF) { if (ch == '#') eatcomment (); else if (isspace (ch)) /* ignore it */ ; else if (isdigit (ch)) break; else { fprintf (stderr, "Found junk character '%c' in header\n", ch); return (-1); } } while (isdigit (ch)) { val = val*10 + ch - '0'; ch = getc (rfile); } return (val); } /***************************************************************** * eatcomment: Read comments and look for titles *****************************************************************/ eatcomment () { char cmtbuf[80]; register char *s; /* Read rest of line, remove trailing newline and skip over leading spaces */ fgets (cmtbuf, sizeof (cmtbuf), stdin); cmtbuf[strlen (cmtbuf) - 1] = '\0'; for (s=cmtbuf; isspace (*s); s++) ; /* If the comment contains the title, squirrel it away */ if (!strncmp (s, "Title: ", 7)) strcpy (title, s+7); fprintf (stderr, "Reading '%s'\n", title); } /**************************************************************** * write_ps: Write out a 1 bit deep bitmap as a PostScript file * * Output is centered with at least 1" left margin, 1/2" right, * top and bottom margins. * * The title is printed in 14 pt Times-Bold centered at the top. * One half inch at the top is reserved for the title ****************************************************************/ # define BYTESPERLINE 32 # define PSRES 300 /* printer resolution, dots per inch */ # define PPINCH 72 /* Points per inch */ # define PAGW 8.5 /* page width 8.5 inches */ # define PAGH 11.0 /* page height 11 inches */ # define MAXW 7.0 /* maximum image width 7 inches */ # define MAXH 9.5 /* maximum image height 9.5 inches */ # define LMRG 1.0 /* left margin 1 inche */ # define BMRG 0.5 /* bottom margin 1/2 inche */ # define TMRG 0.125 /* Title margin, 1/8 inch */ # define FSIZ 14 /* Font size for title (before scaling to 300 dpi) */ write_ps (scale, scribe) int scale, scribe; { register int x, y, k, byte, bytes=0; register unsigned char *bmp = bits; int dotsx, dotsy; double pwidth, pheight, ctrx, ctry; /* Pick the largest scale factor that makes the image fit */ if (scale < 1) { dotsx = (int) MAXW * PSRES / w; dotsy = (int) MAXH * PSRES / h; scale = (dotsx < dotsy) ? dotsx : dotsy; if (scale < 1) scale = 1; } fprintf (stderr, "pbm2ps: scale %d\n", scale); /* Determine width and height of output in inches */ pwidth = (double) w * scale; pheight = (double) h * scale; ctrx = ((double) MAXW / 2.0 + LMRG) * PSRES; ctry = ((double) MAXH / 2.0 + BMRG) * PSRES; printf ("%%%! %s\n\n", title[0] ? title : "PBM to PostScript"); printf ("%lg %lg scale\n", (double) PPINCH / PSRES, (double) PPINCH / PSRES); if (title[0]) { printf ("/centershow { dup stringwidth pop"); printf (" 2 div 0 exch sub 0 rmoveto show } def\n"); printf ("/Times-Bold findfont %lg scalefont setfont\n", (double) FSIZ * PSRES / PPINCH); printf ("%lg %lg moveto\n", ctrx, ctry + pheight / 2.0 + TMRG*PSRES); printf ("(%s) centershow\n\n", title); } printf ("/picstr 32 string def\n"); if (!scribe) { printf ("%lg %lg translate\n", ctrx - pwidth / 2, ctry - pheight / 2); } printf ("%lg %lg scale\n", pwidth, pheight); printf ("%d %d 1 [ %d 0 0 -%d 0 %d ] ", w, h, w, h, h); printf ("{ currentfile picstr readhexstring pop }\n"); printf ("image\n"); for (y=0; y