diff options
Diffstat (limited to 'editor/pnmshear.c')
-rw-r--r-- | editor/pnmshear.c | 170 |
1 files changed, 105 insertions, 65 deletions
diff --git a/editor/pnmshear.c b/editor/pnmshear.c index ae104db9..359df299 100644 --- a/editor/pnmshear.c +++ b/editor/pnmshear.c @@ -12,9 +12,12 @@ #define _XOPEN_SOURCE /* get M_PI in math.h */ +#include <assert.h> #include <math.h> #include <string.h> +#include "pm_c_util.h" +#include "ppm.h" #include "pnm.h" #include "shhopt.h" @@ -28,26 +31,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 +80,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, @@ -81,35 +97,40 @@ makeNewXel(xel * const outputXelP, xel const curXel, xel const prevXel, The format of the pixel is 'format'. -----------------------------------------------------------------------------*/ - switch ( PNM_FORMAT_TYPE(format) ) { + 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 +143,68 @@ 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 = pnm_parsecolorxel(backgroundColorName, maxval, format); + } 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,57 +214,55 @@ 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 ); - - for ( row = 0; row < rows; ++row ) { + pnm_writepnminit(stdout, newcols, rows, newmaxval, newformat, 0); + newxelrow = pnm_allocrow(newcols); + + for (row = 0; row < rows; ++row) { double shearCols; - pnm_readpnmrow( ifp, xelrow, cols, newmaxval, format ); + pnm_readpnmrow(ifP, xelrow, cols, newmaxval, format); - if ( row == 0 ) - bgxel = pnm_backgroundxelrow( xelrow, cols, newmaxval, format ); + if (row == 0) + bgxel = backgroundColor(cmdline.background, + 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; } - |