about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--converter/ppm/pcxtoppm.c38
-rw-r--r--doc/HISTORY3
2 files changed, 33 insertions, 8 deletions
diff --git a/converter/ppm/pcxtoppm.c b/converter/ppm/pcxtoppm.c
index f06dd4e8..8341cf18 100644
--- a/converter/ppm/pcxtoppm.c
+++ b/converter/ppm/pcxtoppm.c
@@ -363,9 +363,25 @@ pcxPlanesToPixels(unsigned char * const pixels,
                   unsigned int    const planes,
                   unsigned int    const bitsPerPixel) {
 /*----------------------------------------------------------------------------
-   Convert multi-plane format into 1 pixel per byte.
+   Unpack sub-byte sample values to yield one byte per pixel.
+
+   As input, 'bitPlanes' is a row of the image.  Each byte contains 8 samples,
+   one per bit.  They are arranged in plane major, column minor order, e.g.
+   in a 100-column image, the Plane 1 samples of the Columns 0-8 are in
+   bitPlanes[100].
+
+   As output, each byte of 'pixels' is one pixel, in major order by column and
+   minor order by plane, e.g. in a 4-plane image, pixels[5] is the Plane 1 of
+   Column 1.
+
+   'bitsPerPixel' is the number of bits per sample, and must be 1.  It's easy
+   to conceive how this subroutine should work with other numbers of bits per
+   sample, but it doesn't.
 -----------------------------------------------------------------------------*/
-    unsigned int const npixels = (bytesPerLine * 8) / bitsPerPixel;
+    unsigned int const pixelCt = bytesPerLine * 8;
+
+    unsigned int bitPlanesIdx;
+        /* Index into 'bitPlanes' of next byte to unpack */
 
     unsigned int  i;
 
@@ -375,23 +391,29 @@ pcxPlanesToPixels(unsigned char * const pixels,
         pm_error("can't handle more than 1 bit per pixel");
 
     /* Clear the pixel buffer - initial value */
-    for (i = 0; i < npixels; ++i)
+    for (i = 0; i < pixelCt; ++i)
         pixels[i] = 0;
 
+    bitPlanesIdx = 0;  /* initial value */
+
     for (i = 0; i < planes; ++i) {
         unsigned int const pixbit = (1 << i);
 
+        unsigned int pixelIdx;
+            /* Index into 'pixels' of next pixel to output */
+
         unsigned int j;
 
-        for (j = 0; j < bytesPerLine; ++j) {
-            unsigned int const bits = bitPlanes[j];
+        for (j = 0, pixelIdx = 0; j < bytesPerLine; ++j) {
+            unsigned int const bits = bitPlanes[bitPlanesIdx++];
 
             unsigned int mask;
-            unsigned int k;
 
-            for (mask = 0x80, k = 0; mask != 0; mask >>= 1, ++k)
+            for (mask = 0x80; mask != 0; mask >>= 1) {
                 if (bits & mask)
-                    pixels[k] |= pixbit;
+                    pixels[pixelIdx] |= pixbit;
+                ++pixelIdx;
+            }
         }
     }
 }
diff --git a/doc/HISTORY b/doc/HISTORY
index 17c0b0f5..4a84359b 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -6,6 +6,9 @@ CHANGE HISTORY
 
 not yet  BJH  Release 11.09.00
 
+              pcxtoppm: Fix wildly incorrect output for all multiplane
+              images.  Broken in Netpbm 11.04 (September 2023).
+
               pbmtoascii: fix bug: allows both -1x2 and -2x4.  Always present
               (pbmtoascii existed in primordial Netpbm).