about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--doc/HISTORY5
-rw-r--r--editor/pnmpad.c205
-rw-r--r--lib/libpbm2.c70
-rw-r--r--lib/pbm.h16
4 files changed, 226 insertions, 70 deletions
diff --git a/doc/HISTORY b/doc/HISTORY
index a4c7b3dc..a89b97e1 100644
--- a/doc/HISTORY
+++ b/doc/HISTORY
@@ -4,6 +4,11 @@ Netpbm.
 CHANGE HISTORY 
 --------------
 
+not yet  BJH  Release 10.44.00
+
+              pnmpad: Add fast PBM path.  Thanks Prophet of the Way
+              <afu@wta.att.ne.jp>.
+
 08.06.27 BJH  Release 10.43.00
 
               Add pamtompfont: Mplayer bitmap font.
diff --git a/editor/pnmpad.c b/editor/pnmpad.c
index 979fe017..f1541e96 100644
--- a/editor/pnmpad.c
+++ b/editor/pnmpad.c
@@ -1,13 +1,13 @@
 /* pnmpad.c - add border to sides of a portable anymap
- ** AJCD 4/9/90
+   ** AJCD 4/9/90
  */
 
 #include <string.h>
 #include <stdio.h>
 
-#include "pnm.h"
-#include "shhopt.h"
 #include "mallocvar.h"
+#include "shhopt.h"
+#include "pnm.h"
 
 #define MAX_WIDTHHEIGHT INT_MAX-10
 
@@ -55,7 +55,7 @@ parseCommandLine(int argc, const char ** argv,
     MALLOCARRAY_NOFAIL(option_def, 100);
 
     option_def_index = 0;   /* incremented by OPTENT3 */
-    OPTENT3(0,   "xsize",     OPT_UINT,    &cmdlineP->xsize,       
+    OPTENT3(0,   "xsize",     OPT_UINT,    &cmdlineP->xsize,
             &cmdlineP->xsizeSpec, 0);
     OPTENT3(0,   "width",     OPT_UINT,    &cmdlineP->xsize,
             &cmdlineP->xsizeSpec, 0);
@@ -63,13 +63,13 @@ parseCommandLine(int argc, const char ** argv,
             &cmdlineP->ysizeSpec, 0);
     OPTENT3(0,   "height",    OPT_UINT,    &cmdlineP->ysize,
             &cmdlineP->ysizeSpec, 0);
-    OPTENT3(0,   "left",      OPT_UINT,    &cmdlineP->left, 
+    OPTENT3(0,   "left",      OPT_UINT,    &cmdlineP->left,
             &cmdlineP->leftSpec, 0);
-    OPTENT3(0,   "right",     OPT_UINT,    &cmdlineP->right, 
+    OPTENT3(0,   "right",     OPT_UINT,    &cmdlineP->right,
             &cmdlineP->rightSpec, 0);
-    OPTENT3(0,   "top",       OPT_UINT,    &cmdlineP->top, 
+    OPTENT3(0,   "top",       OPT_UINT,    &cmdlineP->top,
             &cmdlineP->topSpec, 0);
-    OPTENT3(0,   "bottom",    OPT_UINT,    &cmdlineP->bottom, 
+    OPTENT3(0,   "bottom",    OPT_UINT,    &cmdlineP->bottom,
             &cmdlineP->bottomSpec, 0);
     OPTENT3(0,   "xalign",    OPT_FLOAT,   &cmdlineP->xalign,
             &xalignSpec,           0);
@@ -79,7 +79,7 @@ parseCommandLine(int argc, const char ** argv,
             &yalignSpec,           0);
     OPTENT3(0,   "valign",    OPT_FLOAT,   &cmdlineP->yalign,
             &yalignSpec,           0);
-    OPTENT3(0,   "black",     OPT_FLAG,    NULL, 
+    OPTENT3(0,   "black",     OPT_FLAG,    NULL,
             &blackOpt,           0);
     OPTENT3(0,   "white",     OPT_FLAG,    NULL,
             &cmdlineP->white,    0);
@@ -128,20 +128,20 @@ parseCommandLine(int argc, const char ** argv,
 
     if (xalignSpec) {
         if (cmdlineP->xalign < 0)
-            pm_error("You have specified a negative -halign value (%f)", 
+            pm_error("You have specified a negative -halign value (%f)",
                      cmdlineP->xalign);
         if (cmdlineP->xalign > 1)
-            pm_error("You have specified a -halign value (%f) greater than 1", 
+            pm_error("You have specified a -halign value (%f) greater than 1",
                      cmdlineP->xalign);
     } else
         cmdlineP->xalign = 0.5;
 
     if (yalignSpec) {
         if (cmdlineP->yalign < 0)
-            pm_error("You have specified a negative -halign value (%f)", 
+            pm_error("You have specified a negative -halign value (%f)",
                      cmdlineP->yalign);
         if (cmdlineP->yalign > 1)
-            pm_error("You have specified a -valign value (%f) greater than 1", 
+            pm_error("You have specified a -valign value (%f) greater than 1",
                      cmdlineP->yalign);
     } else
         cmdlineP->yalign = 0.5;
@@ -150,9 +150,9 @@ parseCommandLine(int argc, const char ** argv,
     if (argc-1 > 1)
         pm_error("This program takes at most 1 parameter.  You specified %d",
                  argc-1);
-    else if (argc-1 == 1) 
+    else if (argc-1 == 1)
         cmdlineP->input_filespec = argv[1];
-    else 
+    else
         cmdlineP->input_filespec = "-";
 }
 
@@ -177,7 +177,7 @@ parseCommandLineOld(int argc, const char ** argv,
         case 'l':
             if (atoi(argv[1]+2) < 0)
                 pm_error("left border too small");
-	    else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
+            else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
                 pm_error("left border too large");
             else
                 cmdlineP->left = atoi(argv[1]+2);
@@ -185,7 +185,7 @@ parseCommandLineOld(int argc, const char ** argv,
         case 'r':
             if (atoi(argv[1]+2) < 0)
                 pm_error("right border too small");
-	    else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
+            else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
                 pm_error("right border too large");
             else
                 cmdlineP->right = atoi(argv[1]+2);
@@ -193,7 +193,7 @@ parseCommandLineOld(int argc, const char ** argv,
         case 'b':
             if (atoi(argv[1]+2) < 0)
                 pm_error("bottom border too small");
-	    else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
+            else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
                 pm_error("bottom border too large");
             else
                 cmdlineP->bottom = atoi(argv[1]+2);
@@ -201,7 +201,7 @@ parseCommandLineOld(int argc, const char ** argv,
         case 't':
             if (atoi(argv[1]+2) < 0)
                 pm_error("top border too small");
-	    else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
+            else if (atoi(argv[1]+2) > MAX_WIDTHHEIGHT)
                 pm_error("top border too large");
             else
                 cmdlineP->top = atoi(argv[1]+2);
@@ -239,12 +239,12 @@ validateHorizontalSize(struct cmdlineInfo const cmdline,
 
     if (lpad > MAX_WIDTHHEIGHT)
         pm_error("The left padding value you specified is too large.");
-    
+
     if (rpad > MAX_WIDTHHEIGHT)
         pm_error("The right padding value you specified is too large.");
-    
+
     if ((double) cols + (double) lpad + (double) rpad > MAX_WIDTHHEIGHT)
-        pm_error("Given padding value(s) makes output width too large."); 
+        pm_error("Given padding value(s) makes output width too large.");
 }
 
 
@@ -256,7 +256,7 @@ computeHorizontalPadSizes(struct cmdlineInfo const cmdline,
                           unsigned int *     const rpadP) {
 
     validateHorizontalSize(cmdline, cols);
-    
+
     if (cmdline.xsizeSpec) {
         if (cmdline.leftSpec && cmdline.rightSpec) {
             if (cmdline.left + cols + cmdline.right < cmdline.xsize) {
@@ -270,7 +270,7 @@ computeHorizontalPadSizes(struct cmdlineInfo const cmdline,
             }
         } else if (cmdline.leftSpec) {
             *lpadP = cmdline.left;
-            *rpadP = MAX(cmdline.xsize, cmdline.left + cols) - 
+            *rpadP = MAX(cmdline.xsize, cmdline.left + cols) -
                 (cmdline.left + cols);
         } else if (cmdline.rightSpec) {
             *rpadP = cmdline.right;
@@ -303,15 +303,15 @@ validateVerticalSize(struct cmdlineInfo const cmdline,
 
     if (ysize > MAX_WIDTHHEIGHT)
         pm_error("The height value you specified is too large.");
-    
+
     if (tpad > MAX_WIDTHHEIGHT)
         pm_error("The top padding value you specified is too large.");
-    
+
     if (bpad > MAX_WIDTHHEIGHT)
         pm_error("The bottom padding value you specified is too large.");
-    
+
     if ((double) rows + (double) tpad + (double) bpad > MAX_WIDTHHEIGHT)
-        pm_error("Given padding value(s) makes output height too large."); 
+        pm_error("Given padding value(s) makes output height too large.");
 }
 
 
@@ -337,11 +337,11 @@ computeVerticalPadSizes(struct cmdlineInfo const cmdline,
             }
         } else if (cmdline.topSpec) {
             *tpadP = cmdline.top;
-            *bpadP = MAX(cmdline.ysize, cmdline.top + rows) - 
+            *bpadP = MAX(cmdline.ysize, cmdline.top + rows) -
                 (cmdline.top + rows);
         } else if (cmdline.bottomSpec) {
             *bpadP = cmdline.bottom;
-            *tpadP = MAX(cmdline.ysize, rows + cmdline.bottom) - 
+            *tpadP = MAX(cmdline.ysize, rows + cmdline.bottom) -
                 (rows + cmdline.bottom);
         } else {
             if (cmdline.ysize > rows) {
@@ -380,14 +380,117 @@ computePadSizes(struct cmdlineInfo const cmdline,
 
 
 
+static void
+padPbm(FILE *       const ifP,
+       unsigned int const cols,
+       unsigned int const rows,
+       int          const format,
+       unsigned int const newcols,
+       unsigned int const lpad,
+       unsigned int const rpad,
+       unsigned int const tpad,
+       unsigned int const bpad,
+       bool         const colorWhite) {
+/*----------------------------------------------------------------------------
+  Fast padding routine for PBM
+-----------------------------------------------------------------------------*/
+    unsigned char * const bgrow  = pbm_allocrow_packed(newcols);
+    unsigned char * const newrow = pbm_allocrow_packed(newcols);
+
+    unsigned char const padChar =
+        0xff * (colorWhite ? PBM_WHITE : PBM_BLACK);
+
+    unsigned int const newColChars = pbm_packed_bytes(newcols);
+
+    unsigned int row;
+    unsigned int charCnt;
+
+    /* Set up margin row, input-output buffer */
+    for (charCnt = 0; charCnt < newColChars; ++charCnt)
+        bgrow[charCnt] = newrow[charCnt] = padChar;
+
+    if (newcols % 8 > 0) {
+        bgrow[newColChars-1]  <<= 8 - newcols % 8;
+        newrow[newColChars-1] <<= 8 - newcols % 8;
+    }
+
+    pbm_writepbminit(stdout, newcols, rows + tpad + bpad, 0);
+
+    /* Write top margin */
+    for (row = 0; row < tpad; ++row)
+        pbm_writepbmrow_packed(stdout, bgrow, newcols, 0);
+    
+    /* Read rows, shift and write with left and right margins added */
+    for (row = 0; row < rows; ++row) {
+        pbm_readpbmrow_bitoffset(ifP, newrow, cols, format, lpad);
+        pbm_writepbmrow_packed(stdout, newrow, newcols, 0);
+    }
+
+    pnm_freerow(newrow);
+
+    /* Write bottom margin */
+    for (row = 0; row < bpad; ++row)
+        pbm_writepbmrow_packed(stdout, bgrow, newcols, 0);
+
+    pnm_freerow(bgrow);
+}
+
+
+static void
+padGeneral(FILE *       const ifP,
+           unsigned int const cols,
+           unsigned int const rows,
+           xelval       const maxval,
+           int          const format,
+           unsigned int const newcols,
+           unsigned int const lpad,
+           unsigned int const rpad,
+           unsigned int const tpad,
+           unsigned int const bpad,
+           bool         const colorWhite) {
+/*----------------------------------------------------------------------------
+  General padding routine (logic works for PBM)
+-----------------------------------------------------------------------------*/
+    xel * const bgrow  = pnm_allocrow(newcols);
+    xel * const xelrow = pnm_allocrow(newcols);
+    xel background;
+    unsigned int row, col;
+
+    if (colorWhite)
+        background = pnm_whitexel(maxval, format);
+    else
+        background = pnm_blackxel(maxval, format);
+
+    for (col = 0; col < newcols; ++col)
+        xelrow[col] = bgrow[col] = background;
+
+    pnm_writepnminit(stdout, newcols, rows + tpad + bpad, maxval, format, 0);
+
+    for (row = 0; row < tpad; ++row)
+        pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0);
+
+    for (row = 0; row < rows; ++row) {
+        pnm_readpnmrow(ifP, &xelrow[lpad], cols, maxval, format);
+        pnm_writepnmrow(stdout, xelrow, newcols, maxval, format, 0);
+    }
+
+    for (row = 0; row < bpad; ++row)
+        pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0);
+
+    pnm_freerow(xelrow);
+    pnm_freerow(bgrow);
+}
+
+
+
 int
 main(int argc, const char ** argv) {
 
     struct cmdlineInfo cmdline;
-    FILE *ifP;
-    xel *xelrow, *bgrow, background;
+    FILE * ifP;
+
     xelval maxval;
-    int rows, cols, newcols, row, col, format;
+    int rows, cols, newcols, format;
     bool depr_cmd; /* use deprecated commandline interface */
     unsigned int lpad, rpad, tpad, bpad;
 
@@ -401,7 +504,7 @@ main(int argc, const char ** argv) {
             if (argv[1][2] >= '0' && argv[1][2] <= '9')
                 depr_cmd = TRUE;
         }
-    } 
+    }
     if (argc > 2 && argv[2][0] == '-') {
         if (argv[2][1] == 't' || argv[2][1] == 'b'
             || argv[2][1] == 'l' || argv[2][1] == 'r') {
@@ -410,45 +513,27 @@ main(int argc, const char ** argv) {
         }
     }
 
-    if (depr_cmd) 
+    if (depr_cmd)
         parseCommandLineOld(argc, argv, &cmdline);
-    else 
+    else
         parseCommandLine(argc, argv, &cmdline);
 
     ifP = pm_openr(cmdline.input_filespec);
 
     pnm_readpnminit(ifP, &cols, &rows, &maxval, &format);
-    if (cmdline.white)
-        background = pnm_whitexel(maxval, format);
-    else
-        background = pnm_blackxel(maxval, format);
 
     if (cmdline.verbose) pm_message("image WxH = %dx%d", cols, rows);
 
     computePadSizes(cmdline, cols, rows, &lpad, &rpad, &tpad, &bpad);
 
     newcols = cols + lpad + rpad;
-    xelrow = pnm_allocrow(newcols);
-    bgrow = pnm_allocrow(newcols);
 
-    for (col = 0; col < newcols; col++)
-        xelrow[col] = bgrow[col] = background;
-
-    pnm_writepnminit(stdout, newcols, rows + tpad + bpad, maxval, format, 0);
-
-    for (row = 0; row < tpad; row++)
-        pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0);
-
-    for (row = 0; row < rows; row++) {
-        pnm_readpnmrow(ifP, &xelrow[lpad], cols, maxval, format);
-        pnm_writepnmrow(stdout, xelrow, newcols, maxval, format, 0);
-    }
-
-    for (row = 0; row < bpad; row++)
-        pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0);
-
-    pnm_freerow(xelrow);
-    pnm_freerow(bgrow);
+    if (PNM_FORMAT_TYPE(format) == PBM_TYPE)
+        padPbm(ifP, cols, rows, format, newcols, lpad, rpad, tpad, bpad,
+               !!cmdline.white);
+    else
+        padGeneral(ifP, cols, rows, maxval, format, 
+                   newcols, lpad, rpad, tpad, bpad, !!cmdline.white);
 
     pm_close(ifP);
 
diff --git a/lib/libpbm2.c b/lib/libpbm2.c
index df1443a3..3dbd7173 100644
--- a/lib/libpbm2.c
+++ b/lib/libpbm2.c
@@ -157,8 +157,8 @@ pbm_readpbmrow( file, bitrow, cols, format )
 
 
 void
-pbm_readpbmrow_packed(FILE *          const file, 
-                      unsigned char * const packed_bits,
+pbm_readpbmrow_packed(FILE *          const fileP, 
+                      unsigned char * const packedBits,
                       int             const cols, 
                       int             const format) {
 
@@ -169,22 +169,22 @@ pbm_readpbmrow_packed(FILE *          const file,
 
         /* We first clear the return buffer, then set ones where needed */
         for (byteIndex = 0; byteIndex < pbm_packed_bytes(cols); ++byteIndex)
-            packed_bits[byteIndex] = 0x00;
+            packedBits[byteIndex] = 0x00;
 
         for (col = 0; col < cols; ++col) {
             unsigned char mask;
-            mask = getbit(file) << (7 - col % 8);
-            packed_bits[col / 8] |= mask;
+            mask = getbit(fileP) << (7 - col % 8);
+            packedBits[col / 8] |= mask;
         }
     }
     break;
 
     case RPBM_FORMAT: {
         int bytes_read;
-        bytes_read = fread(packed_bits, 1, pbm_packed_bytes(cols), file);
+        bytes_read = fread(packedBits, 1, pbm_packed_bytes(cols), fileP);
              
         if (bytes_read < pbm_packed_bytes(cols)) {
-            if (feof(file)) 
+            if (feof(fileP)) 
                 if (bytes_read == 0) 
                     pm_error("Attempt to read a raw PBM image row, but "
                              "no more rows left in file.");
@@ -203,6 +203,62 @@ pbm_readpbmrow_packed(FILE *          const file,
 
 
 
+void
+pbm_readpbmrow_bitoffset(FILE *          const ifP,
+                         unsigned char * const packedBits, 
+                         int             const cols,
+                         int             const format,
+                         unsigned int    const offset) {
+/*----------------------------------------------------------------------------
+   Read PBM packed bitrow from file 'ifP' (raster format given by
+   'cols' and 'format') and shift right 'offset' bits.
+
+   Read it into packedBits[], preserving surrounding image data.
+
+   Logic not tested for negative offsets.
+-----------------------------------------------------------------------------*/
+    unsigned int const rsh = offset % 8;
+    unsigned int const lsh = (8 - rsh) % 8;
+    unsigned char * const window = &packedBits[offset/8];
+        /* Area of packed row buffer into which we read the image data.
+           Aligned to nearest byte boundary to the left, so the first
+           few bits might contain original data, not output.
+        */
+    unsigned int const last = pbm_packed_bytes(cols+rsh) - 1;
+        /* Position within window of rightmost byte after shift */
+
+    /* The original leftmost and rightmost chars. */
+    unsigned char const origHead = window[0];
+    unsigned char const origEnd  = window[last];
+
+    pbm_readpbmrow_packed(ifP, window, cols, format);
+
+    if (rsh > 0) {
+        /* Target slot doesn't start on byte boundary; right-shift. */
+        unsigned char carryover;
+        unsigned int i;
+  
+        carryover = (origHead >> lsh) << lsh;
+
+        for (i = 0; i <= last; ++i) {
+            unsigned char const t = window[i] << lsh;
+            window[i] = carryover | window[i] >> rsh;
+            carryover = t;
+        }
+    }
+  
+    if ((cols + rsh) % 8 > 0) {
+        /* Adjust rightmost char */
+        unsigned int  const trs = (cols + rsh) % 8;
+        unsigned int  const tls = 8 - trs;
+        unsigned char const origEndShift = (origEnd << trs) >> trs;
+
+        window[last] = (window[last] >> tls) << tls | origEndShift;
+    }
+} 
+
+
+
 bit**
 pbm_readpbm( file, colsP, rowsP )
     FILE* file;
diff --git a/lib/pbm.h b/lib/pbm.h
index b9ef3479..840e1491 100644
--- a/lib/pbm.h
+++ b/lib/pbm.h
@@ -61,9 +61,19 @@ pbm_allocrow(unsigned int const cols);
 bit** pbm_readpbm(FILE* file, int* colsP, int* rowsP);
 void pbm_readpbminit(FILE* file, int* colsP, int* rowsP, int* formatP);
 void pbm_readpbmrow(FILE* file, bit* bitrow, int cols, int format);
-void pbm_readpbmrow_packed(
-    FILE* const file, unsigned char * const packed_bits, 
-    const int cols, const int format);
+
+void
+pbm_readpbmrow_packed(FILE *          const file, 
+                      unsigned char * const packedBits,
+                      int             const cols, 
+                      int             const format);
+
+void
+pbm_readpbmrow_bitoffset(FILE *          const fileP,
+                         unsigned char * const packedBits, 
+                         int             const cols,
+                         int             const format,
+                         unsigned int    const offset);
 
 void
 pbm_writepbminit(FILE * const fileP,