home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
309.lha
/
PBM_PLUS
/
ppm
/
ppmscale.c
< prev
next >
Wrap
C/C++ Source or Header
|
1980-12-04
|
8KB
|
327 lines
/* ppmscale.c - read a portable pixmap and scale it
**
** Copyright (C) 1989 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 <stdio.h>
#ifdef SYSV
#include <string.h>
#else SYSV
#include <strings.h>
#endif SYSV
#include "ppm.h"
#define SCALE 4096
#define HALFSCALE 2048
#define max(a,b) ((a) > (b) ? (a) : (b))
main( argc, argv )
int argc;
char *argv[];
{
FILE *ifd;
pixel **pixels, **temppixels, *newpixelrow;
register pixel *pP, *npP;
int argn, specxscale, specyscale, specxsize, specysize;
int rows, cols, newrows, newcols;
register int row, col, newrow, neednew;
pixval maxval;
float xscale, yscale;
long sxscale, syscale;
register long fractofill, fracleft;
char *usage = "<s> [ppmfile]\n -xsize|width|-ysize|-height <s> [ppmfile]\n -xscale|-yscale <s> [ppmfile]\n -xscale|-xsize|-width <s> -yscale|-ysize|-height <s> [ppmfile]";
pm_progname = argv[0];
argn = 1;
specxscale = specyscale = specxsize = specysize = 0;
while ( argn + 1 < argc && argv[argn][0] == '-' )
{
if ( strncmp(argv[argn],"-xscale",max(strlen(argv[argn]),4)) == 0 )
{
if ( specxsize )
pm_error(
"only one of -xsize/-width and -xscale may be specified",
0,0,0,0,0 );
if ( sscanf( argv[argn+1], "%g", &xscale ) != 1 )
pm_usage( usage );
if ( xscale <= 0.0 )
pm_error( "x scale must be greater than 0", 0,0,0,0,0 );
specxscale = 1;
}
else if ( strncmp(argv[argn],"-yscale",max(strlen(argv[argn]),4)) == 0 )
{
if ( specysize )
pm_error(
"only one of -ysize/-height and -yscale may be specified",
0,0,0,0,0 );
if ( sscanf( argv[argn+1], "%g", &yscale ) != 1 )
pm_usage( usage );
if ( yscale <= 0.0 )
pm_error( "y scale must be greater than 0", 0,0,0,0,0 );
specyscale = 1;
}
else if ( strncmp(argv[argn],"-xsize",max(strlen(argv[argn]),4)) == 0 ||
strncmp(argv[argn],"-width",max(strlen(argv[argn]),2)) == 0 )
{
if ( specxscale )
pm_error(
"only one of -xscale and -xsize/-width may be specified",
0,0,0,0,0 );
if ( sscanf( argv[argn+1], "%d", &newcols ) != 1 )
pm_usage( usage );
if ( newcols <= 0 )
pm_error( "new width must be greater than 0", 0,0,0,0,0 );
specxsize = 1;
}
else if ( strncmp(argv[argn],"-ysize",max(strlen(argv[argn]),4)) == 0 ||
strncmp(argv[argn],"-height",max(strlen(argv[argn]),2)) == 0 )
{
if ( specyscale )
pm_error(
"only one of -yscale and -ysize/-height may be specified",
0,0,0,0,0 );
if ( sscanf( argv[argn+1], "%d", &newrows ) != 1 )
pm_usage( usage );
if ( newrows <= 0 )
pm_error( "new height must be greater than 0", 0,0,0,0,0 );
specysize = 1;
}
else
pm_usage( usage );
argn += 2;
}
if ( ! ( specxscale || specyscale || specxsize || specysize ) )
{
/* No flags specified, so a single scale factor is required. */
if ( argn == argc )
pm_usage( usage );
if ( sscanf( argv[argn], "%g", &xscale ) != 1 )
pm_usage( usage );
if ( xscale <= 0.0 )
pm_error( "scale must be greater than 0", 0,0,0,0,0 );
argn++;
yscale = xscale;
specxscale = specyscale = 1;
}
/* Now get input file. */
if ( argn != argc )
{
ifd = pm_openr( argv[argn] );
argn++;
}
else
ifd = stdin;
if ( argn != argc )
pm_usage( usage );
ppm_pbmmaxval = 255; /* use larger value for better results */
pixels = ppm_readppm( ifd, &cols, &rows, &maxval );
pm_close( ifd );
/* Compute all sizes and scales. */
if ( specxsize )
xscale = (float) newcols / (float) cols;
else if ( specxscale )
newcols = cols * xscale + 0.999;
if ( specysize )
yscale = (float) newrows / (float) rows;
else if ( specyscale )
newrows = rows * yscale + 0.999;
else
if ( specxsize )
{
yscale = xscale;
newrows = rows * yscale + 0.999;
}
else
{
yscale = 1.0;
newrows = rows;
}
if ( ! ( specxsize || specxscale ) )
if ( specysize )
{
xscale = yscale;
newcols = cols * xscale + 0.999;
}
else
{
xscale = 1.0;
newcols = cols;
}
sxscale = xscale * SCALE;
syscale = yscale * SCALE;
/* First scale Y from pixels into temppixels. */
if ( newrows == rows ) /* shortcut Y scaling if possible */
temppixels = pixels;
else
{
temppixels = ppm_allocarray( cols, newrows );
for ( col = 0; col < cols; col++ )
{
register long r, g, b;
newrow = 0;
npP = &(temppixels[newrow][col]);
fractofill = SCALE;
r = g = b = HALFSCALE;
neednew = 0;
for ( row = 0; row < rows; row++ )
{
pP = &(pixels[row][col]);
fracleft = syscale;
while ( fracleft >= fractofill )
{
if ( neednew )
{
newrow++;
npP = &(temppixels[newrow][col]);
r = g = b = HALFSCALE;
neednew = 0;
}
r += fractofill * PPM_GETR( *pP );
g += fractofill * PPM_GETG( *pP );
b += fractofill * PPM_GETB( *pP );
r /= SCALE;
g /= SCALE;
b /= SCALE;
if ( r > maxval ) r = maxval;
if ( g > maxval ) g = maxval;
if ( b > maxval ) b = maxval;
PPM_ASSIGN( *npP, r, g, b );
fracleft -= fractofill;
fractofill = SCALE;
neednew = 1;
}
if ( fracleft > 0 )
{
if ( neednew )
{
newrow++;
npP = &(temppixels[newrow][col]);
r = g = b = HALFSCALE;
neednew = 0;
}
r += fracleft * PPM_GETR( *pP );
g += fracleft * PPM_GETG( *pP );
b += fracleft * PPM_GETB( *pP );
fractofill -= fracleft;
}
}
if ( fractofill > 0 )
{
pP = &(pixels[rows-1][col]);
r += fractofill * PPM_GETR( *pP );
g += fractofill * PPM_GETG( *pP );
b += fractofill * PPM_GETB( *pP );
}
if ( ! neednew )
{
r /= SCALE;
g /= SCALE;
b /= SCALE;
if ( r > maxval ) r = maxval;
if ( g > maxval ) g = maxval;
if ( b > maxval ) b = maxval;
PPM_ASSIGN( *npP, r, g, b );
}
}
ppm_freearray( pixels, rows );
}
/* Now scale X and write it out. */
if ( newcols == cols ) /* shortcut X scaling if possible */
ppm_writeppm( stdout, temppixels, newcols, newrows, maxval );
else
{
ppm_writeppminit( stdout, newcols, newrows, maxval );
newpixelrow = ppm_allocrow( newcols );
for ( row = 0; row < newrows; row++ )
{
register long r, g, b;
npP = newpixelrow;
fractofill = SCALE;
r = g = b = HALFSCALE;
neednew = 0;
for ( col = 0, pP = temppixels[row]; col < cols; col++, pP++ )
{
fracleft = sxscale;
while ( fracleft >= fractofill )
{
if ( neednew )
{
npP++;
r = g = b = HALFSCALE;
neednew = 0;
}
r += fractofill * PPM_GETR( *pP );
g += fractofill * PPM_GETG( *pP );
b += fractofill * PPM_GETB( *pP );
r /= SCALE;
g /= SCALE;
b /= SCALE;
if ( r > maxval ) r = maxval;
if ( g > maxval ) g = maxval;
if ( b > maxval ) b = maxval;
PPM_ASSIGN( *npP, r, g, b );
fracleft -= fractofill;
fractofill = SCALE;
neednew = 1;
}
if ( fracleft > 0 )
{
if ( neednew )
{
npP++;
r = g = b = HALFSCALE;
neednew = 0;
}
r += fracleft * PPM_GETR( *pP );
g += fracleft * PPM_GETG( *pP );
b += fracleft * PPM_GETB( *pP );
fractofill -= fracleft;
}
}
if ( fractofill > 0 )
{
pP--;
r += fractofill * PPM_GETR( *pP );
g += fractofill * PPM_GETG( *pP );
b += fractofill * PPM_GETB( *pP );
}
if ( ! neednew )
{
r /= SCALE;
g /= SCALE;
b /= SCALE;
if ( r > maxval ) r = maxval;
if ( g > maxval ) g = maxval;
if ( b > maxval ) b = maxval;
PPM_ASSIGN( *npP, r, g, b );
}
ppm_writeppmrow( stdout, newpixelrow, newcols, maxval );
}
}
exit( 0 );
}