diff options
Diffstat (limited to 'converter/pbm')
-rw-r--r-- | converter/pbm/mrftopbm.c | 64 | ||||
-rw-r--r-- | converter/pbm/pbmtog3.c | 30 | ||||
-rw-r--r-- | converter/pbm/pbmtomrf.c | 162 |
3 files changed, 167 insertions, 89 deletions
diff --git a/converter/pbm/mrftopbm.c b/converter/pbm/mrftopbm.c index b7534115..51281028 100644 --- a/converter/pbm/mrftopbm.c +++ b/converter/pbm/mrftopbm.c @@ -41,34 +41,50 @@ bit_input(FILE * const in) { static void -doSquare(FILE * const in, - unsigned char * const image, - int const ox, - int const oy, - int const w, - int const size) { - - if (size == 1 || bit_input(in)) { +doSquare(FILE * const ifP, + unsigned char * const image, + unsigned int const ulCol, + unsigned int const ulRow, + unsigned int const imageWidth, + unsigned int const size) { +/*---------------------------------------------------------------------------- + Do a square of side 'size', whose upper left corner is at (ulCol, ulRow). + The contents of that square are next in file *ifP, in MRF format. + + Return the pixel values of the square in the corresponding position of + image[], which is a concatenation of rows 'imageWidth' pixels wide, one + byte per pixel. +-----------------------------------------------------------------------------*/ + if (size == 1 || bit_input(ifP)) { /* It's all black or all white. Next bit says which. */ - unsigned int const c = bit_input(in); + unsigned int const c = bit_input(ifP); - unsigned int y; + unsigned int rowOfSquare; - for (y = 0; y < size; ++y) { - unsigned int x; - for (x = 0; x < size; ++x) - image[(oy+y)*w+ox+x] = c; + for (rowOfSquare = 0; rowOfSquare < size; ++rowOfSquare) { + unsigned int colOfSquare; + for (colOfSquare = 0; colOfSquare < size; ++colOfSquare) { + unsigned int rowOfImage = ulRow + rowOfSquare; + unsigned int colOfImage = ulCol + colOfSquare; + + image[rowOfImage * imageWidth + colOfImage] = c; + } } } else { - /* not all one color, so recurse. */ - - int halfsize = size >> 1; - - doSquare(in, image, ox, oy, w, halfsize); - doSquare(in, image, ox+halfsize, oy, w, halfsize); - doSquare(in, image, ox, oy+halfsize, w, halfsize); - doSquare(in, image, ox+halfsize, oy+halfsize, w, halfsize); + /* Square is not all one color, so recurse. Do each of the four + quadrants of this square individually. + */ + unsigned int const quadSize = size/2; + + doSquare(ifP, image, ulCol, ulRow, + imageWidth, quadSize); + doSquare(ifP, image, ulCol + quadSize, ulRow, + imageWidth, quadSize); + doSquare(ifP, image, ulCol, ulRow + quadSize, + imageWidth, quadSize); + doSquare(ifP, image, ulCol + quadSize, ulRow + quadSize, + imageWidth, quadSize); } } @@ -80,7 +96,7 @@ writeOutput(FILE * const ofP, int const rows, const unsigned char * const image) { - /* w64 is units-of-64-bits width, h64 same for height */ + /* w64 is units-of-64-bits width */ unsigned int const w64 = (cols+63)/64; bit * bitrow; @@ -145,7 +161,7 @@ readMrfImage(FILE * const ifP, pm_error("Ridiculously large, unprocessable image: %u cols x %u rows", cols, rows); - image = calloc(w64*h64*64*64,1); + image = calloc(w64*h64*64*64, 1); if (image == NULL) pm_error("Unable to get memory for raster"); diff --git a/converter/pbm/pbmtog3.c b/converter/pbm/pbmtog3.c index 0b536390..3fe7f3fc 100644 --- a/converter/pbm/pbmtog3.c +++ b/converter/pbm/pbmtog3.c @@ -55,7 +55,7 @@ struct bitString { struct outStream { struct bitString buffer; - + bool reverseBits; }; @@ -109,6 +109,8 @@ parseCommandLine(int argc, char ** const argv, optParseOptions3(&argc, argv, opt, sizeof(opt), 0); /* Uses and sets argc, argv, and some of *cmdlineP and others. */ + free(option_def); + if (argc-1 == 0) cmdlineP->inputFileName = "-"; else if (argc-1 != 1) @@ -142,7 +144,7 @@ makeBs(wordint const bits, return retval; } - + static __inline__ void putbits(struct bitString const newBits) { @@ -153,7 +155,7 @@ putbits(struct bitString const newBits) { Flush the buffer to stdout as necessary to make room. 'newBits' must be shorter than a whole word. - + N.B. the definition of struct bitString requires upper bits to be zero. -----------------------------------------------------------------------------*/ unsigned int const spaceLeft = @@ -182,11 +184,11 @@ putbits(struct bitString const newBits) { | (newBits.intBuffer >> nextBufBitCount)); if (out.reverseBits) reversebuffer(outbytes, sizeof(outbytes)); - + rc = fwrite(outbytes, 1, sizeof(outbytes), stdout); if (rc != sizeof(outbytes)) pm_error("Output error. Unable to fwrite() to stdout"); - + out.buffer.intBuffer = newBits.intBuffer & ((1<<nextBufBitCount) - 1); out.buffer.bitCount = nextBufBitCount; } @@ -237,7 +239,7 @@ putcode2(int const clr, if (sizeof(wordint) * 8 > 24) { unsigned int const l1 = ttable[loIndex].length; - + putbits( makeBs(mtable[hiIndex].code << l1 | ttable[loIndex].code, mtable[hiIndex].length + l1) @@ -299,7 +301,7 @@ puteol(void) { puts("EOL"); else { struct bitString const eol = {12, 1}; - + putbits(eol); } } @@ -341,7 +343,7 @@ convertRowToRunLengths(unsigned char * const bitrow, wordint * const bitrowByWord = (wordint *) bitrow; int const wordCount = (cols + bitsPerWord - 1)/bitsPerWord; /* Number of full and partial words in the row */ - + if (cols % bitsPerWord != 0) { /* Clean final word in row. For loop simplicity */ @@ -411,7 +413,7 @@ main(int argc, a word of zero padding on the high (right) end for the convenience of code that accesses this buffer in word-size bites. */ - + int rows; int cols; int readcols; @@ -423,7 +425,7 @@ main(int argc, pbm_init(&argc, argv); parseCommandLine(argc, argv, &cmdline); - + ifP = pm_openr(cmdline.inputFileName); pbm_readpbminit(ifP, &cols, &rows, &format); @@ -447,9 +449,9 @@ main(int argc, unsigned int i; pbm_readpbmrow_packed(ifP, bitrow, cols, format); - + convertRowToRunLengths(bitrow, readcols, milepost, &nRun); - + padToDesiredWidth(milepost, &nRun, readcols, outwidth); for (i = p = 0; i < nRun; p = milepost[i++]) @@ -459,6 +461,8 @@ main(int argc, } free(milepost); + pbm_freerow_packed(bitrow); + { unsigned int i; for( i = 0; i < 6; ++i) @@ -467,7 +471,7 @@ main(int argc, if (out.buffer.bitCount > 0) { /* flush final partial buffer */ unsigned int const bytesToWrite = (out.buffer.bitCount+7)/8; - + unsigned char outbytes[sizeof(wordint)]; size_t rc; wordintToBytes(&outbytes, diff --git a/converter/pbm/pbmtomrf.c b/converter/pbm/pbmtomrf.c index c93c88aa..e7b7fcc9 100644 --- a/converter/pbm/pbmtomrf.c +++ b/converter/pbm/pbmtomrf.c @@ -13,83 +13,139 @@ #include "pm_c_util.h" #include "pbm.h" -static int bitbox; -static int bitsleft; -static FILE *bit_out; + +typedef struct bitOut { + int bitbox; + int bitsleft; + FILE * fileP; +} bitOut; + static void -bit_init(FILE * const out) { - bitbox = 0; - bitsleft = 8; - bit_out = out; +bit_init(struct bitOut * const bitOutP, + FILE * const ofP) { + + bitOutP->bitbox = 0; + bitOutP->bitsleft = 8; + bitOutP->fileP = ofP; } static void -bit_output(int const bit) { - --bitsleft; - bitbox |= (bit << bitsleft); - if (bitsleft == 0) { - fputc(bitbox, bit_out); - bitbox = 0; - bitsleft = 8; +bit_output(struct bitOut * const bitOutP, + int const bit) { + + --bitOutP->bitsleft; + bitOutP->bitbox |= (bit << bitOutP->bitsleft); + if (bitOutP->bitsleft == 0) { + fputc(bitOutP->bitbox, bitOutP->fileP); + bitOutP->bitbox = 0; + bitOutP->bitsleft = 8; } } static void -bit_flush(void) { +bit_flush(struct bitOut * const bitOutP) { /* there are never 0 bits left outside of bit_output, but * if 8 bits are left here there's nothing to flush, so * only do it if bitsleft!=8. */ - if (bitsleft != 8) { - bitsleft = 1; - bit_output(0); /* yes, really. This will always work. */ + if (bitOutP->bitsleft != 8) { + bitOutP->bitsleft = 1; + bit_output(bitOutP, 0); /* yes, really. This will always work. */ } } -static void -doSquare(unsigned char * const image, - int const ox, - int const oy, - int const w, - int const size) { - - unsigned int y; +static void +determineBlackWhiteOrMix(const unsigned char * const image, + unsigned int const ulCol, + unsigned int const ulRow, + unsigned int const imageWidth, + unsigned int const size, + bool * const oneColorP, + int * const colorP) { +/*---------------------------------------------------------------------------- + Determine whether a square within 'image' is all white, all black, + or a mix. +-----------------------------------------------------------------------------*/ + unsigned int rowOfSquare; unsigned int t; - /* check square to see if it's all black or all white. */ + for (rowOfSquare = 0, t = 0; rowOfSquare < size; ++rowOfSquare) { + unsigned int colOfSquare; + for (colOfSquare = 0; colOfSquare < size; ++colOfSquare) { + unsigned int rowOfImage = ulRow + rowOfSquare; + unsigned int colOfImage = ulCol + colOfSquare; - t = 0; - for (y = 0; y < size; ++y) { - unsigned int x; - for (x = 0; x < size; ++x) - t += image[(oy+y)*w + ox + x]; + t += image[rowOfImage * imageWidth + colOfImage]; + } } /* if the total's 0, it's black. if it's size*size, it's white. */ - if (t == 0 || t == size*size) { - if (size != 1) /* (it's implicit when size is 1, of course) */ - bit_output(1); /* all same color */ - bit_output(t?1:0); - return; - } - - /* otherwise, if our square is greater than 1x1, we need to recurse. */ - if(size > 1) { - int halfsize = size >> 1; - - bit_output(0); /* not all same */ - doSquare(image, ox, oy, w, halfsize); - doSquare(image, ox+halfsize, oy, w, halfsize); - doSquare(image, ox, oy+halfsize, w, halfsize); - doSquare(image, ox+halfsize, oy+halfsize, w, halfsize); + if (t == 0) { + *oneColorP = TRUE; + *colorP = 0; + } else if (t == SQR(size)) { + *oneColorP = TRUE; + *colorP = 1; + } else + *oneColorP = FALSE; +} + + + +static void +doSquare(bitOut * const bitOutP, + const unsigned char * const image, + unsigned int const ulCol, + unsigned int const ulRow, + unsigned int const imageWidth, + unsigned int const size) { +/*---------------------------------------------------------------------------- + Do a square of side 'size', whose upper left corner is at (ulCol, ulRow). + This is a square within 'image', which is a concatenation of rows + 'imageWidth' pixels wide, one byte per pixel. + + Write the pixel values out to the bit stream *bitOutP, in MRF format. +-----------------------------------------------------------------------------*/ + if (size == 1) { + /* The fact that it is all one color is implied because the square is + just one pixel; no bit goes in MRF output to state that. + */ + bit_output(bitOutP, image[ulRow * imageWidth + ulCol] ? 1 : 0); + } else { + bool oneColor; + int color; + + determineBlackWhiteOrMix(image, ulCol, ulRow, imageWidth, size, + &oneColor, &color); + + if (oneColor) { + bit_output(bitOutP, 1); /* all same color */ + bit_output(bitOutP, color); + } else { + /* Square is not all the same color, so recurse. Do each + of the four quadrants of this square individually. + */ + unsigned int const quadSize = size/2; + + bit_output(bitOutP, 0); /* not all same color */ + + doSquare(bitOutP, image, ulCol, ulRow, + imageWidth, quadSize); + doSquare(bitOutP, image, ulCol + quadSize, ulRow, + imageWidth, quadSize); + doSquare(bitOutP, image, ulCol, ulRow + quadSize, + imageWidth, quadSize); + doSquare(bitOutP, image, ulCol + quadSize, ulRow + quadSize, + imageWidth, quadSize); + } } } @@ -243,7 +299,7 @@ readPbmImage(FILE * const ifP, pm_error("Ridiculously large, unprocessable image: %u cols x %u rows", cols, rows); - image = calloc(w64*h64*64*64,1); + image = calloc(w64*h64*64*64, 1); if (image == NULL) pm_error("Unable to get memory for raster"); @@ -276,6 +332,8 @@ outputMrf(FILE * const ofP, unsigned int const w64 = (cols + 63) / 64; unsigned int const h64 = (rows + 63) / 64; + bitOut bitOut; + unsigned int row; fprintf(ofP, "MRF1"); @@ -285,14 +343,14 @@ outputMrf(FILE * const ofP, /* now recursively check squares. */ - bit_init(ofP); + bit_init(&bitOut, ofP); for (row = 0; row < h64; ++row) { unsigned int col; for (col = 0; col < w64; ++col) - doSquare(image, col*64, row*64, w64*64, 64); + doSquare(&bitOut, image, col*64, row*64, w64*64, 64); } - bit_flush(); + bit_flush(&bitOut); } |