diff options
Diffstat (limited to 'converter/pbm')
-rw-r--r-- | converter/pbm/g3topbm.c | 181 | ||||
-rw-r--r-- | converter/pbm/mdatopbm.c | 267 | ||||
-rw-r--r-- | converter/pbm/pbmto4425.c | 219 | ||||
-rw-r--r-- | converter/pbm/pbmtolj.c | 34 | ||||
-rw-r--r-- | converter/pbm/pbmtomda.c | 217 | ||||
-rw-r--r-- | converter/pbm/pbmtoppa/pbmtoppa.c | 209 | ||||
-rw-r--r-- | converter/pbm/pbmtoxbm.c | 145 | ||||
-rw-r--r-- | converter/pbm/pktopbm.c | 830 | ||||
-rw-r--r-- | converter/pbm/thinkjettopbm.l | 8 | ||||
-rw-r--r-- | converter/pbm/ybmtopbm.c | 5 |
10 files changed, 1251 insertions, 864 deletions
diff --git a/converter/pbm/g3topbm.c b/converter/pbm/g3topbm.c index 5db507a3..f9655fce 100644 --- a/converter/pbm/g3topbm.c +++ b/converter/pbm/g3topbm.c @@ -21,6 +21,8 @@ #define _DEFAULT_SOURCE /* New name for SVID & BSD source defines */ #define _BSD_SOURCE /* Make nstring.h define strcaseeq() */ +#include <assert.h> + #include "pm_c_util.h" #include "pbm.h" #include "shhopt.h" @@ -71,10 +73,6 @@ The receiver may be less patient. It may opt to disconnect if one row is not received within 5 seconds. */ -static G3TableEntry * whash[HASHSIZE]; -static G3TableEntry * bhash[HASHSIZE]; - - struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. @@ -85,6 +83,7 @@ struct CmdlineInfo { unsigned int stretch; unsigned int stop_error; unsigned int expectedLineSize; + unsigned int correctlong; }; @@ -120,6 +119,8 @@ parseCommandLine(int argc, const char ** const argv, &widthSpec, 0); OPTENT3(0, "paper_size", OPT_STRING, &paperSize, &paper_sizeSpec, 0); + OPTENT3(0, "correctlong", OPT_FLAG, NULL, &cmdlineP->correctlong, + 0); opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ @@ -163,6 +164,11 @@ parseCommandLine(int argc, const char ** const argv, +typedef struct { + const G3TableEntry * whash[HASHSIZE]; + const G3TableEntry * bhash[HASHSIZE]; +} BwHash; + struct BitStream { FILE * fileP; @@ -275,16 +281,16 @@ skipToNextLine(struct BitStream * const bitStreamP) { static void -addtohash(G3TableEntry * hash[], - G3TableEntry table[], - unsigned int const n, - int const a, - int const b) { +addtohash(const G3TableEntry ** const hash, + const G3TableEntry * const table, + unsigned int const n, + int const a, + int const b) { unsigned int i; for (i = 0; i < n; ++i) { - G3TableEntry * const teP = &table[i*2]; + const G3TableEntry * const teP = &table[i*2]; unsigned int const pos = ((teP->length + a) * (teP->code + b)) % HASHSIZE; if (hash[pos]) @@ -295,38 +301,51 @@ addtohash(G3TableEntry * hash[], -static G3TableEntry * -hashfind(G3TableEntry * hash[], - int const length, - int const code, - int const a, - int const b) { +static const G3TableEntry * +hashfind(const G3TableEntry * const * const hash, + unsigned int const length, + int const code, + int const a, + int const b) { - unsigned int pos; - G3TableEntry * te; + unsigned int const pos = ((length + a) * (code + b)) % HASHSIZE; + const G3TableEntry * const teP = hash[pos]; - pos = ((length + a) * (code + b)) % HASHSIZE; - te = hash[pos]; - return ((te && te->length == length && te->code == code) ? te : NULL); + return ((teP && teP->length == length && teP->code == code) ? teP : NULL); } -static void -buildHashes(G3TableEntry * (*whashP)[HASHSIZE], - G3TableEntry * (*bhashP)[HASHSIZE]) { +static BwHash * +newBwHash() { - unsigned int i; + BwHash * bwHashP; - for (i = 0; i < HASHSIZE; ++i) - (*whashP)[i] = (*bhashP)[i] = NULL; + MALLOCVAR(bwHashP); - addtohash(*whashP, &g3ttable_table[0], 64, WHASHA, WHASHB); - addtohash(*whashP, &g3ttable_mtable[2], 40, WHASHA, WHASHB); + if (!bwHashP) + pm_error("Unable to allocate memory for hashes"); + else { + unsigned int i; + /* Initialize */ + for (i = 0; i < HASHSIZE; ++i) + bwHashP->whash[i] = bwHashP->bhash[i] = NULL; - addtohash(*bhashP, &g3ttable_table[1], 64, BHASHA, BHASHB); - addtohash(*bhashP, &g3ttable_mtable[3], 40, BHASHA, BHASHB); + addtohash(bwHashP->whash, &g3ttable_table [0], 64, WHASHA, WHASHB); + addtohash(bwHashP->whash, &g3ttable_mtable[2], 40, WHASHA, WHASHB); + addtohash(bwHashP->bhash, &g3ttable_table [1], 64, BHASHA, BHASHB); + addtohash(bwHashP->bhash, &g3ttable_mtable[3], 40, BHASHA, BHASHB); + } + return bwHashP; +} + + + +static void +freeBwHash(BwHash * const bwHashP) { + + free(bwHashP); } @@ -342,10 +361,11 @@ makeRowWhite(unsigned char * const packedBitrow, -static G3TableEntry * -g3code(unsigned int const curcode, - unsigned int const curlen, - bit const color) { +static const G3TableEntry * +g3code(unsigned int const curcode, + unsigned int const curlen, + bit const color, + const BwHash * const bwHashP) { /*---------------------------------------------------------------------------- Return the position in the code tables mtable and ttable of the G3 code which is the 'curlen' bits long with value 'curcode'. @@ -353,20 +373,20 @@ g3code(unsigned int const curcode, Note that it is the _position_ in the table that determines the meaning of the code. The contents of the table entry do not. -----------------------------------------------------------------------------*/ - G3TableEntry * retval; + const G3TableEntry * retval; switch (color) { case PBM_WHITE: if (curlen < 4) retval = NULL; else - retval = hashfind(whash, curlen, curcode, WHASHA, WHASHB); + retval = hashfind(bwHashP->whash, curlen, curcode, WHASHA, WHASHB); break; case PBM_BLACK: if (curlen < 2) retval = NULL; else - retval = hashfind(bhash, curlen, curcode, BHASHA, BHASHB); + retval = hashfind(bwHashP->bhash, curlen, curcode, BHASHA, BHASHB); break; default: pm_error("INTERNAL ERROR: color is not black or white"); @@ -481,6 +501,7 @@ formatBadCodeException(const char ** const exceptionP, static void readFaxRow(struct BitStream * const bitStreamP, unsigned char * const packedBitrow, + BwHash * const bwHashP, unsigned int * const lineLengthP, const char ** const exceptionP, const char ** const errorP) { @@ -561,7 +582,7 @@ readFaxRow(struct BitStream * const bitStreamP, done = TRUE; } else if (curcode != 0) { const G3TableEntry * const teP = - g3code(curcode, curlen, currentColor); + g3code(curcode, curlen, currentColor, bwHashP); /* Address of structure that describes the current G3 code. Null means 'curcode' isn't a G3 code yet (probably just the beginning of one) @@ -644,16 +665,21 @@ typedef struct { */ bool warned; /* We have warned the user that he has a line length problem */ + bool tolerateErrors; /* Try to continue when we detect a line size error, as opposed to aborting the program. */ -} lineSizeAnalyzer; + unsigned int lineSizeCt[MAXCOLS+1]; + /* Histogram of line sizes in image -- lineSizeCt[i] is the number + of lines we've seen of size i. + */ +} LineSizeAnalyzer; static void -initializeLineSizeAnalyzer(lineSizeAnalyzer * const analyzerP, +initializeLineSizeAnalyzer(LineSizeAnalyzer * const analyzerP, unsigned int const expectedLineSize, bool const tolerateErrors) { @@ -662,12 +688,19 @@ initializeLineSizeAnalyzer(lineSizeAnalyzer * const analyzerP, analyzerP->maxLineSize = 0; analyzerP->warned = FALSE; + + { + unsigned int i; + + for (i = 0; i < MAXCOLS; ++i) + analyzerP->lineSizeCt[i] = 0; + } } static void -analyzeLineSize(lineSizeAnalyzer * const analyzerP, +analyzeLineSize(LineSizeAnalyzer * const analyzerP, unsigned int const thisLineSize) { const char * error; @@ -700,6 +733,45 @@ analyzeLineSize(lineSizeAnalyzer * const analyzerP, pm_strfree(error); } analyzerP->maxLineSize = MAX(thisLineSize, analyzerP->maxLineSize); + + assert(thisLineSize <= MAXCOLS); + ++analyzerP->lineSizeCt[thisLineSize]; +} + + + +static unsigned int +imageLineSize(const LineSizeAnalyzer * const lineSizeAnalyzerP, + bool const mustCorrectLongLine) { +/*---------------------------------------------------------------------------- + The width of the fax in pixels, based on the analysis of the image + *lineSizeAnalyzerP. + + Zero if the fax contains no lines. +-----------------------------------------------------------------------------*/ + unsigned int retval; + + if (mustCorrectLongLine) { + /* Assume that long lines are actually concatenation of two + lines because the EOL code that was supposed to separate them + got lost. + + Assume the most common line length in the image is the correct line + length for the image and that other line lengths are due to + corruption + */ + unsigned int modeSoFar; + unsigned int i; + + for (i = 0, modeSoFar = 0; i <= MAXCOLS; ++i) { + if (lineSizeAnalyzerP->lineSizeCt[i] > modeSoFar) + modeSoFar = i; + } + retval = modeSoFar; + } else { + retval = lineSizeAnalyzerP->maxLineSize; + } + return retval; } @@ -717,12 +789,14 @@ static void readFax(struct BitStream * const bitStreamP, bool const stretch, unsigned int const expectedLineSize, - bool const tolerateErrors, + bool const mustTolerateErrors, + bool const mustCorrectLongLine, + BwHash * const bwHashP, unsigned char *** const packedBitsP, unsigned int * const colsP, unsigned int * const rowsP) { - lineSizeAnalyzer lineSizeAnalyzer; + LineSizeAnalyzer lineSizeAnalyzer; unsigned char ** packedBits; const char * error; bool eof; @@ -731,7 +805,7 @@ readFax(struct BitStream * const bitStreamP, MALLOCARRAY_NOFAIL(packedBits, MAXROWS); initializeLineSizeAnalyzer(&lineSizeAnalyzer, - expectedLineSize, tolerateErrors); + expectedLineSize, mustTolerateErrors); eof = FALSE; error = NULL; @@ -747,10 +821,10 @@ readFax(struct BitStream * const bitStreamP, const char * exception; packedBits[row] = pbm_allocrow_packed(MAXCOLS); - readFaxRow(bitStreamP, packedBits[row], + readFaxRow(bitStreamP, packedBits[row], bwHashP, &lineSize, &exception, &error); - handleRowException(exception, error, row, tolerateErrors); + handleRowException(exception, error, row, mustTolerateErrors); if (!error) { if (lineSize == 0) { @@ -774,7 +848,8 @@ readFax(struct BitStream * const bitStreamP, } } *rowsP = row; - *colsP = lineSizeAnalyzer.maxLineSize; + *colsP = imageLineSize(&lineSizeAnalyzer, mustCorrectLongLine); + *packedBitsP = packedBits; } @@ -788,6 +863,7 @@ main(int argc, const char * argv[]) { struct BitStream bitStream; unsigned int rows, cols; unsigned char ** packedBits; + BwHash * bwHashP; pm_proginit(&argc, argv); @@ -805,10 +881,10 @@ main(int argc, const char * argv[]) { } skipToNextLine(&bitStream); - buildHashes(&whash, &bhash); + bwHashP = newBwHash(); readFax(&bitStream, cmdline.stretch, cmdline.expectedLineSize, - !cmdline.stop_error, + !cmdline.stop_error, !!cmdline.correctlong, bwHashP, &packedBits, &cols, &rows); pm_close(ifP); @@ -825,5 +901,10 @@ main(int argc, const char * argv[]) { freeBits(packedBits, rows, cmdline.stretch); + freeBwHash(bwHashP); + return 0; } + + + diff --git a/converter/pbm/mdatopbm.c b/converter/pbm/mdatopbm.c index 461b3f80..670ba8c4 100644 --- a/converter/pbm/mdatopbm.c +++ b/converter/pbm/mdatopbm.c @@ -1,4 +1,3 @@ - /*************************************************************************** MDATOPBM: Convert Microdesign area to portable bitmap @@ -30,156 +29,188 @@ typedef unsigned char mdbyte; /* Must be exactly one byte */ -static FILE *infile; /* Input file */ static mdbyte header[128]; /* MDA file header */ static bit **data; /* PBM image */ static mdbyte *mdrow; /* MDA row after decompression (MD3 only) */ static int bInvert = 0; /* Invert image? */ static int bScale = 0; /* Scale image? */ static int bAscii = 0; /* Output ASCII PBM? */ -static int nInRows, nInCols; /* Height, width of input (rows x bytes) */ -static int nOutCols, nOutRows; /* Height, width of output (rows x bytes) */ -static mdbyte -getbyte(void) { +static mdbyte +getbyte(FILE * const ifP) { /* Read a byte from the input stream, with error trapping */ int b; - b = fgetc(infile); + b = fgetc(ifP); + + if (b == EOF) + pm_error("Unexpected end of MDA file"); - if (b == EOF) pm_error("Unexpected end of MDA file\n"); - return (mdbyte)b; } -static void -render_byte(int *col, int *xp, int *yp, int b) { +static void +renderByte(unsigned int const nInCols, + unsigned int const nOutRows, + unsigned int * const colP, + unsigned int * const xP, + unsigned int * const yP, + int const b) { +/*---------------------------------------------------------------------------- + Convert a byte to 8 cells in the destination bitmap -/* Convert a byte to 8 cells in the destination bitmap - * - * *col = source column - * *xp = destination column - * *yp = destination row - * b = byte to draw - * - * Will update *col, *xp and *yp to point to the next bit of the row. - */ + As input - int mask = 0x80; - int n; - int y3 = *yp; + *colP = source column + *xP = destination column + *yP = destination row + b = byte to draw - if (bScale) y3 *= 2; + As output, update *colP, *xP and *yP to point to the next bit of the row. +-----------------------------------------------------------------------------*/ + int const y3 = bScale ? *yP * 2 : *yP; - if (y3 >= nOutRows) return; + if (y3 < nOutRows) { + unsigned int n; + int mask; - for (n = 0; n < 8; ++n) { - if (bInvert) data[y3][*xp] = (b & mask) ? PBM_BLACK : PBM_WHITE; - else data[y3][*xp] = (b & mask) ? PBM_WHITE : PBM_BLACK; - mask = mask >> 1; - if (bScale) data[y3+1][*xp] = data[y3][*xp]; - ++(*xp); - } - ++(*col); /* Next byte */ - if ((*col) >= nInCols) { - /* Onto next line? */ - *col = 0; - *xp = 0; - ++(*yp); + for (n = 0, mask = 0x80; n < 8; ++n) { + if (bInvert) data[y3][*xP] = (b & mask) ? PBM_BLACK : PBM_WHITE; + else data[y3][*xP] = (b & mask) ? PBM_WHITE : PBM_BLACK; + mask = mask >> 1; + if (bScale) + data[y3+1][*xP] = data[y3][*xP]; + ++(*xP); + } + ++(*colP); /* Next byte */ + if ((*colP) >= nInCols) { + /* Onto next line? */ + *colP = 0; + *xP = 0; + ++(*yP); + } } } -static void -md2_trans(void) { - /* Convert a MicroDesign 2 area to PBM */ - /* MD2 has RLE encoding that may go over */ - int x1, y1, col; /* multiple lines. */ +static void +md2Trans(FILE * const ifP, + unsigned int const nInRows, + unsigned int const nInCols, + unsigned int const nOutRows, + unsigned int const nOutCols) { +/*---------------------------------------------------------------------------- + Convert a MicroDesign 2 area to PBM + + MD2 has RLE encoding that may go over +-----------------------------------------------------------------------------*/ + unsigned int x1, y1, col; /* multiple lines. */ mdbyte b; - int c; x1 = y1 = col = 0; while (y1 < nInRows) { - b = getbyte(); - + b = getbyte(ifP); + if (b == 0 || b == 0xFF) { /* RLE sequence */ - c = getbyte(); - if (c == 0) c = 256; - while (c > 0) { - render_byte(&col, &x1, &y1, b); - --c; + int c; + c = getbyte(ifP); + if (c == 0) + c = 256; + while (c > 0) { + renderByte(nInCols, nOutRows, &col, &x1, &y1, b); + --c; } - } - else - render_byte(&col, &x1, &y1, b); /* Not RLE */ + } else + /* Not RLE */ + renderByte(nInCols, nOutRows, &col, &x1, &y1, b); } } -static void -md3_trans(void) { - /* Convert MD3 file. MD3 are encoded as rows, and - there are three types. - */ - int x1, y1, col; - mdbyte b; - int c, d, n; +static void +md3Trans(FILE * const ifP, + unsigned int const nInRows, + unsigned int const nInCols, + unsigned int const nOutRows, + unsigned int const nOutCols) { +/*---------------------------------------------------------------------------- + Convert MD3 file. MD3 are encoded as rows, and there are three types. +-----------------------------------------------------------------------------*/ + unsigned int y1; for (y1 = 0; y1 < nInRows; ++y1) { - b = getbyte(); /* Row type */ + mdbyte b; + + b = getbyte(ifP); /* Row type */ switch(b) { - case 0: /* All the same byte */ - c = getbyte(); - for (n = 0; n < nInCols; n++) - mdrow[n] = c; - break; - + case 0: { /* All the same byte */ + int c; + unsigned int i; + c = getbyte(ifP); + for (i = 0; i < nInCols; ++i) + mdrow[i] = c; + } break; + case 1: /* Encoded data */ - case 2: col = 0; /* Encoded as XOR with previous row */ + case 2: { /* Encoded as XOR with previous row */ + unsigned int col; + col = 0; while (col < nInCols) { - c = getbyte(); + int c; + c = getbyte(ifP); if (c >= 129) { /* RLE sequence */ + unsigned int i; + int d; c = 257 - c; - d = getbyte(); - for (n = 0; n < c; ++n) { - if (b == 1) + d = getbyte(ifP); + for (i = 0; i < c; ++i) { + if (b == 1) mdrow[col++] = d; - else + else mdrow[col++] ^= d; - } + } } else { /* not RLE sequence */ - ++c; - for (n = 0; n < c; ++n) { - d = getbyte(); - if (b == 1) - mdrow[col++] = d; - else - mdrow[col++] ^= d; - } - } + unsigned int i; + ++c; + for (i = 0; i < c; ++i) { + int d; + d = getbyte(ifP); + if (b == 1) + mdrow[col++] = d; + else + mdrow[col++] ^= d; + } + } } + } break; } - /* Row loaded. Convert it. */ - x1 = 0; col = 0; - for (n = 0; n < nInCols; ++n) { - d = y1; - render_byte(&col, &x1, &d, mdrow[n]); + { + /* Row loaded. Convert it. */ + unsigned int x1; + unsigned int col; + unsigned int i; + + for (i = 0, x1 = 0, col = 0; i < nInCols; ++i) { + unsigned int d; + d = y1; + renderByte(nInCols, nOutRows, &col, &x1, &d, mdrow[i]); + } } } } -static void -usage(char *s) { +static void +usage(const char *s) { printf("mdatopbm v1.00, Copyright (C) 1999 " "John Elliott <jce@seasip.demon.co.uk>\n" "This program is redistributable under the terms of " @@ -197,17 +228,24 @@ usage(char *s) { -int -main(int argc, char **argv) { +int +main(int argc, const char **argv) { + + FILE * ifP; int n, optstop = 0; - char *fname = NULL; + const char * fname; + unsigned int nInRows, nInCols; + /* Height, width of input (rows x bytes) */ + unsigned int nOutCols, nOutRows; + /* Height, width of output (rows x bytes) */ - pbm_init(&argc, argv); + pm_proginit(&argc, argv); /* Parse options */ + fname = NULL; /* initial value */ for (n = 1; n < argc; ++n) { - if (argv[n][0] == '-' && !optstop) { + if (argv[n][0] == '-' && !optstop) { if (argv[n][1] == 'a' || argv[n][1] == 'A') bAscii = 1; if (argv[n][1] == 'd' || argv[n][1] == 'D') bScale = 1; if (argv[n][1] == 'i' || argv[n][1] == 'I') bInvert = 1; @@ -225,47 +263,50 @@ main(int argc, char **argv) { } } - if (fname) - infile = pm_openr(fname); + if (fname) + ifP = pm_openr(fname); else - infile = stdin; + ifP = stdin; /* Read MDA file header */ - if (fread(header, 1, 128, infile) < 128) + if (fread(header, 1, 128, ifP) < 128) pm_error("Not a .MDA file\n"); - if (strncmp((char*) header, ".MDA", 4) && + if (strncmp((char*) header, ".MDA", 4) && strncmp((char*) header, ".MDP", 4)) pm_error("Not a .MDA file\n"); { short yy; - pm_readlittleshort(infile, &yy); nInRows = yy; - pm_readlittleshort(infile, &yy); nInCols = yy; + pm_readlittleshort(ifP, &yy); nInRows = yy; + pm_readlittleshort(ifP, &yy); nInCols = yy; } - + nOutCols = 8 * nInCols; nOutRows = nInRows; - if (bScale) + if (bScale) nOutRows *= 2; data = pbm_allocarray(nOutCols, nOutRows); - + MALLOCARRAY_NOFAIL(mdrow, nInCols); - if (header[21] == '0') - md2_trans(); + if (header[21] == '0') + md2Trans(ifP, nInRows, nInCols, nOutRows, nOutCols); else - md3_trans(); + md3Trans(ifP, nInRows, nInCols, nOutRows, nOutCols); - pbm_writepbm(stdout, data, nInCols*8, nOutRows, bAscii); + pbm_writepbm(stdout, data, nOutCols, nOutRows, bAscii); - if (infile != stdin) - pm_close(infile); + if (ifP != stdin) + pm_close(ifP); fflush(stdout); pbm_freearray(data, nOutRows); free(mdrow); return 0; } + + + diff --git a/converter/pbm/pbmto4425.c b/converter/pbm/pbmto4425.c index 1d97ac6a..f18b2e5a 100644 --- a/converter/pbm/pbmto4425.c +++ b/converter/pbm/pbmto4425.c @@ -1,178 +1,155 @@ +#include <assert.h> #include <string.h> #include "nstring.h" +#include "mallocvar.h" #include "pbm.h" -static char bit_table[2][3] = { -{1, 4, 0x10}, -{2, 8, 0x40} +static char const bit_table[2][3] = { + {1, 4, 0x10}, + {2, 8, 0x40} }; -static int vmap_width; -static int vmap_height; +static unsigned int const vmapWidth = 132; +static unsigned int const vmapHeight = 23; -static int xres; -static int yres; - -static char *vmap; static void -init_map() -{ - int x, y; +initMap(char * const vmap) { + unsigned int col; - for(x = 0; x < vmap_width; ++x) - { - for(y = 0; y < vmap_height; ++y) - { - vmap[y*(vmap_width) + x] = 0x20; - } + for (col = 0; col < vmapWidth; ++col) { + unsigned int row; + + for (row = 0; row < vmapHeight; ++row) + vmap[row * vmapWidth + col] = ' '; } } static void -set_vmap(x, y) - int x, y; -{ - int ix, iy; +setVmap(char * const vmap, + unsigned int const x, + unsigned int const y) { + + unsigned int const ix = x/2; + unsigned int const iy = y/3; - ix = x/2; - iy = y/3; + assert(ix < vmapWidth); + assert(iy < vmapHeight); - vmap[iy*(vmap_width) + ix] |= bit_table[x % 2][y % 3]; + vmap[iy * vmapWidth + ix] |= bit_table[x % 2][y % 3]; } static void -fill_map(pbmfp) - FILE *pbmfp; -{ - bit **pbm_image; +fillMap(FILE * const pbmFileP, + char * const vmap) { + + unsigned int const xres = vmapWidth * 2; + unsigned int const yres = vmapHeight * 3; + + bit ** pbmImage; int cols; int rows; - int x; - int y; - - pbm_image = pbm_readpbm(pbmfp, &cols, &rows); - for(y = 0; y < rows && y < yres; ++y) - { - for(x = 0; x < cols && x < xres; ++x) - { - if(pbm_image[y][x] == PBM_WHITE) - { - set_vmap(x, y); - } + unsigned int row; + + pbmImage = pbm_readpbm(pbmFileP, &cols, &rows); + + for (row = 0; row < rows && row < yres; ++row) { + unsigned int col; + + for (col = 0; col < cols && col < xres; ++col) { + if (pbmImage[row][col] == PBM_WHITE) + setVmap(vmap, col, row); } } } + static void -print_map() -{ - int x, y; - int last_byte; - -#ifdef BUFFERED - char *iobuf; - iobuf = (char *)malloc(BUFSIZ); - if(iobuf == NULL) - { - pm_message( "Can't allocate space for I/O buffer. " - "Using unbuffered I/O...\n" ); - setbuf(stdout, NULL); - } - else - { - setbuf(stdout, iobuf); - } -#endif - - fputs("\033[H\033[J", stdout); /* clear screen */ - fputs("\033[?3h", stdout); /* 132 column mode */ - fputs("\033)}\016", stdout); /* mosaic mode */ - - for(y = 0; y < vmap_height; ++y) - { - for(last_byte = vmap_width - 1; - last_byte >= 0 - && vmap[y * vmap_width + last_byte] == 0x20; - --last_byte) +printMap(char * const vmap, + FILE * const ofP) { + + unsigned int row; + + fputs("\033[H\033[J", ofP); /* clear screen */ + fputs("\033[?3h", ofP); /* 132 column mode */ + fputs("\033)}\016", ofP); /* mosaic mode */ + + for (row = 0; row < vmapHeight; ++row) { + unsigned int endCol; + /* Column number just past the non-space data in the row; + (i.e. spaces on the right are padding; not data + */ + unsigned int col; + + for (endCol = vmapWidth; + endCol > 0 && vmap[row * vmapWidth + (endCol-1)] == ' '; + --endCol) ; - for(x = 0; x <= last_byte; ++x) - { - fputc(vmap[y*(vmap_width) + x], stdout); - } - fputc('\n', stdout); + for (col = 0; col < endCol; ++col) + fputc(vmap[row * vmapWidth + col], ofP); + + fputc('\n', ofP); } - fputs("\033(B\017", stdout); + fputs("\033(B\017", ofP); } int -main(int argc, char * argv[]) { - int argn; - const char *pbmfile; - FILE *pbmfp; - const char *usage="[pbmfile]"; - - pbm_init( &argc, argv ); - for(argn = 1; - argn < argc && argv[argn][0] == '-' && strlen(argv[argn]) > 1; - ++argn) - { - pm_usage(usage); - } +main(int argc, const char ** argv) { - if(argn >= argc) - { - pbmfile = "-"; - } - else if(argc - argn != 1) - { - pm_usage(usage); - } - else - { - pbmfile = argv[argn]; - } + unsigned int argn; + const char * inputFileNm; + FILE * ifP; + + char * vmap; /* malloced */ + + pm_proginit(&argc, argv); - if(streq(pbmfile, "-")) - { - pbmfp = stdin; + for (argn = 1; + argn < argc && argv[argn][0] == '-' && strlen(argv[argn]) > 1; + ++argn) { + pm_error("Unrecognized option '%s'", argv[argn]); } - else - { - pbmfp = pm_openr( argv[argn] ); + + if (argn >= argc) { + inputFileNm = "-"; + } else if(argc - argn != 1) { + pm_error("Too many arguments. At most one argument is allowed: " + "Name of the input file"); + } else { + inputFileNm = argv[argn]; } - vmap_width = 132; - vmap_height = 23; + ifP = pm_openr(inputFileNm); + + assert(vmapWidth < UINT_MAX/vmapHeight); + + MALLOCARRAY(vmap, vmapWidth * vmapHeight); + if (!vmap) + pm_error("Cannot allocate memory for %u x %u pixels", + vmapWidth, vmapHeight); - xres = vmap_width * 2; - yres = vmap_height * 3; + initMap(vmap); + fillMap(ifP, vmap); + printMap(vmap, stdout); - vmap = malloc(vmap_width * vmap_height * sizeof(char)); - if(vmap == NULL) - { - pm_error( "Cannot allocate memory" ); - } + free(vmap); - init_map(); - fill_map(pbmfp); - print_map(); /* If the program failed, it previously aborted with nonzero completion code, via various function calls. */ - return 0; + return 0; } diff --git a/converter/pbm/pbmtolj.c b/converter/pbm/pbmtolj.c index 3cd76703..1936544f 100644 --- a/converter/pbm/pbmtolj.c +++ b/converter/pbm/pbmtolj.c @@ -27,12 +27,14 @@ ** implied warranty. */ +#include <stdbool.h> +#include <assert.h> +#include <string.h> + #include "pm_c_util.h" #include "pbm.h" #include "shhopt.h" #include "mallocvar.h" -#include <string.h> -#include <assert.h> static char *rowBuffer, *prevRowBuffer, *packBuffer, *deltaBuffer; static int rowBufferSize, rowBufferIndex, prevRowBufferIndex; @@ -43,7 +45,7 @@ static int item, bitsperitem, bitshift; -struct cmdlineInfo { +struct CmdlineInfo { /* All the information the user supplied in the command line, in a form easy for the program to use. */ @@ -58,8 +60,8 @@ struct cmdlineInfo { static void -parseCommandLine(int argc, char ** argv, - struct cmdlineInfo * const cmdlineP) { +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 us as the argv array. @@ -91,10 +93,10 @@ parseCommandLine(int argc, char ** argv, &compressSpec, 0); opt.opt_table = option_def; - opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ - opt.allowNegNum = FALSE; /* We may have parms that are negative numbers */ + opt.short_allowed = false; /* We have no short (old-fashioned) options */ + opt.allowNegNum = false; /* We may have parms that are negative numbers */ - pm_optParseOptions3(&argc, argv, opt, sizeof(opt), 0); + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ if (argc-1 == 0) @@ -144,7 +146,7 @@ freeBuffers(void) { static void -putinit(struct cmdlineInfo const cmdline) { +putinit(struct CmdlineInfo const cmdline) { if (!cmdline.noreset) { /* Printer reset. */ printf("\033E"); @@ -352,9 +354,9 @@ findRightmostBlackCol(const bit * const bitrow, for (i = cols - 1; i >= 0 && bitrow[i] == PBM_WHITE; --i); if (i < 0) - *allWhiteP = TRUE; + *allWhiteP = true; else { - *allWhiteP = FALSE; + *allWhiteP = false; *blackColP = i; } } @@ -495,7 +497,7 @@ printRow(void) { static void doPage(FILE * const ifP, - struct cmdlineInfo const cmdline) { + struct CmdlineInfo const cmdline) { bit * bitrow; int rows, cols, format, row; @@ -541,19 +543,19 @@ doPage(FILE * const ifP, int -main(int argc, char * argv[]) { +main(int argc, const char ** argv) { - struct cmdlineInfo cmdline; + struct CmdlineInfo cmdline; FILE * ifP; int eof; - pbm_init(&argc, argv); + pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); ifP = pm_openr(cmdline.inputFilename); - eof = FALSE; + eof = false; while (!eof) { doPage(ifP, cmdline); pbm_nextimage(ifP, &eof); diff --git a/converter/pbm/pbmtomda.c b/converter/pbm/pbmtomda.c index 3ad51499..a39cf1a7 100644 --- a/converter/pbm/pbmtomda.c +++ b/converter/pbm/pbmtomda.c @@ -1,7 +1,7 @@ /*************************************************************************** - 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 +20,80 @@ ******************************************************************************/ +#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; + /* Instructions to pm_optParseOptions3 on how to parse our options. + */ + 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_optParseOptions3(&argc, (char **)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 +105,109 @@ 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 */ +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; - int const step = bScale ? 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) { -int main(int argc, char **argv) -{ - int nOutRowsUnrounded; /* Before rounding up to multiple of 4 */ - int nOutCols, nOutRows; + const char * const headerValue = ".MDAMicroDesignPCWv1.00\r\npbm2mda\r\n"; + + 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 +218,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; } + + + diff --git a/converter/pbm/pbmtoppa/pbmtoppa.c b/converter/pbm/pbmtoppa/pbmtoppa.c index ff4a599e..47e64ecc 100644 --- a/converter/pbm/pbmtoppa/pbmtoppa.c +++ b/converter/pbm/pbmtoppa/pbmtoppa.c @@ -14,6 +14,8 @@ #include <unistd.h> #include "pbm.h" +#include "nstring.h" + #include "ppa.h" #include "ppapbm.h" #include "cutswath.h" @@ -40,8 +42,8 @@ int Pwidth; /* width in bytes */ ppa_stat printer; -static int -print_pbm(FILE * const in) { +static int +printPbm(FILE * const ifP) { char line[1024]; pbm_stat pbm; @@ -51,8 +53,8 @@ print_pbm(FILE * const in) { ppa_init_job(&printer); - while(make_pbm_stat(&pbm, in)) { - if (pbm.width != Width || pbm.height != Height) + while(make_pbm_stat(&pbm, ifP)) { + if (pbm.width != Width || pbm.height != Height) pm_error("print_pbm(): Input image is not the size " "of a page for Page %d. " "The input is %dW x %dH, " @@ -123,7 +125,7 @@ print_pbm(FILE * const in) { /* eat any remaining whitespace */ if(pbm.version==P1) - fgets (line, 1024, in); + fgets (line, 1024, ifP); ++numpages; } @@ -141,11 +143,13 @@ print_pbm(FILE * const in) { -static void -set_printer_specific_defaults() -{ - switch(printer.version) - { +static void +setPrinterSpecificDefaults() { + + switch(printer.version) { + case HP710: + pm_error("Don't know how to drive HP 710"); + break; case HP720: printer.marg_diff = HP720_MARG_DIFF; printer.bufsize = HP720_BUFSIZE; @@ -179,14 +183,12 @@ set_printer_specific_defaults() printer.right_margin = HP1000_RIGHT_MARGIN; printer.bottom_margin = HP1000_BOTTOM_MARGIN; break; - default: - pm_error("set_printer_defaults(): unknown printer version"); } } -static void +static void show_usage(const char* const prog) { printf("usage: %s [ options ] [ <infile> [ <outfile> ] ]\n\n",prog); @@ -220,9 +222,9 @@ show_usage(const char* const prog) -static void -parm_version(char* arg) -{ +static void +parmVersion(char * const arg) { + if(!strcasecmp(arg,"hp720") || !strcmp(arg,"720")) printer.version=HP720; else if(!strcasecmp(arg,"hp820") || !strcmp(arg,"820")) @@ -231,39 +233,39 @@ parm_version(char* arg) printer.version=HP1000; else pm_error("parm_version(): unknown printer version '%s'",arg); - set_printer_specific_defaults(); + setPrinterSpecificDefaults(); } -static void -parm_iversion(int arg) -{ +static void +parmIversion(int const arg) { + switch(arg) { case 720: - printer.version=HP720; + printer.version = HP720; break; case 820: - printer.version=HP820; + printer.version = HP820; break; case 1000: - printer.version=HP1000; + printer.version = HP1000; break; default: - pm_error("parm_iversion(): unknown printer version '%d'", arg); + pm_error("parmIversion(): unknown printer version '%d'", arg); } - set_printer_specific_defaults(); + setPrinterSpecificDefaults(); } -static void -dump_config() -{ +static void +dumpConfig() { + printf("version: "); - switch(printer.version) - { + + switch(printer.version) { case HP710: printf("HP710\n"); break; case HP720: printf("HP720\n"); break; case HP820: printf("HP820\n"); break; @@ -278,90 +280,88 @@ dump_config() -static void -read_config_file(const char* const fname) -{ - FILE* cfgfile=fopen(fname,"r"); - char line[1024],key[14],buf[10]; - int len,value,lineno=1; +static void +readConfigFile(const char * const fname) { + + FILE * cfgFileP; + char line[1024]; + char key[14]; + char buf[10]; + int len; + int value; + int lineno; - if(!cfgfile) + cfgFileP = fopen(fname, "r"); + + lineno = 1; /* initial value */ + + if (!cfgFileP) pm_error("read_config_file(): couldn't open file '%s'", fname); - while(fgets(line,1024,cfgfile)) - { - if(strchr(line,'#')) - *strchr(line,'#')=0; - switch(sscanf(line,"%13s%9s",key,buf)) - { + while (fgets(line, 1024, cfgFileP)) { + if (strchr(line, '#')) + *strchr(line, '#')=0; + switch(sscanf(line, "%13s%9s", key, buf)) { case 2: - value=atoi(buf); - len=strlen(key); - if(!strncmp(key,"version",len)) - parm_iversion(value); - else if(!strncmp(key,"xoffset",len)) - printer.x_offset=value; - else if(!strncmp(key,"yoffset",len)) - printer.y_offset=value; - else if(!strncmp(key,"topmargin",len)) - printer.top_margin=value; - else if(!strncmp(key,"leftmargin",len)) - printer.left_margin=value; - else if(!strncmp(key,"rightmargin",len)) - printer.right_margin=value; - else if(!strncmp(key,"bottommargin",len)) - printer.bottom_margin=value; - else if(!strncmp(key,"papersize",len)) - { - if(!strcmp(buf,"us")) - { - Width = USWIDTH; + value = atoi(buf); + len = strlen(key); + if (strneq(key, "version", len)) + parmIversion(value); + else if (strneq(key, "xoffset", len)) + printer.x_offset = value; + else if (strneq(key, "yoffset", len)) + printer.y_offset = value; + else if(strneq(key, "topmargin", len)) + printer.top_margin = value; + else if(strneq(key, "leftmargin", len)) + printer.left_margin = value; + else if(strneq(key, "rightmargin", len)) + printer.right_margin = value; + else if(strneq(key, "bottommargin", len)) + printer.bottom_margin = value; + else if(strneq(key, "papersize" , len)) { + if(streq(buf, "us")) { + Width = USWIDTH; Height = USHEIGHT; - } - else if(!strcmp(buf,"a4")) - { - Width = A4WIDTH; + } else if (streq(buf, "a4")) { + Width = A4WIDTH; Height = A4HEIGHT; - } - else + } else pm_error("read_config_file(): unknown paper size %s", buf); - } - else if(!strcmp(key,"dump")) - dump_config(); - else + } else if(!strcmp(key,"dump")) + dumpConfig(); + else pm_error("read_config_file(): unrecognized parameter '%s' " "(line %d)", key, lineno); case EOF: - case 0: + case 0: break; default: pm_error("read_config_file(): error parsing config file " "(line %d)", lineno); } - lineno++; + ++lineno; } - if(feof(cfgfile)) - { - fclose(cfgfile); - return; - } - - pm_error("read_config_file(): error parsing config file"); + if (feof(cfgFileP)) { + fclose(cfgFileP); + } else + pm_error("read_config_file(): error parsing config file"); } -const char* const defaultcfgfile="/etc/pbmtoppa.conf"; +const char * const defaultCfgFileNm = "/etc/pbmtoppa.conf"; -int +int main(int argc, char *argv[]) { int argn; int got_in=0, got_out=0, do_continue=1; - FILE *in=stdin, *out=stdout; + FILE * ifP; + FILE * ofP; struct stat tmpstat; pbm_init(&argc, argv); @@ -374,12 +374,15 @@ main(int argc, char *argv[]) { printer.right_margin = DEFAULT_RIGHT_MARGIN; printer.bottom_margin = DEFAULT_BOTTOM_MARGIN; printer.DPI = DEFAULT_DPI; - Width = USWIDTH; + Width = USWIDTH; Height = USHEIGHT; - set_printer_specific_defaults(); + setPrinterSpecificDefaults(); + + if (!stat(defaultCfgFileNm, &tmpstat)) + readConfigFile(defaultCfgFileNm); - if(!stat(defaultcfgfile,&tmpstat)) - read_config_file(defaultcfgfile); + ifP = stdin; /* initial value */ + ofP = stdout; /* initial value */ for(argn=1; argn<argc; argn++) { @@ -389,12 +392,12 @@ main(int argc, char *argv[]) { return 0; } else if(!strcmp(argv[argn],"-d")) - dump_config(); + dumpConfig(); else if(argn+1<argc) { do_continue=1; if(!strcmp(argv[argn],"-v")) - parm_version(argv[++argn]); + parmVersion(argv[++argn]); else if(!strcmp(argv[argn],"-x")) printer.x_offset+=atoi(argv[++argn]); else if(!strcmp(argv[argn],"-y")) @@ -426,7 +429,7 @@ main(int argc, char *argv[]) { pm_error("unknown paper size %s",argv[argn]); } else if(!strcmp(argv[argn],"-f")) - read_config_file(argv[++argn]); + readConfigFile(argv[++argn]); else do_continue=0; if(do_continue) continue; } @@ -434,18 +437,18 @@ main(int argc, char *argv[]) { if(!got_in) { if (strcmp (argv[argn], "-") == 0) - in = stdin; - else if ((in = fopen (argv[argn], "rb")) == NULL) - pm_error("main(): couldn't open file '%s'", + ifP = stdin; + else if ((ifP = fopen (argv[argn], "rb")) == NULL) + pm_error("main(): couldn't open file '%s'", argv[argn]); got_in=1; } else if(!got_out) { if (strcmp (argv[argn], "-") == 0) - out = stdout; - else if ((out = fopen (argv[argn], "wb")) == NULL) - pm_error("main(): couldn't open file '%s'", + ofP = stdout; + else if ((ofP = fopen (argv[argn], "wb")) == NULL) + pm_error("main(): couldn't open file '%s'", argv[argn]); got_out=1; } @@ -453,9 +456,11 @@ main(int argc, char *argv[]) { pm_error("main(): unrecognized parameter '%s'", argv[argn]); } - Pwidth=(Width+7)/8; - printer.fptr=out; + Pwidth = (Width+7)/8; + printer.fptr = ofP; - return print_pbm (in); + return printPbm(ifP); } + + diff --git a/converter/pbm/pbmtoxbm.c b/converter/pbm/pbmtoxbm.c index 1a003189..4bd33dd8 100644 --- a/converter/pbm/pbmtoxbm.c +++ b/converter/pbm/pbmtoxbm.c @@ -10,10 +10,10 @@ ** implied warranty. */ -/* 2006.10 (afu) +/* 2006.10 (afu) Changed bitrow from plain to raw, read function from pbm_readpbmrow() to pbm_readpbmrow_packed(). Retired bitwise transformation functions. - + Output function putitem rewritten to handle both X10 and X11. Added -name option. There is no check for the string thus given. @@ -35,7 +35,7 @@ #include "nstring.h" -enum xbmVersion { X10, X11 }; +enum XbmVersion { X10, X11 }; struct CmdlineInfo { /* All the information the user supplied in the command line, @@ -43,16 +43,16 @@ struct CmdlineInfo { */ const char * inputFileName; const char * name; - enum xbmVersion xbmVersion; + enum XbmVersion xbmVersion; }; static void -parseCommandLine(int argc, +parseCommandLine(int argc, const char ** argv, struct CmdlineInfo *cmdlineP ) { /*---------------------------------------------------------------------------- Parse program command line described in Unix standard form by argc - and argv. Return the information in the options as *cmdlineP. + and argv. Return the information in the options as *cmdlineP. If command line is internally inconsistent (invalid options, etc.), issue error message to stderr and abort program. @@ -96,19 +96,19 @@ parseCommandLine(int argc, pm_error("Image name '%s' contains invalid character (%c).", cmdlineP->name, cmdlineP->name[i]); } - + if (x10 && x11) pm_error("You can't specify both -x10 and -x11"); else if (x10) cmdlineP->xbmVersion = X10; - else + else cmdlineP->xbmVersion = X11; - - if (argc-1 < 1) + + if (argc-1 < 1) cmdlineP->inputFileName = "-"; else { cmdlineP->inputFileName = argv[1]; - + if (argc-1 > 1) pm_error("Program takes zero or one argument (filename). You " "specified %u", argc-1); @@ -141,22 +141,22 @@ generateName(char const filenameArg[], /* indices into the input and output buffers */ /* Start just after the rightmost slash, or at beginning if no slash */ - if (strrchr(filenameArg, '/') == 0) + if (strrchr(filenameArg, '/') == 0) argIndex = 0; else argIndex = strrchr(filenameArg, '/') - filenameArg + 1; - if (filenameArg[argIndex] == '\0') + if (filenameArg[argIndex] == '\0') *nameP = strdup("noname"); else { char * name; nameIndex = 0; /* Start at beginning of name buffer */ name = malloc(strlen(filenameArg)); - - while (filenameArg[argIndex] != '\0' + + while (filenameArg[argIndex] != '\0' && filenameArg[argIndex] != '.') { const char filenameChar = filenameArg[argIndex++]; - name[nameIndex++] = + name[nameIndex++] = ISALNUM(filenameChar) ? filenameChar : '_'; } name[nameIndex] = '\0'; @@ -167,37 +167,46 @@ generateName(char const filenameArg[], -static unsigned short int itemBuff[22]; -static int itemCnt; /* takes values 0 to 15 (x11) or 21 (x10) */ -static enum xbmVersion itemVersion; +typedef struct { + unsigned short int buff[22]; + int cnt; /* takes values 0 to 15 (x11) or 21 (x10) */ + enum XbmVersion version; +} ItemWriter; + +static ItemWriter itemWriter; static void putitemX10(unsigned char const item) { - if (itemCnt == 22) { + if (itemWriter.cnt == 22) { /* Buffer is full. Write out one line. */ int rc; rc = printf(" 0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x," "0x%02x%02x,0x%02x%02x,0x%02x%02x,0x%02x%02x," "0x%02x%02x,0x%02x%02x,0x%02x%02x,\n", - itemBuff[ 1], itemBuff[ 0], itemBuff[ 3], itemBuff[ 2], - itemBuff[ 5], itemBuff[ 4], itemBuff[ 7], itemBuff[ 6], - itemBuff[ 9], itemBuff[ 8], itemBuff[11], itemBuff[10], - itemBuff[13], itemBuff[12], itemBuff[15], itemBuff[14], - itemBuff[17], itemBuff[16], itemBuff[19], itemBuff[18], - itemBuff[21], itemBuff[20] + itemWriter.buff[ 1], itemWriter.buff[ 0], + itemWriter.buff[ 3], itemWriter.buff[ 2], + itemWriter.buff[ 5], itemWriter.buff[ 4], + itemWriter.buff[ 7], itemWriter.buff[ 6], + itemWriter.buff[ 9], itemWriter.buff[ 8], + itemWriter.buff[11], itemWriter.buff[10], + itemWriter.buff[13], itemWriter.buff[12], + itemWriter.buff[15], itemWriter.buff[14], + itemWriter.buff[17], itemWriter.buff[16], + itemWriter.buff[19], itemWriter.buff[18], + itemWriter.buff[21], itemWriter.buff[20] ); - if (rc < 0) + if (rc < 0) pm_error("Error writing X10 bitmap raster item. " "printf() failed with errno %d (%s)", errno, strerror(errno)); - - itemCnt = 0; + + itemWriter.cnt = 0; } - itemBuff[itemCnt++] = bitreverse[item]; + itemWriter.buff[itemWriter.cnt++] = bitreverse[item]; } @@ -205,26 +214,30 @@ putitemX10(unsigned char const item) { static void putitemX11(unsigned char const item) { - if (itemCnt == 15 ) { + if (itemWriter.cnt == 15 ) { /* Buffer is full. Write out one line. */ int rc; rc = printf(" 0x%02x,0x%02x,0x%02x,0x%02x," "0x%02x,0x%02x,0x%02x,0x%02x," "0x%02x,0x%02x,0x%02x,0x%02x," "0x%02x,0x%02x,0x%02x,\n", - itemBuff[0], itemBuff[1], itemBuff[2], itemBuff[3], - itemBuff[4], itemBuff[5], itemBuff[6], itemBuff[7], - itemBuff[8], itemBuff[9], itemBuff[10],itemBuff[11], - itemBuff[12],itemBuff[13],itemBuff[14] + itemWriter.buff[ 0], itemWriter.buff[ 1], + itemWriter.buff[ 2], itemWriter.buff[ 3], + itemWriter.buff[ 4], itemWriter.buff[ 5], + itemWriter.buff[ 6], itemWriter.buff[ 7], + itemWriter.buff[ 8], itemWriter.buff[ 9], + itemWriter.buff[10], itemWriter.buff[11], + itemWriter.buff[12], itemWriter.buff[13], + itemWriter.buff[14] ); - if (rc < 0) + if (rc < 0) pm_error("Error writing X11 bitmap raster item. " "printf() failed with errno %d (%s)", errno, strerror(errno)); - - itemCnt = 0; + + itemWriter.cnt = 0; } - itemBuff[itemCnt++] = bitreverse[item]; + itemWriter.buff[itemWriter.cnt++] = bitreverse[item]; } @@ -232,7 +245,7 @@ putitemX11(unsigned char const item) { static void putitem(unsigned char const item) { - switch (itemVersion) { + switch (itemWriter.version) { case X10: putitemX10(item); break; case X11: putitemX11(item); break; } @@ -245,19 +258,19 @@ puttermX10(void) { unsigned int i; - assert(itemCnt % 2 == 0); + assert(itemWriter.cnt % 2 == 0); - for (i = 0; i < itemCnt; i += 2) { + for (i = 0; i < itemWriter.cnt; i += 2) { int rc; - assert(i + 1 < itemCnt); + assert(i + 1 < itemWriter.cnt); rc = printf("%s0x%02x%02x%s", (i == 0) ? " " : "", - itemBuff[i+1], - itemBuff[i], - (i + 2 >= itemCnt) ? "" : ","); - if (rc < 0) + itemWriter.buff[i+1], + itemWriter.buff[i], + (i + 2 >= itemWriter.cnt) ? "" : ","); + if (rc < 0) pm_error("Error writing Item %u at end of X10 bitmap raster. " "printf() failed with errno %d (%s)", i, errno, strerror(errno)); @@ -271,15 +284,15 @@ puttermX11(void) { unsigned int i; - for (i = 0; i < itemCnt; ++i) { + for (i = 0; i < itemWriter.cnt; ++i) { int rc; rc = printf("%s0x%02x%s", (i == 0) ? " " : "", - itemBuff[i], - (i + 1 >= itemCnt) ? "" : ","); + itemWriter.buff[i], + (i + 1 >= itemWriter.cnt) ? "" : ","); - if (rc < 0) + if (rc < 0) pm_error("Error writing Item %u at end of X11 bitmap raster. " "printf() failed with errno %d (%s)", i, errno, strerror(errno)); @@ -289,10 +302,10 @@ puttermX11(void) { static void -putinit(enum xbmVersion const xbmVersion) { +putinit(enum XbmVersion const xbmVersion) { - itemCnt = 0; - itemVersion = xbmVersion; + itemWriter.cnt = 0; + itemWriter.version = xbmVersion; } @@ -300,7 +313,7 @@ putinit(enum xbmVersion const xbmVersion) { static void putterm(void) { - switch (itemVersion) { + switch (itemWriter.version) { case X10: puttermX10(); break; case X11: puttermX11(); break; } @@ -310,7 +323,7 @@ putterm(void) { rc = printf("};\n"); - if (rc < 0) + if (rc < 0) pm_error("Error writing end of X11 bitmap raster. " "printf() failed with errno %d (%s)", errno, strerror(errno)); @@ -320,7 +333,7 @@ putterm(void) { static void -writeXbmHeader(enum xbmVersion const xbmVersion, +writeXbmHeader(enum XbmVersion const xbmVersion, const char * const name, unsigned int const width, unsigned int const height, @@ -341,11 +354,11 @@ convertRaster(FILE * const ifP, unsigned int const rows, int const format, FILE * const ofP, - enum xbmVersion const xbmVersion) { - - unsigned int const bitsPerUnit = xbmVersion == X10 ? 16 : 8; + enum XbmVersion const xbmVersion) { + + unsigned int const bitsPerUnit = xbmVersion == X10 ? 16 : 8; unsigned int const padright = ROUNDUP(cols, bitsPerUnit) - cols; - /* Amount of padding to round cols up to the nearest multiple of + /* Amount of padding to round cols up to the nearest multiple of 8 (if x11) or 16 (if x10). */ unsigned int const bitrowBytes = (cols + padright) / 8; @@ -360,7 +373,7 @@ convertRaster(FILE * const ifP, putinit(xbmVersion); bitrow = pbm_allocrow_packed(cols + padright); - + for (row = 0; row < rows; ++row) { unsigned int i; @@ -386,7 +399,7 @@ int main(int argc, const char ** argv) { - struct CmdlineInfo cmdline; + struct CmdlineInfo cmdline; FILE * ifP; int rows, cols, format; const char * name; @@ -394,15 +407,15 @@ main(int argc, pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); - if (cmdline.name == NULL) + if (cmdline.name == NULL) generateName(cmdline.inputFileName, &name); else name = strdup(cmdline.name); ifP = pm_openr(cmdline.inputFileName); - + pbm_readpbminit(ifP, &cols, &rows, &format); - + writeXbmHeader(cmdline.xbmVersion, name, cols, rows, stdout); convertRaster(ifP, cols, rows, format, stdout, cmdline.xbmVersion); diff --git a/converter/pbm/pktopbm.c b/converter/pbm/pktopbm.c index 712f339f..49e15c49 100644 --- a/converter/pbm/pktopbm.c +++ b/converter/pbm/pktopbm.c @@ -7,159 +7,279 @@ * fix bitmap y placement of dynamically packed char * skip char early if no output file allocated - added debug output - + compile with: cc -lpbm -o pktopbm pktopbm.c */ +#include <stdbool.h> #include <stdio.h> #include <string.h> #include "pm_c_util.h" #include "nstring.h" +#include "mallocvar.h" +#include "shhopt.h" #include "pbm.h" #define NAMELENGTH 80 #define MAXROWWIDTH 3200 #define MAXPKCHAR 256 -typedef int integer ; -typedef unsigned char quarterword ; -typedef char boolean ; -typedef quarterword eightbits ; - -static FILE *pkfile ; -static char pkname[NAMELENGTH+1] ; -static integer pktopbm_pkloc = 0; -static char *filename[MAXPKCHAR] ; -static bit **bitmap = NULL ; -static integer dynf ; -static eightbits inputbyte ; -static eightbits bitweight ; -static integer repeatcount ; -static integer flagbyte ; -static integer debug=0; +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 outputFileCt; + /* The number of output files */ + const char * outputFileNm[MAXPKCHAR]; + /* The output file name, in order */ + unsigned int character; + unsigned int xSpec; + unsigned int x; + unsigned int ySpec; + unsigned int y; + unsigned int debug; +}; + -#define dprintf(s,d) if (debug) printf(s,d) -#define dprintf0(s) if (debug) printf(s) -/* add a suffix to a filename in an allocated space */ static void -pktopbm_add_suffix(char * const name, - const char * const suffix) { - - char * const slash = strrchr(name, '/'); - char * const dot = strrchr(name, '.'); - - if ((dot && slash ? dot < slash : !dot) && !streq(name, "-")) - strcat(name, suffix); +parseCommandLine(int argc, const char ** argv, + struct CmdlineInfo * const cmdlineP) { +/*---------------------------------------------------------------------------- + Note that the file spec strings we return are stored in the storage that + was passed to us as the argv array. +-----------------------------------------------------------------------------*/ + optEntry * option_def; + /* Instructions to pm_optParseOptions3 on how to parse our options. + */ + optStruct3 opt; + + unsigned int option_def_index; + unsigned int characterSpec; + unsigned int firstOutputArgNm; + + MALLOCARRAY_NOFAIL(option_def, 100); + + option_def_index = 0; /* incremented by OPTENTRY */ + OPTENT3(0, "character", OPT_UINT, &cmdlineP->character, + &characterSpec, 0); + OPTENT3(0, "x", OPT_UINT, &cmdlineP->x, + &cmdlineP->xSpec, 0); + OPTENT3(0, "X", OPT_UINT, &cmdlineP->x, + &cmdlineP->xSpec, 0); + OPTENT3(0, "y", OPT_UINT, &cmdlineP->y, + &cmdlineP->ySpec, 0); + OPTENT3(0, "Y", OPT_UINT, &cmdlineP->y, + &cmdlineP->ySpec, 0); + OPTENT3(0, "debug", OPT_UINT, NULL, + &cmdlineP->debug, 0); + + opt.opt_table = option_def; + opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ + opt.allowNegNum = FALSE; /* We may have parms that are negative numbers */ + + pm_optParseOptions3(&argc, (char **)argv, opt, sizeof(opt), 0); + /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + + if (characterSpec) { + if (cmdlineP->character >= MAXPKCHAR) + pm_error("Character number (-character) must be in range 0 to %u", + MAXPKCHAR-1); + } else + cmdlineP->character = 0; + + if (argc-1 < 1) { + cmdlineP->inputFileNm = "-"; + firstOutputArgNm = 1; + } else { + cmdlineP->inputFileNm = argv[1]; + firstOutputArgNm = 2; + } + + cmdlineP->outputFileCt = 0; /* initial value */ + { + unsigned int argn; + bool stdoutUsed; + for (argn = firstOutputArgNm, stdoutUsed = false; + argn < argc; + ++argn) { + if (cmdlineP->outputFileCt >= MAXPKCHAR) + pm_error("You may not specify more than %u output files.", + MAXPKCHAR); + cmdlineP->outputFileNm[cmdlineP->outputFileCt++] = argv[argn]; + if (streq(argv[argn], "-")) { + if (stdoutUsed) + pm_error("You cannot specify Standard Output ('-') " + "for more than one output file"); + stdoutUsed = true; + } + } + } + if (cmdlineP->outputFileCt < 1) + cmdlineP->outputFileNm[cmdlineP->outputFileCt++] = "-"; + + if (cmdlineP->character + cmdlineP->outputFileCt >= MAXPKCHAR) + pm_error("Number of output files (%u) " + "plus -character value (%u) exceeds " + "the maximum number of characters is a PK font file (%u)", + cmdlineP->character, cmdlineP->outputFileCt, MAXPKCHAR); } -/* get a byte from the PK file */ -static eightbits -pktopbm_pkbyte(void) { - pktopbm_pkloc++ ; - return(getc(pkfile)) ; +typedef unsigned char eightbits ; + +static FILE * ifP; +static unsigned int pkLoc; +static const char * fileName[MAXPKCHAR]; +static int dynf ; +static eightbits inputByte ; +static eightbits bitWeight ; +static int repeatCount ; +static int flagByte ; +static int debug = 0; + +#define dprintf(s,d) if (debug) printf(s,d) +#define dprintf0(s) if (debug) printf(s) + +static eightbits +pkByte() { +/*---------------------------------------------------------------------------- + Get a byte from the PK file +-----------------------------------------------------------------------------*/ + ++pkLoc; + + return getc(ifP); } -/* get a 16-bit half word from the PK file */ -static integer -get16(void) { - integer const a = pktopbm_pkbyte() ; - return((a<<8) + pktopbm_pkbyte()) ; +static int +get16() { +/*---------------------------------------------------------------------------- + Get a 16-bit half word from the PK file +-----------------------------------------------------------------------------*/ + int const a = pkByte() ; + + return (a<<8) + pkByte(); } -/* get a 32-bit word from the PK file */ -static integer get32(void) { - integer a; - a = get16() ; - if (a > 32767) a -= 65536 ; - return((a<<16) + get16()) ; +static int +get32() { +/*---------------------------------------------------------------------------- + Get a 32-bit word from the PK file +-----------------------------------------------------------------------------*/ + int a; + + a = get16(); /* initial value */ + + if (a > 32767) + a -= 65536; + + return (a << 16) + get16(); } -/* get a nibble from current input byte, or new byte if no current byte */ -static integer -getnyb(void) { +static int +getNybble() { +/*---------------------------------------------------------------------------- + Get a nibble from current input byte, or new byte if no current byte +-----------------------------------------------------------------------------*/ eightbits temp; - if (bitweight == 0) { - inputbyte = pktopbm_pkbyte() ; - bitweight = 16 ; + + if (bitWeight == 0) { + inputByte = pkByte() ; + bitWeight = 16 ; } - temp = inputbyte / bitweight ; - inputbyte -= temp * bitweight ; - bitweight >>= 4 ; - return(temp) ; + temp = inputByte / bitWeight ; + inputByte -= temp * bitWeight ; + bitWeight >>= 4 ; + + return temp; } -/* get a bit from the current input byte, or a new byte if no current byte */ static bool -getbit(void) { +getBit() { +/*---------------------------------------------------------------------------- + Get a bit from the current input byte, or a new byte if no current byte +-----------------------------------------------------------------------------*/ bool temp ; - bitweight >>= 1 ; - if (bitweight == 0) { - inputbyte = pktopbm_pkbyte() ; - bitweight = 128 ; + + bitWeight >>= 1 ; + if (bitWeight == 0) { + inputByte = pkByte(); + bitWeight = 128 ; } - temp = (inputbyte >= bitweight) ; - if (temp) inputbyte -= bitweight ; - return(temp) ; + temp = (inputByte >= bitWeight); + if (temp) + inputByte -= bitWeight; + + return temp; } -/* unpack a dynamically packed number. dynf is dynamic packing threshold */ -static integer -pkpackednum(void) { - integer i, j ; - i = getnyb() ; +static int +pkPackedNum() { +/*---------------------------------------------------------------------------- + Unpack a dynamically packed number. dynf is dynamic packing threshold +-----------------------------------------------------------------------------*/ + int i, j ; + + i = getNybble() ; + if (i == 0) { /* large run count, >= 3 nibbles */ do { - j = getnyb() ; /* count extra nibbles */ + j = getNybble() ; /* count extra nibbles */ i++ ; } while (j == 0) ; while (i > 0) { - j = (j<<4) + getnyb() ; /* add extra nibbles */ + j = (j<<4) + getNybble() ; /* add extra nibbles */ i-- ; } return (j - 15 +((13 - dynf)<<4) + dynf) ; } else if (i <= dynf) return (i) ; /* number > 0 and <= dynf */ - else if (i < 14) return (((i - dynf - 1)<<4) + getnyb() + dynf + 1) ; + else if (i < 14) return (((i - dynf - 1)<<4) + getNybble() + dynf + 1) ; else { - if (i == 14) repeatcount = pkpackednum() ; /* get repeat count */ - else repeatcount = 1 ; /* value 15 indicates repeat count 1 */ - return(pkpackednum()) ; + if (i == 14) + repeatCount = pkPackedNum() ; /* get repeat count */ + else + repeatCount = 1 ; /* value 15 indicates repeat count 1 */ + + return pkPackedNum(); } } -/* skip specials in PK files, inserted by Metafont or some other program */ static void -skipspecials(void) { - integer i, j; +skipSpecials() { +/*---------------------------------------------------------------------------- + Skip specials in PK files, inserted by Metafont or some other program +-----------------------------------------------------------------------------*/ do { - flagbyte = pktopbm_pkbyte() ; - if (flagbyte >= 240) - switch(flagbyte) { + flagByte = pkByte() ; + if (flagByte >= 240) + switch(flagByte) { case 240: /* specials of size 1-4 bytes */ case 241: case 242: - case 243: + case 243: { + int i, j; + i = 0 ; - for (j = 240 ; j <= flagbyte ; ++j) - i = (i<<8) + pktopbm_pkbyte() ; - for (j = 1 ; j <= i ; ++j) - pktopbm_pkbyte() ; /* ignore special */ - break ; + for (j = 240 ; j <= flagByte ; ++j) + i = (i<<8) + pkByte() ; + for (j = 1 ; j <= i ; ++j) + pkByte() ; /* ignore special */ + } break ; case 244: /* no-op, parameters to specials */ get32() ; case 245: /* start of postamble */ @@ -174,272 +294,378 @@ skipspecials(void) { case 253: case 254: case 255: - pm_error("unexpected flag byte %d", flagbyte) ; + pm_error("unexpected flag byte %d", flagByte) ; } - } while (!(flagbyte < 240 || flagbyte == 245)) ; + } while (!(flagByte < 240 || flagByte == 245)) ; } -/* ignore character packet */ static void -ignorechar(integer const car, - integer const endofpacket) { +ignoreChar(int const car, + unsigned int const endOfPacket) { +/*---------------------------------------------------------------------------- + ignore character packet +-----------------------------------------------------------------------------*/ + while (pkLoc != endOfPacket) + pkByte(); - while (pktopbm_pkloc != endofpacket) pktopbm_pkbyte() ; if (car < 0 || car >= MAXPKCHAR) pm_message("Character %d out of range", car) ; - skipspecials() ; + + skipSpecials() ; } -int -main(int argc, char *argv[]) { - integer x; - integer endofpacket ; - boolean turnon ; - integer i, j; - integer car ; - integer bmx=0, bmy=0; - integer set_bmx=0, set_bmy=0; - bit row[MAXROWWIDTH+1] ; - const char * const usage = - "pkfile[.pk] [-d] [[-x width] [-y height] [-c num] pbmfile]..."; - - pbm_init(&argc, argv); - for (i = 0 ; i < MAXPKCHAR ; i ++) filename[i] = NULL ; - - pm_message("This is PKtoPBM, version 2.5") ; - - if (--argc < 1) pm_usage(usage) ; - - ++argv; - if(strlen(*argv) + 4 > NAMELENGTH) - pm_error("pkname is too long"); - strcpy(pkname, *argv) ; - pktopbm_add_suffix(pkname, ".pk") ; - - car = 0 ; - /* urg: use getopt */ - while (++argv, --argc) { - if (argv[0][0] == '-' && argv[0][1]) - switch (argv[0][1]) { - case 'X': - case 'x': - if (argv[0][2]) bmx = atoi(*argv+2) ; - else if (++argv, --argc) set_bmx = atoi(*argv) ; - else pm_usage(usage) ; - continue ; - case 'Y': - case 'y': - if (argv[0][2]) bmy = atoi(*argv+2) ; - else if (++argv, --argc) set_bmy = atoi(*argv) ; - else pm_usage(usage) ; - continue ; - case 'C': - case 'c': - if (argv[0][2]) car = atoi(*argv+2) ; - else if (++argv, --argc) car = atoi(*argv) ; - else pm_usage(usage) ; - break ; - case 'd': - debug=1; - break ; - default: - pm_usage(usage) ; - } else if (car < 0 || car >= MAXPKCHAR) { - pm_error("character must be in range 0 to %d (-c)", - MAXPKCHAR-1) ; - } else filename[car++] = *argv ; - } +static void +readHeader() { +/*---------------------------------------------------------------------------- + Read the header of the input file. + + Surprisingly, nothing in the header is useful to this program, so we're + just reading past it and doing some validation. - pkfile = pm_openr(pkname); - if (pktopbm_pkbyte() != 247) + We read through the first flag byte and update the global variable + 'flagByte'. +-----------------------------------------------------------------------------*/ + unsigned int commentSz; + unsigned int i; + + if (pkByte() != 247) pm_error("bad PK file (pre command missing)") ; - if (pktopbm_pkbyte() != 89) + + if (pkByte() != 89) pm_error("wrong version of packed file") ; - j = pktopbm_pkbyte() ; /* get header comment size */ - for (i = 1 ; i <= j ; i ++) pktopbm_pkbyte() ; /* ignore header comment */ + + commentSz = pkByte() ; /* get header comment size */ + + for (i = 1 ; i <= commentSz ; ++i) + pkByte() ; /* ignore header comment */ + get32() ; /* ignore designsize */ get32() ; /* ignore checksum */ if (get32() != get32()) /* h & v pixels per point */ pm_message("Warning: aspect ratio not 1:1") ; - skipspecials() ; - while (flagbyte != 245) { /* not at postamble */ - integer cheight, cwidth ; - integer xoffs=0, yoffs=0; - FILE *ofp; - - bmx=set_bmx; - bmy=set_bmy; - dynf = (flagbyte>>4) ; /* get dynamic packing value */ - flagbyte &= 15 ; - turnon = (flagbyte >= 8) ; /* black or white initially? */ - if (turnon) flagbyte &= 7 ; /* long or short form */ - if (flagbyte == 7) { /* long form preamble */ - integer packetlength = get32() ; /* character packet length */ - car = get32() ; /* character number */ - endofpacket = packetlength + pktopbm_pkloc; - /* calculate end of packet */ - if ((car >= MAXPKCHAR) || !filename[car]) { - ignorechar(car, endofpacket); - continue; - } - dprintf0 ("flagbyte7\n"); - dprintf ("car: %d\n", car); - get32() ; /* ignore tfmwidth */ - x=get32() ; /* ignore horiz escapement */ - x=get32() ; /* ignore vert escapement */ - dprintf ("horiz esc %d\n", x); - dprintf ("vert esc %d\n", x); - cwidth = get32() ; /* bounding box width */ - cheight = get32() ; /* bounding box height */ - dprintf ("cwidth %d\n", cwidth); - dprintf ("cheight %d\n", cheight); - if (cwidth < 0 || cheight < 0 || - cwidth > 65535 || cheight > 65535) { - ignorechar(car, endofpacket); - continue; - } - xoffs= get32() ; /* horiz offset */ - yoffs= get32() ; /* vert offset */ - dprintf ("xoffs %d\n", xoffs); - dprintf ("yoffs %d\n", yoffs); - } else if (flagbyte > 3) { /* extended short form */ - integer packetlength = ((flagbyte - 4)<<16) + get16() ; - /* packet length */ - car = pktopbm_pkbyte() ; /* char number */ - endofpacket = packetlength + pktopbm_pkloc ; - /* calculate end of packet */ - if ((car >= MAXPKCHAR) || !filename[car]) { - ignorechar(car, endofpacket); - continue; - } - dprintf0 ("flagbyte>3\n"); - dprintf ("car: %d\n", car); - pktopbm_pkbyte() ; /* ignore tfmwidth (3 bytes) */ - get16() ; /* ignore tfmwidth (3 bytes) */ - get16() ; /* ignore horiz escapement */ - cwidth = get16() ; /* bounding box width */ - cheight = get16() ; /* bounding box height */ - dprintf ("cwidth %d\n", cwidth); - dprintf ("cheight %d\n", cheight); - xoffs=get16(); /* horiz offset */ - if (xoffs >= 32768) - xoffs-= 65536; - yoffs=get16(); /* vert offset */ - if (yoffs >= 32768) - yoffs-= 65536; - dprintf ("xoffs %d\n", xoffs); - dprintf ("yoffs %d\n", yoffs); - } else { /* short form preamble */ - integer packetlength = (flagbyte<<8) + pktopbm_pkbyte() ; - /* packet length */ - car = pktopbm_pkbyte() ; /* char number */ - endofpacket = packetlength + pktopbm_pkloc ; - /* calculate end of packet */ - if ((car >= MAXPKCHAR) || !filename[car]) { - ignorechar(car, endofpacket); - continue; - } - dprintf0 ("flagbyte<=3\n"); - dprintf ("car: %d\n", car); - pktopbm_pkbyte() ; /* ignore tfmwidth (3 bytes) */ - get16() ; /* ignore tfmwidth (3 bytes) */ - x = pktopbm_pkbyte() ; /* ignore horiz escapement */ - dprintf ("horiz esc %d\n", x); - cwidth = pktopbm_pkbyte() ; /* bounding box width */ - cheight = pktopbm_pkbyte() ; /* bounding box height */ - dprintf ("cwidth %d\n", cwidth); - dprintf ("cheight %d\n", cheight); - xoffs=pktopbm_pkbyte (); /* horiz offset */ - if (xoffs >= 128) - xoffs-=256; - yoffs=pktopbm_pkbyte (); /* vert offset */ - if (yoffs >= 128) - yoffs-=256; + + skipSpecials(); +} + + + +static void +readCharacterHeader(int * const carP, + unsigned int * const endOfPacketP, + bool * const mustIgnoreP, + int * const cheightP, + int * const cwidthP, + int * const xoffsP, + int * const yoffsP, + bool * const turnonP) { + + int packetLength; + /* character packet length field value */ + int cheight, cwidth; + /* bounding box height, width field values */ + int xoffs=0, yoffs=0; + bool turnon ; + int x; + + dynf = (flagByte >> 4); /* get dynamic packing value */ + flagByte &= 15; + turnon = (flagByte >= 8) ; /* black or white initially? */ + if (turnon) + flagByte &= 7; /* long or short form */ + + if (flagByte == 7) { /* long form preamble */ + packetLength = get32(); + *carP = get32(); /* character number */ + + dprintf0("flagByte7\n"); + dprintf("car: %d\n", *carP); + get32(); /* ignore tfmwidth */ + x=get32(); /* ignore horiz escapement */ + dprintf("horiz esc %d\n", x); + x=get32(); /* ignore vert escapement */ + dprintf("vert esc %d\n", x); + cwidth = get32(); /* bounding box width */ + cheight = get32(); /* bounding box height */ + dprintf("cwidth %d\n", cwidth); + dprintf("cheight %d\n", cheight); + if (cwidth < 0 || cheight < 0 || + cwidth > 65535 || cheight > 65535) { + *mustIgnoreP = true; + } else { + *mustIgnoreP = false; + xoffs = get32() ; /* horiz offset */ + yoffs = get32() ; /* vert offset */ dprintf ("xoffs %d\n", xoffs); dprintf ("yoffs %d\n", yoffs); } - if (filename[car]) { - if (!bmx) bmx= cwidth; - if (!bmy) bmy= cheight; - bitmap = pbm_allocarray(bmx, bmy) ; - if (bitmap == NULL) - pm_error("out of memory allocating bitmap") ; - } else { - ignorechar(car, endofpacket); - continue; + } else if (flagByte > 3) { /* extended short form */ + packetLength = ((flagByte - 4)<<16) + get16() ; + + *carP = pkByte() ; /* char number */ + + *mustIgnoreP = false; + + dprintf0("flagByte>3\n"); + dprintf("car: %d\n", *carP); + pkByte(); /* ignore tfmwidth (3 bytes) */ + get16(); /* ignore tfmwidth (3 bytes) */ + get16(); /* ignore horiz escapement */ + cwidth = get16(); /* bounding box width */ + cheight = get16(); /* bounding box height */ + dprintf("cwidth %d\n", cwidth); + dprintf("cheight %d\n", cheight); + xoffs = get16(); /* horiz offset */ + if (xoffs >= 32768) + xoffs -= 65536; + yoffs = get16(); /* vert offset */ + if (yoffs >= 32768) + yoffs -= 65536; + dprintf("xoffs %d\n", xoffs); + dprintf("yoffs %d\n", yoffs); + } else { /* short form preamble */ + packetLength = (flagByte << 8) + pkByte(); + *carP = pkByte(); /* char number */ + + *mustIgnoreP = false; + + dprintf0("flagByte<=3\n"); + dprintf("car: %d\n", *carP); + pkByte(); /* ignore tfmwidth (3 bytes) */ + get16(); /* ignore tfmwidth (3 bytes) */ + x = pkByte() ; /* ignore horiz escapement */ + dprintf("horiz esc %d\n", x); + cwidth = pkByte(); /* bounding box width */ + cheight = pkByte() ; /* bounding box height */ + dprintf("cwidth %d\n", cwidth); + dprintf("cheight %d\n", cheight); + xoffs = pkByte(); /* horiz offset */ + if (xoffs >= 128) + xoffs -=256; + yoffs = pkByte(); /* vert offset */ + if (yoffs >= 128) + yoffs -= 256; + dprintf("xoffs %d\n", xoffs); + dprintf("yoffs %d\n", yoffs); + } + if (packetLength < 0) + pm_error("Invalid character header - negative packet length"); + if (packetLength > UINT_MAX - pkLoc) + pm_error("Invalid character header - excessive packet lenght"); + + *endOfPacketP = packetLength + pkLoc; + + *cheightP = cheight; + *cwidthP = cwidth; + *xoffsP = xoffs; + *yoffsP = yoffs; + *turnonP = turnon; +} + + + +static void +readOneCharacter(bool const bmxOverrideSpec, + int const bmxOverride, + bool const bmyOverrideSpec, + int const bmyOverride, + unsigned int * const carP, + bool * const mustIgnoreP, + bit *** const bitmapP, + unsigned int * const bmxP, + unsigned int * const bmyP) { + + int car; + unsigned int endOfPacket; + bool mustIgnore; + int cheight, cwidth; + int xoffs, yoffs; + bool turnon; + bit row[MAXROWWIDTH+1]; + + readCharacterHeader(&car, &endOfPacket, &mustIgnore, + &cheight, &cwidth, &xoffs, &yoffs, &turnon); + + *carP = car; + + if (mustIgnore || !fileName[car]) { + /* Ignore this character in the font */ + ignoreChar(car, endOfPacket); + *mustIgnoreP = true; + } else { + bit ** bitmap; + unsigned int i; + + int const bmx = bmxOverrideSpec ? bmxOverride : cwidth; + int const bmy = bmyOverrideSpec ? bmyOverride : cheight; + + *mustIgnoreP = false; + + bitmap = pbm_allocarray(bmx, bmy); + + bitWeight = 0 ; + for (i = 0 ; i < bmy ; ++i) { + /* make it blank */ + unsigned int j; + + for (j = 0 ; j < bmx ; ++j) + bitmap[i][j] = PBM_WHITE; } - bitweight = 0 ; - for (i = 0 ; i < bmy ; i ++) /* make it blank */ - for (j = 0 ; j < bmx ; j ++) - bitmap[i][j]= PBM_WHITE; if (dynf == 14) { /* bitmapped character */ - dprintf ("bmy: %d\n ", bmy); - dprintf ("y: %d\n ", bmy-yoffs-1); - for (i = 0 ; i < cheight ; i ++) { - int yi= i+(bmy-yoffs-1); - for (j = 0 ; j < cwidth ; j ++) { - int xj= j-xoffs; - if (getbit() && 0<=xj && xj<bmx && 0<=yi && yi<bmy) + dprintf("bmy: %d\n ", bmy); + dprintf("y: %d\n ", bmy - yoffs - 1); + for (i = 0 ; i < cheight ; ++i) { + unsigned int const yi = i + (bmy - yoffs - 1); + unsigned int j; + for (j = 0 ; j < cwidth ; ++j) { + unsigned int const xj = j - xoffs; + if (getBit() && 0 <= xj && xj < bmx && 0 <= yi && yi < bmy) bitmap[yi][xj] = PBM_BLACK ; } } } else { /* dynamically packed char */ - integer rowsleft = cheight ; - integer hbit = cwidth ; - integer rp = 0; - repeatcount = 0 ; - dprintf ("bmy: %d\n ", bmy); - dprintf ("y: %d\n", cheight-rowsleft+(bmy-2*yoffs-1)); + int rowsleft = cheight ; + int hbit = cwidth ; + int rp = 0; + repeatCount = 0 ; + dprintf("bmy: %d\n ", bmy); + dprintf("y: %d\n", cheight-rowsleft+(bmy-2*yoffs-1)); while (rowsleft > 0) { - integer count = pkpackednum() ; /* get current color count */ + int count = pkPackedNum() ; /* get current color count */ while (count > 0) { if (count < hbit) { /* doesn't extend past row */ hbit -= count ; while (count--) row[rp++] = turnon ? PBM_BLACK : PBM_WHITE; } else { /* reaches end of row */ - count -= hbit ; + count -= hbit; while (hbit--) row[rp++] = turnon ? PBM_BLACK : PBM_WHITE; - for (i = 0; i <= repeatcount; i++) { /* fill row */ - int yi= i+cheight-rowsleft-1; - if (0<=yi && yi < bmy) + for (i = 0; i <= repeatCount; i++) { /* fill row */ + unsigned int const yi = i + cheight - rowsleft - 1; + if (0 <= yi && yi < bmy) { + unsigned int j; for (j = 0; j < cwidth; j++) { - int xj= j-xoffs; - if (0<=xj && xj<bmx) + unsigned int const xj= j - xoffs; + if (0 <= xj && xj < bmx) bitmap[yi][xj] = row[j] ; } + } } - rowsleft -= repeatcount + 1; - repeatcount = rp = 0 ; - hbit = cwidth ; + rowsleft -= repeatCount + 1; + repeatCount = rp = 0; + hbit = cwidth; } } - turnon = !turnon ; + turnon = !turnon; } if (rowsleft != 0 || hbit != cwidth) pm_error("bad pk file (more bits than required)") ; } - if (endofpacket != pktopbm_pkloc) + if (endOfPacket != pkLoc) pm_error("bad pk file (bad packet length)") ; - - ofp = pm_openw(filename[car]); - filename[car] = NULL; - pbm_writepbm(ofp, bitmap, bmx, bmy, 0) ; - pbm_freearray(bitmap, bmy) ; - pm_close(ofp) ; - skipspecials() ; + *bitmapP = bitmap; + *bmxP = bmx; + *bmyP = bmy; } - while (! feof(pkfile)) pktopbm_pkbyte() ; /* skip trailing junk */ - pm_close(pkfile); - for (car = 0; car < MAXPKCHAR; car++) - if (filename[car]) +} + + + +static void +generatePbmFile(const char * const fileNm, + bit ** const bitmap, + unsigned int const cols, + unsigned int const rows) { + + FILE * ofP; + + ofP = pm_openw(fileNm); + + pbm_writepbm(ofP, bitmap, cols, rows, 0); + + pm_close(ofP); +} + + + +static void +warnMissingCodePoint() { + + unsigned int car; + + for (car = 0; car < MAXPKCHAR; ++car) { + if (fileName[car]) pm_message("Warning: No character in position %d (file %s).", - car, filename[car]) ; - pm_message("%d bytes read from packed file.", pktopbm_pkloc-1) ; + car, fileName[car]) ; + } +} + + + +int +main(int argc, const char ** argv) { + + struct CmdlineInfo cmdline; + unsigned int i; + + pm_proginit(&argc, argv); + + parseCommandLine(argc, argv, &cmdline); + + debug = cmdline.debug; + + for (i = 0; i < cmdline.character; ++i) + fileName[i] = NULL; + for (i = 0; i < cmdline.outputFileCt; ++i) + fileName[cmdline.character + i] = cmdline.outputFileNm[i]; + for (i = cmdline.character + cmdline.outputFileCt; + i < MAXPKCHAR; + ++i) + fileName[i] = NULL; + + ifP = pm_openr(cmdline.inputFileNm); + + pkLoc = 0; + + readHeader(); + + while (flagByte != 245) { /* not at postamble */ + + unsigned int car; + bool mustIgnore; + bit ** bitmap; + unsigned int cols, rows; + + readOneCharacter(!!cmdline.xSpec, cmdline.x, + !!cmdline.ySpec, cmdline.y, + &car, &mustIgnore, &bitmap, &cols, &rows); + + if (!mustIgnore) { + generatePbmFile(fileName[car], bitmap, cols, rows); + + pbm_freearray(bitmap, rows) ; + } + + fileName[car] = NULL; + + skipSpecials(); + } + + while (!feof(ifP)) + pkByte() ; /* skip trailing junk */ + + pm_close(ifP); + + warnMissingCodePoint(); + + pm_message("%u bytes read from packed file.", pkLoc); + return 0; } + + + diff --git a/converter/pbm/thinkjettopbm.l b/converter/pbm/thinkjettopbm.l index 5de4f2bb..c55a0085 100644 --- a/converter/pbm/thinkjettopbm.l +++ b/converter/pbm/thinkjettopbm.l @@ -38,6 +38,7 @@ #include <errno.h> #include <unistd.h> #include "pm_c_util.h" +#include "mallocvar.h" #include "pbm.h" #include "shhopt.h" @@ -114,8 +115,10 @@ DIG [0-9] <RASTERMODE>\033\*b{DIG}+W { int l; if (rowCount >= rowCapacity) { + if (rowCapacity > INT_MAX-100) + pm_error("Too many rows to count"); rowCapacity += 100; - rows = realloc (rows, rowCapacity * sizeof *rows); + REALLOCARRAY(rows, rowCapacity); if (rows == NULL) pm_error ("Out of memory."); } @@ -223,6 +226,9 @@ yywrap (void) debug ("Got %d rows, %d columns\n", rowCount, maxRowLength); + if (maxRowLength > INT_MAX/8) + pm_error("A row has an uncomputably large number of columns: %d", + maxRowLength); /* * Quite simple since ThinkJet bit arrangement matches PBM */ diff --git a/converter/pbm/ybmtopbm.c b/converter/pbm/ybmtopbm.c index 36f2dee7..78eb79f2 100644 --- a/converter/pbm/ybmtopbm.c +++ b/converter/pbm/ybmtopbm.c @@ -10,6 +10,8 @@ ** implied warranty. */ +#include <limits.h> + #include "pm.h" #include "pbm.h" #include "bitreverse.h" @@ -80,6 +82,9 @@ main(int argc, const char * argv[]) { getinit(ifP, &cols, &rows, &depth); if (depth != 1) pm_error("YBM file has depth of %u, must be 1", (unsigned int) depth); + if (cols > INT_MAX - 15) + pm_error("YBM file has uncomputably large width %d", cols); + pbm_writepbminit(stdout, cols, rows, 0); |