about summary refs log tree commit diff
path: root/converter/pbm/pbmtomda.c
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm/pbmtomda.c')
-rw-r--r--converter/pbm/pbmtomda.c217
1 files changed, 123 insertions, 94 deletions
diff --git a/converter/pbm/pbmtomda.c b/converter/pbm/pbmtomda.c
index 3ad51499..f684276f 100644
--- a/converter/pbm/pbmtomda.c
+++ b/converter/pbm/pbmtomda.c
@@ -1,7 +1,6 @@
-
 /***************************************************************************
 
-    PBMTOMDA: Convert portable bitmap to Microdesign area
+    PBMTOMDA: Convert PBM to Microdesign area
     Copyright (C) 1999,2004 John Elliott <jce@seasip.demon.co.uk>
 
     This program is free software; you can redistribute it and/or modify
@@ -20,31 +19,78 @@
 
 ******************************************************************************/
 
+#include <stdbool.h>
+#include <assert.h>
 #include <stdio.h>
 #include <string.h>
 
 #include "pbm.h"
 #include "mallocvar.h"
+#include "shhopt.h"
+
+struct CmdlineInfo {
+    /* All the information the user supplied in the command line,
+       in a form easy for the program to use.
+    */
+    const char * inputFileNm;
+    unsigned int dscale;
+    unsigned int invert;
+};
+
+
+static void
+parseCommandLine(int argc, const char ** argv,
+                 struct CmdlineInfo * const cmdlineP) {
+/*----------------------------------------------------------------------------
+   Note that the file spec array we return is stored in the storage that
+   was passed to as as the argv array.
+-----------------------------------------------------------------------------*/
+    optEntry * option_def;
+    optStruct3 opt;
+
+    unsigned int option_def_index;
+
+    MALLOCARRAY_NOFAIL(option_def, 100);
+
+    option_def_index = 0;   /* incremented by OPTENT3 */
+    OPTENT3(0,   "dscale", OPT_FLAG,  NULL, &cmdlineP->dscale,   0);
+    OPTENT3(0,   "invert", OPT_FLAG,  NULL, &cmdlineP->invert,   0);
+
+    opt.opt_table     = option_def;
+    opt.short_allowed = false; /* We have no short (old-fashioned) options */
+    opt.allowNegNum   = false; /* We have no parms that are negative numbers */
+
+    pm_optParseOptions4(&argc, argv, opt, sizeof(opt), 0);
+        /* Uses and sets argc, argv, and some of *cmdlineP and others */
+
+    if (argc-1 < 1)
+        cmdlineP->inputFileNm = "-";
+    else if (argc-1 == 1)
+        cmdlineP->inputFileNm = argv[1];
+    else
+        pm_error("Program takes at most one argument:  input file name");
+
+    free(option_def);
+}
+
 
-/* I'm being somewhat conservative in the PBM -> MDA translation. I output 
+
+/* I'm being somewhat conservative in the PBM -> MDA translation. I output
  * only the MD2 format and don't allow RLE over the ends of lines.
  */
 
-typedef unsigned char mdbyte;
-
-static FILE *infile;
-static mdbyte header[128];
-static int bInvert = 0;
-static int bScale  = 0;
+typedef unsigned char Mdbyte;
 
 /* Encode 8 pixels as a byte */
 
-static mdbyte 
-encode(bit ** const bits, int const row, int const col)
-{
+static Mdbyte
+encode(bit ** const bits,
+       int    const row,
+       int    const col) {
+
     int n;
     int mask;
-    mdbyte b;
+    Mdbyte b;
 
     mask = 0x80;   /* initial value */
     b = 0;  /* initial value */
@@ -56,131 +102,110 @@ encode(bit ** const bits, int const row, int const col)
     return b;
 }
 
-/* Translate a pbm to MD2 format, one row at a time */
 
-static void 
-do_translation(bit ** const bits, 
-               int    const nOutCols, 
-               int    const nOutRows,
-               int    const nInRows)
-{
-    int row;
-    mdbyte *mdrow;  /* malloc'ed */
 
-    int const step = bScale ? 2 : 1;
+static void
+doTranslation(bit **       const bits,
+              unsigned int const nOutCols,
+              unsigned int const nOutRows,
+              unsigned int const nInRows,
+              bool         const mustInvert,
+              bool         const mustScale) {
+/*----------------------------------------------------------------------------
+  Translate a pbm to MD2 format, one row at a time
+-----------------------------------------------------------------------------*/
+    unsigned int const step = mustScale ? 2 : 1;
+
+    unsigned int row;
+    Mdbyte * mdrow;  /* malloc'ed */
 
     MALLOCARRAY(mdrow, nOutCols);
 
     if (mdrow == NULL)
-        pm_error("Not enough memory for conversion.");
+        pm_error("Unable to allocate memory for %u columns", nOutCols);
 
-    for (row = 0; row < nOutRows; row+=step)
-    {
-        int col;
-        int x1;
+    for (row = 0; row < nOutRows; row += step) {
+        unsigned int col;
 
         /* Encode image into non-compressed bitmap */
         for (col = 0; col < nOutCols; ++col) {
-            mdbyte b;
+            Mdbyte b;
 
             if (row < nInRows)
-                b = encode(bits, row, col*8);
+                b = encode(bits, row, col * 8);
             else
                 b = 0xff;  /* All black */
 
-            mdrow[col] = bInvert ? b : ~b;
+            mdrow[col] = mustInvert ? b : ~b;
         }
 
         /* Encoded. Now RLE it */
-        for (col = 0; col < nOutCols; )
-        {
-            mdbyte const b = mdrow[col];
+        for (col = 0; col < nOutCols; ) {
+            Mdbyte const b = mdrow[col];
 
-            if (b != 0xFF && b != 0) /* Normal byte */
-            {
+            if (b != 0xFF && b != 0) {
+                /* Normal byte */
                 putchar(b);
                 ++col;
-            }
-            else    /* RLE a run of 0s or 0xFFs */
-            {
-                for (x1 = col; x1 < nOutCols; x1++)
-                {
+            } else {
+                /* RLE a run of 0s or 0xFFs */
+
+                unsigned int x1;
+
+                for (x1 = col; x1 < nOutCols; ++x1) {
                     if (mdrow[x1] != b) break;
+                    assert(x1 >= col);
                     if (x1 - col > 256) break;
                 }
+                assert(x1 >= col);
                 x1 -= col;    /* x1 = no. of repeats */
                 if (x1 == 256) x1 = 0;
                 putchar(b);
                 putchar(x1);
-                col += x1;        
-            }   
+                col += x1;
+            }
         }
     }
     free(mdrow);
 }
 
 
-static void usage(char *s)
-{        
-    printf("pbmtomda v1.01, Copyright (C) 1999,2004 John Elliott <jce@seasip.demon.co.uk>\n"
-         "This program is redistributable under the terms of the GNU General Public\n"
-                 "License, version 2 or later.\n\n"
-                 "Usage: %s [ -d ] [ -i ] [ -- ] [ infile ]\n\n"
-                 "-d: Halve height (to compensate for the PCW aspect ratio)\n"
-                 "-i: Invert colors\n"
-                 "--: No more options (use if filename begins with a dash)\n",
-        s);
 
-    exit(0);
-}
+int
+main(int argc, const char ** argv) {
+
+    const char * const headerValue = ".MDAMicroDesignPCWv1.00\r\npbm2mda\r\n";
 
-int main(int argc, char **argv)
-{
-    int nOutRowsUnrounded;  /* Before rounding up to multiple of 4 */
-    int nOutCols, nOutRows;
+    struct CmdlineInfo cmdline;
+    FILE * ifP;
+    unsigned int nOutRowsUnrounded;  /* Before rounding up to multiple of 4 */
+    unsigned int nOutCols, nOutRows;
     int nInCols, nInRows;
-    bit **bits;
+    bit ** bits;
+    Mdbyte header[128];
     int rc;
 
-    int n, optstop = 0;
-    char *fname = NULL;
+    pm_proginit(&argc, argv);
 
-    pbm_init(&argc, argv);
+    parseCommandLine(argc, argv, &cmdline);
 
     /* Output v2-format MDA images. Simulate MDA header...
-     * 2004-01-11: Hmm. Apparently some (but not all) MDA-reading 
-     * programs insist on the program identifier being exactly 
+     * 2004-01-11: Hmm. Apparently some (but not all) MDA-reading
+     * programs insist on the program identifier being exactly
      * 'MicroDesignPCW'. The spec does not make this clear. */
-    strcpy((char*) header, ".MDAMicroDesignPCWv1.00\r\npbm2mda\r\n");
-
-    for (n = 1; n < argc; n++)
-    {
-        if (argv[n][0] == '-' && !optstop)
-        {   
-            if (argv[n][1] == 'd' || argv[n][1] == 'D') bScale = 1;
-            if (argv[n][1] == 'i' || argv[n][1] == 'I') bInvert = 1;
-            if (argv[n][1] == 'h' || argv[n][1] == 'H') usage(argv[0]);
-            if (argv[n][1] == '-' && argv[n][2] == 0 && !fname)     /* "--" */
-            {
-                optstop = 1;
-            }
-            if (argv[n][1] == '-' && (argv[n][2] == 'h' || argv[n][2] == 'H')) usage(argv[0]);
-        }
-        else if (argv[n][0] && !fname)  /* Filename */
-        {
-            fname = argv[n];
-        }
-    }
+    memcpy(header + 0, headerValue, strlen(headerValue));
+    memset(header + strlen(headerValue),
+           0x00,
+           sizeof(header)-strlen(headerValue));
 
-    if (fname) infile = pm_openr(fname);
-    else       infile = stdin;
+    ifP = pm_openr(cmdline.inputFileNm);
 
-    bits = pbm_readpbm(infile, &nInCols, &nInRows);
-    
-    nOutRowsUnrounded = bScale ? nInRows/2 : nInRows;
+    bits = pbm_readpbm(ifP, &nInCols, &nInRows);
+
+    nOutRowsUnrounded = cmdline.dscale ? nInRows/2 : nInRows;
 
     nOutRows = ((nOutRowsUnrounded + 3) / 4) * 4;
-        /* MDA wants rows a multiple of 4 */   
+        /* MDA wants rows a multiple of 4 */
     nOutCols = nInCols / 8;
 
     rc = fwrite(header, 1, 128, stdout);
@@ -191,11 +216,15 @@ int main(int argc, char **argv)
     pm_writelittleshort(stdout, nOutRows);
     pm_writelittleshort(stdout, nOutCols);
 
-    do_translation(bits, nOutCols, nOutRows, nInRows);
+    doTranslation(bits, nOutCols, nOutRows, nInRows,
+                  !!cmdline.invert, !!cmdline.dscale);
 
-    pm_close(infile);
+    pm_close(ifP);
     fflush(stdout);
     pbm_freearray(bits, nInRows);
-    
+
     return 0;
 }
+
+
+