about summary refs log tree commit diff
path: root/editor/pnmpad.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-07-06 17:07:36 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2008-07-06 17:07:36 +0000
commit773463d6db696dc2910c83b7fa311bd91ca1d69c (patch)
tree4be0f5f94b5cd76a5dd1e2e39c7a284e4e5f6f11 /editor/pnmpad.c
parente96eb23dd2b9056014120b132801a35c8856dec6 (diff)
downloadnetpbm-mirror-773463d6db696dc2910c83b7fa311bd91ca1d69c.tar.gz
netpbm-mirror-773463d6db696dc2910c83b7fa311bd91ca1d69c.tar.xz
netpbm-mirror-773463d6db696dc2910c83b7fa311bd91ca1d69c.zip
Add fast PBM path for Pnmpad
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@661 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor/pnmpad.c')
-rw-r--r--editor/pnmpad.c205
1 files changed, 145 insertions, 60 deletions
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);