about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-12-31 22:18:58 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-12-31 22:18:58 +0000
commit8fad703a62bf24c7f9aa53514ce6e3fa27c8c36e (patch)
tree53f5a33c7b2472a7a2b7b2084051e59cb23329af
parentcc003b5518ab0a5e11a92d57da3f4a6dfe5d87bd (diff)
downloadnetpbm-mirror-8fad703a62bf24c7f9aa53514ce6e3fa27c8c36e.tar.gz
netpbm-mirror-8fad703a62bf24c7f9aa53514ce6e3fa27c8c36e.tar.xz
netpbm-mirror-8fad703a62bf24c7f9aa53514ce6e3fa27c8c36e.zip
Fix crashes, incorrect output in all cases
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@804 9d0c8265-081b-0410-96cb-a4ca84ce46f8
-rw-r--r--converter/pbm/mrftopbm.c61
-rw-r--r--converter/pbm/pbmtomrf.c160
-rw-r--r--doc/HISTORY5
3 files changed, 155 insertions, 71 deletions
diff --git a/converter/pbm/mrftopbm.c b/converter/pbm/mrftopbm.c
index 9cf93d47..51281028 100644
--- a/converter/pbm/mrftopbm.c
+++ b/converter/pbm/mrftopbm.c
@@ -41,31 +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. */
-        doSquare(in, image, ox,      oy,     w, size >> 1);
-        doSquare(in, image, ox+size, oy,     w, size >> 1);
-        doSquare(in, image, ox,      oy+size,w, size >> 1);
-        doSquare(in, image, ox+size, oy+size,w, size >> 1);
+        /* 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);
     }
 }
 
@@ -77,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;
@@ -142,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/pbmtomrf.c b/converter/pbm/pbmtomrf.c
index 186e95f5..e7b7fcc9 100644
--- a/converter/pbm/pbmtomrf.c
+++ b/converter/pbm/pbmtomrf.c
@@ -13,81 +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) {
-        bit_output(0);    /* not all same */
-        doSquare(image, ox,      oy,      w, size>>1);
-        doSquare(image, ox+size, oy,      w, size>>1);
-        doSquare(image, ox,      oy+size, w, size>>1);
-        doSquare(image, ox+size, oy+size, w, size>>1);
+    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);
+        }
     }
 }
     
@@ -241,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");
                  
@@ -274,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");
@@ -283,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);
 }
 
 
diff --git a/doc/HISTORY b/doc/HISTORY
index ade42e40..203da01d 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -6,6 +6,9 @@ CHANGE HISTORY
 
 not yet  BJH  Release 10.46.00
 
+              pbmtomrf, mrftopbm: fix crashes, incorrect output in all
+              cases.  Broken forever.
+
               pamcut: fix bug with PBM and -pad.
 
 08.12.28 BJH  Release 10.45.00
@@ -1870,6 +1873,8 @@ not yet  BJH  Release 10.46.00
 
 03.09.19 BJH  Release 10.18
 
+              Add pbmtomrf, mrftopbm.
+
               Add escp2topbm, pbmtoescp2.  Thanks Ulrich Walcher
               <u.walcher@gmx.de>