about summary refs log tree commit diff
path: root/converter/pbm
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm')
-rw-r--r--converter/pbm/pbmtolps.c277
1 files changed, 157 insertions, 120 deletions
diff --git a/converter/pbm/pbmtolps.c b/converter/pbm/pbmtolps.c
index dcc5badd..e9577ec8 100644
--- a/converter/pbm/pbmtolps.c
+++ b/converter/pbm/pbmtolps.c
@@ -1,27 +1,29 @@
-/*
- * pbmtolps -- convert a Portable BitMap into Postscript.  The
- * output Postscript uses lines instead of the image operator to
- * generate a (device dependent) picture which will be imaged
- * much faster.
- *
- * The Postscript path length is constrained to be at most 1000
- * points so that no limits are overrun on the Apple Laserwriter
- * and (presumably) no other printers.  The typical limit is 1500.
- * See "4.4 Path Construction" and "Appendix B: Implementation Limits"
- * in: PostScript Language Reference Manual
- *     https://www.adobe.com/content/dam/acom/en/devnet/actionscript/
- *             articles/psrefman.pdf
- *
- * To do:
- *      make sure encapsulated format is correct
- *      repitition of black-white strips
- *      make it more device independent (is this possible?)
- *
- * Author:
- *      George Phillips <phillips@cs.ubc.ca>
- *      Department of Computer Science
- *      University of British Columbia
- */
+/*=============================================================================
+                             pbmtolps
+===============================================================================
+
+  Convert a PBM image to Postscript.  The output Postscript uses lines instead
+  of the image operator to generate a (device dependent) picture which will be
+  imaged much faster.
+
+  The Postscript path length is constrained to be at most 1000 vertices so that
+  no limits are overrun on the Apple Laserwriter and (presumably) no other
+  printers.  The typical limit is 1500.  See "4.4 Path Construction" and
+  "Appendix B: Implementation Limits" in: PostScript Language Reference Manual
+  https://www.adobe.com/content/dam/acom/en/devnet/actionscript/
+  articles/psrefman.pdf
+
+  To do:
+       make sure encapsulated format is correct
+       repetition of black-white strips
+       make it more device independent (is this possible?)
+
+  Author:
+       George Phillips <phillips@cs.ubc.ca>
+       Department of Computer Science
+       University of British Columbia
+=============================================================================*/
+#include <stdbool.h>
 
 #include "pm_c_util.h"
 #include "mallocvar.h"
@@ -30,9 +32,9 @@
 #include "pbm.h"
 
 
-static float const MaxDPI = 5000;
-static float const MinDPI = 10;
-static unsigned int const MaxPathPoints = 1000;
+static float        const MAX_DPI           = 5000;
+static float        const MIN_DPI           = 10;
+static unsigned int const MAX_PATH_VERTICES = 1000;
 
 
 struct CmdlineInfo {
@@ -50,6 +52,15 @@ struct CmdlineInfo {
 
 
 static void
+validateDpi(float const dpi) {
+
+    if (dpi > MAX_DPI || dpi < MIN_DPI)
+        pm_error("Specified DPI value out of range (%f)", dpi);
+}
+
+
+
+static void
 parseCommandLine(int                        argc,
                  const char **        const argv,
                  struct CmdlineInfo * const cmdlineP) {
@@ -78,24 +89,26 @@ parseCommandLine(int                        argc,
     pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0);
         /* Uses and sets argc, argv, and some of *cmdlineP and others. */
 
+    if (cmdlineP->dpiSpec)
+        validateDpi(cmdlineP->dpi);
+    else
+        cmdlineP->dpi = 300;
+
     if (argc-1 < 1)
         cmdlineP->inputFileName = "-";
     else {
         if (argc-1 > 1)
             pm_error("Program takes zero or one argument (filename).  You "
-                     "specified %d", argc-1);
-        else                      
-            cmdlineP->inputFileName = argv[1];                     
+                     "specified %u", argc-1);
+        else
+            cmdlineP->inputFileName = argv[1];
     }
 
     if (cmdlineP->inputFileName[0] == '-' &&
         cmdlineP->inputFileName[1] == '\0')
-        cmdlineP->inputFileSpec = FALSE;
-    else 
-        cmdlineP->inputFileSpec = TRUE;
-
-    if (cmdlineP->dpiSpec == FALSE)
-        cmdlineP->dpi = 300;
+        cmdlineP->inputFileSpec = false;
+    else
+        cmdlineP->inputFileSpec = true;
 
     free(option_def);
 }
@@ -114,103 +127,127 @@ validateLineWidth(float const sc_cols,
 
 
 static void
-validateDpi(float const dpi) {
-    if (dpi > MaxDPI || dpi < MinDPI)
-        pm_error("Specified DPI value out of range (%f)", dpi);
-}
+doRaster(FILE *       const ifP,
+         unsigned int const cols,
+         unsigned int const rows,
+         int          const format,
+         FILE *       const ofP) {
 
+    bit *        bitrow;
+    unsigned int row;
+    unsigned int vertexCt;
+        /* Number of vertices drawn since last stroke command */
 
+    bitrow = pbm_allocrow(cols);
 
-int
-main(int argc, const char *argv[]) {
-    FILE*   fp;
-    bit*    bits;
-    int     row;
-    int     col;
-    int     rows;
-    int     cols;
-    int     format;
-    int     white;
-    int     black;
-    float   sc_rows;
-    float   sc_cols;
-    struct CmdlineInfo cmdline;
-    const char* psName;
-    unsigned int pointCnt;
+    for (row = 0, vertexCt = 0; row < rows; ++row) {
+        unsigned int col;
+        bool firstRun;
 
-    pm_proginit(&argc, argv);
-
-    parseCommandLine(argc, argv, &cmdline);
-    
-    if (cmdline.dpi)
-        validateDpi(cmdline.dpi); 
+        firstRun = true;  /* initial value */
 
-    fp = pm_openr(cmdline.inputFileName);
-    pbm_readpbminit(fp, &cols, &rows, &format);
+        pbm_readpbmrow(ifP, bitrow, cols, format);
 
-    sc_rows = (float) rows / cmdline.dpi * 72.0;
-    sc_cols = (float) cols / cmdline.dpi * 72.0;
-    
-    if (cmdline.lineWidthSpec)
-        validateLineWidth(sc_cols, sc_rows, cmdline.lineWidth); 
-
-    bits = pbm_allocrow(cols);
-    psName = cmdline.inputFileSpec ? cmdline.inputFileName : "noname";
-
-    puts("%!PS-Adobe-2.0 EPSF-2.0");
-    puts("%%Creator: pbmtolps");
-    printf("%%%%Title: %s\n", psName);
-    printf("%%%%BoundingBox: %d %d %d %d\n",
-           (int)(305.5 - sc_cols / 2.0),
-           (int)(395.5 - sc_rows / 2.0),
-           (int)(306.5 + sc_cols / 2.0),
-           (int)(396.5 + sc_rows / 2.0));
-    puts("%%EndComments");
-    puts("%%EndProlog");
-    puts("gsave");
-
-    printf("%f %f translate\n", 306.0 - sc_cols / 2.0, 396.0 + sc_rows / 2.0);
-    printf("72 %f div dup neg scale\n", cmdline.dpi);
-    if (cmdline.lineWidthSpec)
-        printf("%f setlinewidth\n", cmdline.lineWidth); 
-    puts("/a { 0 rmoveto 0 rlineto } def");
-    puts("/m { currentpoint stroke newpath moveto } def");
-    puts("newpath 0 0 moveto");
-
-    pointCnt = 0;
-    for (row = 0; row < rows; row++) {
-        bool firstRun = TRUE; /* Initial value */        
-                
-        pbm_readpbmrow(fp, bits, cols, format);
         /* output white-strip + black-strip sequences */
+
         for (col = 0; col < cols; ) {
-        
-            for (white = 0; col < cols && bits[col] == PBM_WHITE; col++)
-                white++;
-            for (black = 0; col < cols && bits[col] == PBM_BLACK; col++)
-                black++;
-
-            if (black != 0) {
-                if (pointCnt > MaxPathPoints) {
-                     printf("m ");
-		     pointCnt = 0;
-		}
-
-                if (firstRun == TRUE) {
-                    printf ("%d %d moveto %d 0 rlineto\n", white, row, black);
-                    firstRun = FALSE;
+            unsigned int whiteCt;
+            unsigned int blackCt;
+
+            for (whiteCt = 0; col < cols && bitrow[col] == PBM_WHITE; ++col)
+                ++whiteCt;
+            for (blackCt = 0; col < cols && bitrow[col] == PBM_BLACK; ++col)
+                ++blackCt;
+
+            if (blackCt > 0) {
+                if (vertexCt > MAX_PATH_VERTICES) {
+                    printf("m ");
+                    vertexCt = 0;
                 }
-                else
-                    printf("%d %d a\n", black, white);
 
-                pointCnt += 2;
+                if (firstRun) {
+                    printf("%u %u moveto %u 0 rlineto\n",
+                           whiteCt, row, blackCt);
+                    firstRun = false;
+                } else
+                    printf("%u %u a\n", blackCt, whiteCt);
+
+                vertexCt += 2;
             }
         }
     }
-    puts("stroke grestore showpage");
-    puts("%%Trailer");
+    pbm_freerow(bitrow);
+}
+
+
+
+static void
+pbmtolps(FILE * const ifP,
+         FILE * const ofP,
+         struct CmdlineInfo const cmdline) {
+
+    const char * const psName =
+        cmdline.inputFileSpec ? cmdline.inputFileName : "noname";
+
+    int          rows;
+    int          cols;
+    int          format;
+    float        scRows;
+    float        scCols;
+
+    pbm_readpbminit(ifP, &cols, &rows, &format);
+
+    scRows = (float) rows / cmdline.dpi * 72.0;
+    scCols = (float) cols / cmdline.dpi * 72.0;
+
+    if (cmdline.lineWidthSpec)
+        validateLineWidth(scCols, scRows, cmdline.lineWidth);
+
+    fputs("%!PS-Adobe-2.0 EPSF-2.0\n", ofP);
+    fputs("%%Creator: pbmtolps\n", ofP);
+    fprintf(ofP, "%%%%Title: %s\n", psName);
+    fprintf(ofP, "%%%%BoundingBox: %d %d %d %d\n",
+           (int)(305.5 - scCols / 2.0),
+           (int)(395.5 - scRows / 2.0),
+           (int)(306.5 + scCols / 2.0),
+           (int)(396.5 + scRows / 2.0));
+    fputs("%%EndComments\n", ofP);
+    fputs("%%EndProlog\n", ofP);
+    fputs("gsave\n", ofP);
+
+    fprintf(ofP, "%f %f translate\n",
+            306.0 - scCols / 2.0, 396.0 + scRows / 2.0);
+    fprintf(ofP, "72 %f div dup neg scale\n", cmdline.dpi);
+
+    if (cmdline.lineWidthSpec)
+        fprintf(ofP, "%f setlinewidth\n", cmdline.lineWidth);
+
+    fputs("/a { 0 rmoveto 0 rlineto } def\n", ofP);
+    fputs("/m { currentpoint stroke newpath moveto } def\n", ofP);
+    fputs("newpath 0 0 moveto\n", ofP);
+
+    doRaster(ifP, cols, rows, format, ofP);
+
+    fputs("stroke grestore showpage\n", ofP);
+    fputs("%%Trailer\n", ofP);
+}
+
+
+
+int
+main(int argc, const char *argv[]) {
+    FILE *  ifP;
+    struct CmdlineInfo cmdline;
+
+    pm_proginit(&argc, argv);
+
+    parseCommandLine(argc, argv, &cmdline);
+
+    ifP = pm_openr(cmdline.inputFileName);
+
+    pbmtolps(ifP, stdout, cmdline);
 
-    pm_close(fp);
+    pm_close(ifP);
 
-    exit(0);
+    return 0;
 }