/* pbmtopgm.c - convert PBM to PGM by totalling pixels over sample area * AJCD 12/12/90 */ #include #include #include "pm_c_util.h" #include "nstring.h" #include "pgm.h" struct CmdlineInfo { unsigned int convCols; unsigned int convRows; const char * inputFileName; }; static void parseCommandLine(int const argc, const char ** const argv, struct CmdlineInfo * const cmdlineP) { const char * error; /* error message from pm_string_to_uint */ if (argc-1 < 2) pm_error("Insufficient arguments (%d). Need width and height " "of convolution kernel, in pixels", argc-1); else { pm_string_to_uint(argv[1], &cmdlineP->convCols, &error); if (error) pm_error("Invalid convolution kernel width argument. %s", error); pm_string_to_uint(argv[2], &cmdlineP->convRows, &error); if (error) pm_error("Invalid convolution kernel height argument. %s", error); if (cmdlineP->convCols < 1 || cmdlineP->convRows < 1) pm_error("convolution kernel width and height must be > 0"); if (argc-1 >= 3) cmdlineP->inputFileName = argv[3]; else { cmdlineP->inputFileName = "-"; if (argc-1 > 3) pm_error("Too many arguments (%d). The most possible are " "convolution kernel width and height " "and input file name", argc-1); } } } int main(int argc, const char ** argv) { struct CmdlineInfo cmdline; gray * outrow; gray maxval; unsigned int right, left, down, up; bit ** inbits; int rows, cols; FILE * ifP; unsigned int row; pm_proginit(&argc, argv); parseCommandLine(argc, argv, &cmdline); ifP = pm_openr(cmdline.inputFileName); inbits = pbm_readpbm(ifP, &cols, &rows); if (cmdline.convCols > cols) pm_error("You specified a convolution kernel width (%u columns) " "which is greater than the image width (%u columns)", cmdline.convCols, cols); if (cmdline.convRows > rows) pm_error("You specified a convolution kernel height (%u rows) " "which is greater than the image height (%u rows)", cmdline.convRows, rows); left = cmdline.convCols / 2; right = cmdline.convCols - left; up = cmdline.convRows / 2; down = cmdline.convRows - up; outrow = pgm_allocrow(cols) ; maxval = MIN(PGM_OVERALLMAXVAL, cmdline.convCols * cmdline.convRows); pgm_writepgminit(stdout, cols, rows, maxval, 0) ; for (row = 0; row < rows; ++row) { unsigned int const t = (row > up) ? (row - up) : 0; unsigned int const b = (row + down < rows) ? (row + down) : rows; unsigned int const actualConvRows = cmdline.convRows - (t - row + up) - (row + down - b); unsigned int col; for (col = 0; col < cols; ++col) { unsigned int const l = (col > left) ? (col - left) : 0; unsigned int const r = (col + right < cols) ? (col + right) : cols; unsigned int const actualConvCols = cmdline.convCols - (l - col + left) - (col + right - r); unsigned int value; unsigned int x; for (x = l, value = 0; x < r; ++x) { unsigned int y; for (y = t; y < b; ++y) if (inbits[y][x] == PBM_WHITE) ++value; } { unsigned int const convKernelArea = actualConvRows * actualConvCols; outrow[col] = (gray) (((double) value/convKernelArea)*maxval); } } pgm_writepgmrow(stdout, outrow, cols, maxval, 0) ; } pbm_freearray(inbits, rows); pm_close(ifP); return 0; }