about summary refs log tree commit diff
path: root/editor/pnmshear.c
diff options
context:
space:
mode:
authorgiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-11-27 16:48:30 +0000
committergiraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8>2006-11-27 16:48:30 +0000
commitc9df14757a83c953deec8b55dbeb964148a524bd (patch)
treeceb7b75c620857f1bbe6e4b23ec23ed2333e8b8d /editor/pnmshear.c
parent49a61bec1215b4ef9e12f305aec84cb0ee2e2198 (diff)
downloadnetpbm-mirror-c9df14757a83c953deec8b55dbeb964148a524bd.tar.gz
netpbm-mirror-c9df14757a83c953deec8b55dbeb964148a524bd.tar.xz
netpbm-mirror-c9df14757a83c953deec8b55dbeb964148a524bd.zip
Add -background, -noantialias to Pnmshear
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@151 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor/pnmshear.c')
-rw-r--r--editor/pnmshear.c181
1 files changed, 118 insertions, 63 deletions
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;
 }
-