/* pnmpad.c - add border to sides of a portable anymap ** AJCD 4/9/90 */ /* * Changelog * * 2002/01/25 - Rewrote options parsing code. * Added pad-to-width and pad-to-height with custom * alignment. MVB. */ #include #include "pnm.h" #include "shhopt.h" struct cmdline_info { /* All the information the user supplied in the command line, in a form easy for the program to use. */ const char *input_filespec; /* Filespecs of input files */ unsigned int xsize; unsigned int ysize; unsigned int lpad; unsigned int rpad; unsigned int tpad; unsigned int bpad; float xalign; float yalign; bool white; /* TRUE: pad white; FALSE: pad black */ bool verbose; }; static void parse_command_line(int argc, char ** argv, struct cmdline_info * const cmdline_p) { /*---------------------------------------------------------------------------- Note that the file spec array we return is stored in the storage that was passed to us as the argv array. -----------------------------------------------------------------------------*/ optStruct *option_def = malloc(100*sizeof(optStruct)); /* Instructions to OptParseOptions2 on how to parse our options. */ optStruct2 opt; unsigned int option_def_index; bool black = FALSE; /* trap -black option (ignored as black is default) */ cmdline_p->xsize = cmdline_p->ysize = 0; cmdline_p->lpad = cmdline_p->rpad = cmdline_p->tpad = cmdline_p->bpad = 0; cmdline_p->xalign = cmdline_p->yalign = 0.5; cmdline_p->white = cmdline_p->verbose = FALSE; option_def_index = 0; /* incremented by OPTENTRY */ OPTENTRY(0, "xsize", OPT_UINT, &cmdline_p->xsize, 0); OPTENTRY(0, "width", OPT_UINT, &cmdline_p->xsize, 0); OPTENTRY(0, "ysize", OPT_UINT, &cmdline_p->ysize, 0); OPTENTRY(0, "height", OPT_UINT, &cmdline_p->ysize, 0); OPTENTRY(0, "left", OPT_UINT, &cmdline_p->lpad, 0); OPTENTRY(0, "right", OPT_UINT, &cmdline_p->rpad, 0); OPTENTRY(0, "top", OPT_UINT, &cmdline_p->tpad, 0); OPTENTRY(0, "bottom", OPT_UINT, &cmdline_p->bpad, 0); OPTENTRY(0, "xalign", OPT_FLOAT, &cmdline_p->xalign, 0); OPTENTRY(0, "halign", OPT_FLOAT, &cmdline_p->xalign, 0); OPTENTRY(0, "yalign", OPT_FLOAT, &cmdline_p->yalign, 0); OPTENTRY(0, "valign", OPT_FLOAT, &cmdline_p->yalign, 0); OPTENTRY(0, "black", OPT_FLAG, &black, 0); OPTENTRY(0, "white", OPT_FLAG, &cmdline_p->white, 0); OPTENTRY(0, "verbose", OPT_FLAG, &cmdline_p->verbose, 0); /* Set the defaults. -1 = unspecified */ cmdline_p->verbose = FALSE; opt.opt_table = option_def; opt.short_allowed = FALSE; /* We have no short (old-fashioned) options */ opt.allowNegNum = FALSE; /* We have no parms that are negative numbers */ optParseOptions2(&argc, argv, opt, 0); /* Uses and sets argc, argv, and some of *cmdline_p and others. */ /* reject invalid values */ if (cmdline_p->xalign < 0) pm_error("You have specified a negative halign value (%f)", cmdline_p->xalign); if (cmdline_p->xalign > 1) pm_error("You have specified a halign value (%f) greater than 1", cmdline_p->xalign); if (cmdline_p->yalign < 0) pm_error("You have specified a negative halign value (%f)", cmdline_p->yalign); if (cmdline_p->yalign > 1) pm_error("You have specified a valign value (%f) greater than 1", cmdline_p->yalign); /* get optional input filename */ if (argc-1 > 1) pm_error("This program takes at most 1 parameter. You specified %d", argc-1); else if (argc-1 == 1) cmdline_p->input_filespec = argv[1]; else cmdline_p->input_filespec = "-"; } static void parse_command_line_old(int argc, char ** argv, struct cmdline_info * const cmdline_p) { /* This syntax was abandonned in February 2002. */ pm_message("Warning: old style options are deprecated!"); cmdline_p->xsize = cmdline_p->ysize = 0; cmdline_p->lpad = cmdline_p->rpad = cmdline_p->tpad = cmdline_p->bpad = 0; cmdline_p->xalign = cmdline_p->yalign = 0.5; cmdline_p->white = cmdline_p->verbose = FALSE; while (argc >= 2 && argv[1][0] == '-') { if (strcmp(argv[1]+1,"black") == 0) cmdline_p->white = FALSE; else if (strcmp(argv[1]+1,"white") == 0) cmdline_p->white = TRUE; else switch (argv[1][1]) { case 'l': if (atoi(argv[1]+2) < 0) pm_error("left border too small"); else cmdline_p->lpad = atoi(argv[1]+2); break; case 'r': if (atoi(argv[1]+2) < 0) pm_error("right border too small"); else cmdline_p->rpad = atoi(argv[1]+2); break; case 'b': if (atoi(argv[1]+2) < 0) pm_error("bottom border too small"); else cmdline_p->bpad = atoi(argv[1]+2); break; case 't': if (atoi(argv[1]+2) < 0) pm_error("top border too small"); else cmdline_p->tpad = atoi(argv[1]+2); break; default: pm_usage("[-white|-black] [-l#] [-r#] [-t#] [-b#] [pnmfile]"); } argc--, argv++; } if (argc > 2) pm_usage("[-white|-black] [-l#] [-r#] [-t#] [-b#] [pnmfile]"); if (argc == 2) cmdline_p->input_filespec = argv[1]; else cmdline_p->input_filespec = "-"; } int main(int argc, char ** argv) { struct cmdline_info cmdline; FILE *ifP; xel *xelrow, *bgrow, background; xelval maxval; int rows, cols, newcols, row, col, format; bool depr_cmd; /* use deprecated commandline interface */ pnm_init( &argc, argv ); /* detect deprecated options */ depr_cmd = FALSE; /* initial assumption */ if (argc > 1 && argv[1][0] == '-') { if (argv[1][1] == 't' || argv[1][1] == 'b' || argv[1][1] == 'l' || argv[1][1] == 'r') { 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') { if (argv[2][2] >= '0' && argv[2][2] <= '9') depr_cmd = TRUE; } } if (depr_cmd) parse_command_line_old(argc, argv, &cmdline); else parse_command_line(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 (cols == 0 || rows == 0) { pm_message("empty bitmap"); cmdline.lpad = cmdline.rpad = cmdline.tpad = cmdline.bpad = 0; } if (cmdline.verbose) pm_message("image WxH = %dx%d", cols, rows); if (cmdline.xsize > 0) { if (cmdline.xsize < cols) { cmdline.lpad = cmdline.rpad = 0; } else { cmdline.lpad = (float)(cmdline.xsize - cols) * cmdline.xalign; cmdline.rpad = cmdline.xsize - cols - cmdline.lpad; if (cmdline.verbose) pm_message("calculated hpad: %d - %d - %d", cmdline.lpad, cols, cmdline.rpad); } } if (cmdline.ysize > 0) { if (cmdline.ysize < rows) { cmdline.bpad = cmdline.tpad = 0; } else { cmdline.bpad = (float)(cmdline.ysize - rows) * cmdline.yalign; cmdline.tpad = cmdline.ysize - rows - cmdline.bpad; if (cmdline.verbose) pm_message("calculated vpad: %d - %d - %d", cmdline.bpad, rows, cmdline.tpad); } } newcols = cols + cmdline.lpad + cmdline.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 + cmdline.tpad + cmdline.bpad, maxval, format, 0); for (row = 0; row < cmdline.tpad; row++) pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0); for (row = 0; row < rows; row++) { pnm_readpnmrow(ifP, &xelrow[cmdline.lpad], cols, maxval, format); pnm_writepnmrow(stdout, xelrow, newcols, maxval, format, 0); } for (row = 0; row < cmdline.bpad; row++) pnm_writepnmrow(stdout, bgrow, newcols, maxval, format, 0); pnm_freerow(xelrow); pnm_freerow(bgrow); pm_close(ifP); exit(0); }