diff options
Diffstat (limited to 'converter/pbm/pbmtomda.c')
-rw-r--r-- | converter/pbm/pbmtomda.c | 217 |
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; } + + + |