From 773463d6db696dc2910c83b7fa311bd91ca1d69c Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sun, 6 Jul 2008 17:07:36 +0000 Subject: Add fast PBM path for Pnmpad git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@661 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/pnmpad.c | 205 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 145 insertions(+), 60 deletions(-) (limited to 'editor/pnmpad.c') 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 #include -#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); -- cgit 1.4.1