From c9df14757a83c953deec8b55dbeb964148a524bd Mon Sep 17 00:00:00 2001 From: giraffedata Date: Mon, 27 Nov 2006 16:48:30 +0000 Subject: Add -background, -noantialias to Pnmshear git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@151 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- editor/pnmshear.c | 181 +++++++++++++++++++++++++++++++++++------------------- 1 file changed, 118 insertions(+), 63 deletions(-) (limited to 'editor/pnmshear.c') diff --git a/editor/pnmshear.c b/editor/pnmshear.c index 1b2d36a8..7bf983cc 100644 --- a/editor/pnmshear.c +++ b/editor/pnmshear.c @@ -28,26 +28,34 @@ struct cmdline_info { const char * input_filespec; /* Filespec of input file */ double angle; /* requested shear angle, in radians */ unsigned int noantialias; /* -noantialias option */ + const char * background; /* NULL if none */ }; static void -parse_command_line(int argc, char ** argv, - struct cmdline_info *cmdlineP) { +parseCommandLine(int argc, char ** argv, + struct cmdline_info *cmdlineP) { optStruct3 opt; unsigned int option_def_index = 0; optEntry *option_def = malloc(100*sizeof(optEntry)); + unsigned int backgroundSpec; + OPTENT3(0, "noantialias", OPT_FLAG, NULL, &cmdlineP->noantialias, 0); + OPTENT3(0, "background", OPT_STRING, &cmdlineP->background, + &backgroundSpec, 0); opt.opt_table = option_def; opt.short_allowed = FALSE; opt.allowNegNum = TRUE; optParseOptions3(&argc, argv, opt, sizeof(opt), 0); - + + if (!backgroundSpec) + cmdlineP->background = NULL; + if (argc-1 < 1) pm_error("Need an argument: the shear angle.\n"); else { @@ -69,9 +77,14 @@ parse_command_line(int argc, char ** argv, } + static void -makeNewXel(xel * const outputXelP, xel const curXel, xel const prevXel, - double const fracnew0, double const omfracnew0, int const format) { +makeNewXel(xel * const outputXelP, + xel const curXel, + xel const prevXel, + double const fracnew0, + double const omfracnew0, + int const format) { /*---------------------------------------------------------------------------- Create an output xel as *outputXel, which is part curXel and part prevXel, the part given by the fractions omfracnew0 and fracnew0, @@ -83,33 +96,38 @@ makeNewXel(xel * const outputXelP, xel const curXel, xel const prevXel, switch ( PNM_FORMAT_TYPE(format) ) { case PPM_TYPE: - PPM_ASSIGN( *outputXelP, - ( fracnew0 * PPM_GETR(prevXel) - + omfracnew0 * PPM_GETR(curXel) - + HALFSCALE ) / SCALE, - ( fracnew0 * PPM_GETG(prevXel) - + omfracnew0 * PPM_GETG(curXel) - + HALFSCALE ) / SCALE, - ( fracnew0 * PPM_GETB(prevXel) - + omfracnew0 * PPM_GETB(curXel) - + HALFSCALE ) / SCALE ); + PPM_ASSIGN(*outputXelP, + (fracnew0 * PPM_GETR(prevXel) + + omfracnew0 * PPM_GETR(curXel) + + HALFSCALE) / SCALE, + (fracnew0 * PPM_GETG(prevXel) + + omfracnew0 * PPM_GETG(curXel) + + HALFSCALE) / SCALE, + (fracnew0 * PPM_GETB(prevXel) + + omfracnew0 * PPM_GETB(curXel) + + HALFSCALE) / SCALE ); break; default: - PNM_ASSIGN1( *outputXelP, - ( fracnew0 * PNM_GET1(prevXel) - + omfracnew0 * PNM_GET1(curXel) - + HALFSCALE ) / SCALE ); + PNM_ASSIGN1(*outputXelP, + (fracnew0 * PNM_GET1(prevXel) + + omfracnew0 * PNM_GET1(curXel) + + HALFSCALE) / SCALE ); break; } } + static void -shear_row(xel * const xelrow, int const cols, - xel * const newxelrow, int const newcols, - double const shearCols, - int const format, xel const bgxel, bool const antialias) { +shearRow(xel * const xelrow, + unsigned int const cols, + xel * const newxelrow, + unsigned int const newcols, + double const shearCols, + int const format, + xel const bgxel, + bool const antialias) { /*---------------------------------------------------------------------------- Shear the row 'xelrow' by 'shearCols' columns, and return the result as 'newxelrow'. They are 'cols' and 'newcols' columns wide, respectively. @@ -122,47 +140,86 @@ shear_row(xel * const xelrow, int const cols, The format of the input xels (which implies something about the output xels too) is 'format'. -----------------------------------------------------------------------------*/ - int const intShearCols = (int) shearCols; + unsigned int const intShearCols = (unsigned int) shearCols; + + assert(shearCols >= 0.0); - if ( antialias ) { - const long fracnew0 = ( shearCols - intShearCols ) * SCALE; + if (antialias) { + const long fracnew0 = (shearCols - intShearCols) * SCALE; const long omfracnew0 = SCALE - fracnew0; - int col; + unsigned int col; xel prevXel; - for ( col = 0; col < newcols; ++col ) + for (col = 0; col < newcols; ++col) newxelrow[col] = bgxel; prevXel = bgxel; - for ( col = 0; col < cols; ++col){ + for (col = 0; col < cols; ++col) { makeNewXel(&newxelrow[intShearCols + col], xelrow[col], prevXel, fracnew0, omfracnew0, format); prevXel = xelrow[col]; } - if ( fracnew0 > 0 ) + if (fracnew0 > 0) /* Need to add a column for what's left over */ makeNewXel(&newxelrow[intShearCols + cols], bgxel, prevXel, fracnew0, omfracnew0, format); } else { - int col; - for ( col = 0; col < intShearCols; ++col ) + unsigned int col; + for (col = 0; col < intShearCols; ++col) newxelrow[col] = bgxel; - for ( col = 0; col < cols; ++col ) + for (col = 0; col < cols; ++col) newxelrow[intShearCols+col] = xelrow[col]; - for ( col = intShearCols + cols; col < newcols; ++col ) + for (col = intShearCols + cols; col < newcols; ++col) newxelrow[col] = bgxel; } } +static xel +backgroundColor(const char * const backgroundColorName, + xel * const topRow, + int const cols, + xelval const maxval, + int const format) { + + xel retval; + + if (backgroundColorName) { + retval = ppm_parsecolor(backgroundColorName, maxval); + + switch(PNM_FORMAT_TYPE(format)) { + case PGM_TYPE: + if (!PPM_ISGRAY(retval)) + pm_error("Image is PGM (grayscale), " + "but you specified a non-gray " + "background color '%s'", backgroundColorName); + break; + case PBM_TYPE: + if (!PNM_EQUAL(retval, pnm_whitexel(maxval, format)) && + !PNM_EQUAL(retval, pnm_blackxel(maxval, format))) + pm_error ("Image is PBM (black and white), " + "but you specified '%s', which is neither black " + "nor white, as background color", + backgroundColorName); + break; + } + } else + retval = pnm_backgroundxelrow(topRow, cols, maxval, format); + + return retval; +} + + + int main(int argc, char * argv[]) { - FILE* ifp; - xel* xelrow; - xel* newxelrow; + + FILE * ifP; + xel * xelrow; + xel * newxelrow; xel bgxel; int rows, cols, format; int newformat, newcols; @@ -172,56 +229,54 @@ main(int argc, char * argv[]) { struct cmdline_info cmdline; - pnm_init( &argc, argv ); + pnm_init(&argc, argv); - parse_command_line( argc, argv, &cmdline ); + parseCommandLine(argc, argv, &cmdline); - ifp = pm_openr( cmdline.input_filespec ); + ifP = pm_openr(cmdline.input_filespec); - pnm_readpnminit( ifp, &cols, &rows, &maxval, &format ); - xelrow = pnm_allocrow( cols ); + pnm_readpnminit(ifP, &cols, &rows, &maxval, &format); + xelrow = pnm_allocrow(cols); /* Promote PBM files to PGM. */ - if ( !cmdline.noantialias && PNM_FORMAT_TYPE(format) == PBM_TYPE ) { + if (!cmdline.noantialias && PNM_FORMAT_TYPE(format) == PBM_TYPE) { newformat = PGM_TYPE; newmaxval = PGM_MAXMAXVAL; - pm_message( "promoting from PBM to PGM - " - "use -noantialias to avoid this" ); + pm_message("promoting from PBM to PGM - " + "use -noantialias to avoid this"); } else { newformat = format; newmaxval = maxval; } - shearfac = tan( cmdline.angle ); - if ( shearfac < 0.0 ) - shearfac = -shearfac; + shearfac = fabs(tan(cmdline.angle)); newcols = rows * shearfac + cols + 0.999999; - pnm_writepnminit( stdout, newcols, rows, newmaxval, newformat, 0 ); - newxelrow = pnm_allocrow( newcols ); - - bgxel = pnm_backgroundxelrow( xelrow, cols, newmaxval, format ); + pnm_writepnminit(stdout, newcols, rows, newmaxval, newformat, 0); + newxelrow = pnm_allocrow(newcols); + + bgxel = backgroundColor(cmdline.background, xelrow, cols, newmaxval, + format); - for ( row = 0; row < rows; ++row ) { + for (row = 0; row < rows; ++row) { double shearCols; - pnm_readpnmrow( ifp, xelrow, cols, newmaxval, format ); + pnm_readpnmrow(ifP, xelrow, cols, newmaxval, format); - if ( cmdline.angle > 0.0 ) + if (cmdline.angle > 0.0) shearCols = row * shearfac; else - shearCols = ( rows - row ) * shearfac; + shearCols = (rows - row) * shearfac; - shear_row(xelrow, cols, newxelrow, newcols, + shearRow(xelrow, cols, newxelrow, newcols, shearCols, format, bgxel, !cmdline.noantialias); - pnm_writepnmrow( stdout, newxelrow, newcols, newmaxval, newformat, 0 ); + pnm_writepnmrow(stdout, newxelrow, newcols, newmaxval, newformat, 0); } + + pm_close(ifP); + pm_close(stdout); - pm_close( ifp ); - pm_close( stdout ); - - exit( 0 ); + return 0; } - -- cgit 1.4.1