This is pnmshear.c in view mode; [Download] [Up]
/* pnmshear.c - read a portable anymap and shear it by some angle ** ** Copyright (C) 1989, 1991 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include <math.h> #include "pnm.h" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif /*M_PI*/ #define SCALE 4096 #define HALFSCALE 2048 int main( argc, argv ) int argc; char* argv[]; { FILE* ifp; xel* xelrow; register xel* newxelrow; register xel* xP; register xel* nxP; xel bgxel, prevxel; int argn, rows, cols, format, newformat, newcols, row, col; xelval maxval; int antialias; float fangle, shearfac, new0; int intnew0; register long fracnew0, omfracnew0; char* usage = "[-noantialias] <angle> [pnmfile]"; pnm_init( &argc, argv ); argn = 1; antialias = 1; if ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' && ( argv[argn][1] < '0' || argv[argn][1] > '9' ) ) { if ( pm_keymatch( argv[argn], "-antialias", 2 ) ) antialias = 1; else if ( pm_keymatch( argv[argn], "-noantialias", 2 ) ) antialias = 0; else pm_usage( usage ); ++argn; } if ( argn == argc ) pm_usage( usage ); if ( sscanf( argv[argn], "%f", &fangle ) != 1 ) pm_usage( usage ); ++argn; if ( fangle <= -90.0 || fangle >= 90.0 ) pm_error( "angle must be between -90 and 90" ); fangle = fangle * M_PI / 180.0; /* convert to radians */ shearfac = tan( fangle ); if ( shearfac < 0.0 ) shearfac = -shearfac; if ( argn != argc ) { ifp = pm_openr( argv[argn] ); ++argn; } else ifp = stdin; if ( argn != argc ) pm_usage( usage ); pnm_pbmmaxval = PNM_MAXMAXVAL; /* use larger value for better results */ pnm_readpnminit( ifp, &cols, &rows, &maxval, &format ); xelrow = pnm_allocrow( cols ); /* Promote PBM files to PGM. */ if ( antialias && PNM_FORMAT_TYPE(format) == PBM_TYPE ) { newformat = PGM_TYPE; pm_message( "promoting from PBM to PGM - use -noantialias to avoid this" ); } else newformat = format; newcols = rows * shearfac + cols + 0.999999; pnm_writepnminit( stdout, newcols, rows, maxval, newformat, 0 ); newxelrow = pnm_allocrow( newcols ); bgxel = pnm_backgroundxelrow( xelrow, cols, maxval, format ); for ( row = 0; row < rows; ++row ) { pnm_readpnmrow( ifp, xelrow, cols, maxval, format ); if ( fangle > 0.0 ) new0 = row * shearfac; else new0 = ( rows - row ) * shearfac; intnew0 = (int) new0; if ( antialias ) { fracnew0 = ( new0 - intnew0 ) * SCALE; omfracnew0 = SCALE - fracnew0; for ( col = 0, nxP = newxelrow; col < newcols; ++col, ++nxP ) *nxP = bgxel; prevxel = bgxel; for ( col = 0, nxP = &(newxelrow[intnew0]), xP = xelrow; col < cols; ++col, ++nxP, ++xP ) { switch ( PNM_FORMAT_TYPE(format) ) { case PPM_TYPE: PPM_ASSIGN( *nxP, ( fracnew0 * PPM_GETR(prevxel) + omfracnew0 * PPM_GETR(*xP) + HALFSCALE ) / SCALE, ( fracnew0 * PPM_GETG(prevxel) + omfracnew0 * PPM_GETG(*xP) + HALFSCALE ) / SCALE, ( fracnew0 * PPM_GETB(prevxel) + omfracnew0 * PPM_GETB(*xP) + HALFSCALE ) / SCALE ); break; default: PNM_ASSIGN1( *nxP, ( fracnew0 * PNM_GET1(prevxel) + omfracnew0 * PNM_GET1(*xP) + HALFSCALE ) / SCALE ); break; } prevxel = *xP; } if ( fracnew0 > 0 ) { nxP = &(newxelrow[intnew0 + cols]); switch ( PNM_FORMAT_TYPE(format) ) { case PPM_TYPE: PPM_ASSIGN( *nxP, ( fracnew0 * PPM_GETR(prevxel) + omfracnew0 * PPM_GETR(bgxel) + HALFSCALE ) / SCALE, ( fracnew0 * PPM_GETG(prevxel) + omfracnew0 * PPM_GETG(bgxel) + HALFSCALE ) / SCALE, ( fracnew0 * PPM_GETB(prevxel) + omfracnew0 * PPM_GETB(bgxel) + HALFSCALE ) / SCALE ); break; default: PNM_ASSIGN1( *nxP, ( fracnew0 * PNM_GET1(prevxel) + omfracnew0 * PNM_GET1(bgxel) + HALFSCALE ) / SCALE ); break; } } } else { for ( col = 0, nxP = newxelrow; col < intnew0; ++col, ++nxP ) *nxP = bgxel; for ( col = 0, xP = xelrow; col < cols; ++col, ++nxP, ++xP ) *nxP = *xP; for ( col = intnew0 + cols; col < newcols; ++col, ++nxP ) *nxP = bgxel; } pnm_writepnmrow( stdout, newxelrow, newcols, maxval, newformat, 0 ); } pm_close( ifp ); pm_close( stdout ); exit( 0 ); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.