about summary refs log tree commit diff
path: root/converter/pbm
diff options
context:
space:
mode:
Diffstat (limited to 'converter/pbm')
-rw-r--r--converter/pbm/mrftopbm.c64
-rw-r--r--converter/pbm/pbmtog3.c30
-rw-r--r--converter/pbm/pbmtomrf.c162
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);
 }