about summary refs log tree commit diff
path: root/editor/pnmshear.c
diff options
context:
space:
mode:
Diffstat (limited to 'editor/pnmshear.c')
-rw-r--r--editor/pnmshear.c170
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;
 }
-