diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /editor/pbmreduce.c | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'editor/pbmreduce.c')
-rw-r--r-- | editor/pbmreduce.c | 208 |
1 files changed, 208 insertions, 0 deletions
diff --git a/editor/pbmreduce.c b/editor/pbmreduce.c new file mode 100644 index 00000000..15ec2a1b --- /dev/null +++ b/editor/pbmreduce.c @@ -0,0 +1,208 @@ +/* pbmreduce.c - read a portable bitmap and reduce it N times +** +** 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 "pbm.h" +#include "mallocvar.h" + +int +main( argc, argv ) + int argc; + char* argv[]; + { + FILE* ifp; + register bit** bitslice; + register bit* newbitrow; + register bit* nbP; + int argn, n, rows, cols, format, newrows, newcols; + int row, col, limitcol, subrow, subcol, count, direction; + const char* const usage = "[-floyd|-fs | -threshold] [-value <val>] N [pbmfile]"; + int halftone; +#define QT_FS 1 +#define QT_THRESH 2 +#define SCALE 1024 +#define HALFSCALE 512 + long threshval, sum; + long* thiserr; /* used for Floyd-Steinberg stuff */ + long* nexterr; /* used for Floyd-Steinberg stuff */ + long* temperr; + + + pbm_init( &argc, argv ); + + argn = 1; + halftone = QT_FS; + threshval = HALFSCALE; + + while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) + { + if ( pm_keymatch( argv[argn], "-fs", 2 ) || + pm_keymatch( argv[argn], "-floyd", 2 ) ) + halftone = QT_FS; + else if ( pm_keymatch( argv[argn], "-threshold", 2 ) ) + halftone = QT_THRESH; + else if ( pm_keymatch( argv[argn], "-value", 2 ) ) + { + float f; + + ++argn; + if ( argn == argc || sscanf( argv[argn], "%f", &f ) != 1 || + f < 0.0 || f > 1.0 ) + pm_usage( usage ); + threshval = f * SCALE; + } + else + pm_usage( usage ); + ++argn; + } + + if ( argn == argc ) + pm_usage( usage ); + if ( sscanf( argv[argn], "%d", &n ) != 1 ) + pm_usage( usage ); + if ( n < 2 ) + pm_error( "N must be greater than 1" ); + ++argn; + + if ( argn == argc ) + ifp = stdin; + else + { + ifp = pm_openr( argv[argn] ); + ++argn; + } + + if ( argn != argc ) + pm_usage( usage ); + + pbm_readpbminit( ifp, &cols, &rows, &format ); + bitslice = pbm_allocarray( cols, n ); + + newrows = rows / n; + newcols = cols / n; + pbm_writepbminit( stdout, newcols, newrows, 0 ); + newbitrow = pbm_allocrow( newcols ); + + if ( halftone == QT_FS ) { + /* Initialize Floyd-Steinberg. */ + MALLOCARRAY(thiserr, newcols + 2); + MALLOCARRAY(nexterr, newcols + 2); + if ( thiserr == NULL || nexterr == NULL ) + pm_error( "out of memory" ); + + srand( (int) ( time( 0 ) ^ getpid( ) ) ); + for ( col = 0; col < newcols + 2; ++col ) + thiserr[col] = ( rand( ) % SCALE - HALFSCALE ) / 4; + /* (random errors in [-SCALE/8 .. SCALE/8]) */ + } else { + /* These variables are meaningless in this case, and the values + should never be used. + */ + thiserr = NULL; + nexterr = NULL; + } + direction = 1; + + for ( row = 0; row < newrows; ++row ) + { + for ( subrow = 0; subrow < n; ++subrow ) + pbm_readpbmrow( ifp, bitslice[subrow], cols, format ); + + if ( halftone == QT_FS ) + for ( col = 0; col < newcols + 2; ++col ) + nexterr[col] = 0; + if ( direction ) + { + col = 0; + limitcol = newcols; + nbP = newbitrow; + } + else + { + col = newcols - 1; + limitcol = -1; + nbP = &(newbitrow[col]); + } + + do + { + sum = 0; + count = 0; + for ( subrow = 0; subrow < n; ++subrow ) + for ( subcol = 0; subcol < n; ++subcol ) + if ( row * n + subrow < rows && col * n + subcol < cols ) + { + count += 1; + if ( bitslice[subrow][col * n + subcol] == PBM_WHITE ) + sum += 1; + } + sum = ( sum * SCALE ) / count; + + if ( halftone == QT_FS ) + sum += thiserr[col + 1]; + + if ( sum >= threshval ) + { + *nbP = PBM_WHITE; + if ( halftone == QT_FS ) + sum = sum - threshval - HALFSCALE; + } + else + *nbP = PBM_BLACK; + + if ( halftone == QT_FS ) + { + if ( direction ) + { + thiserr[col + 2] += ( sum * 7 ) / 16; + nexterr[col ] += ( sum * 3 ) / 16; + nexterr[col + 1] += ( sum * 5 ) / 16; + nexterr[col + 2] += ( sum ) / 16; + } + else + { + thiserr[col ] += ( sum * 7 ) / 16; + nexterr[col + 2] += ( sum * 3 ) / 16; + nexterr[col + 1] += ( sum * 5 ) / 16; + nexterr[col ] += ( sum ) / 16; + } + } + if ( direction ) + { + ++col; + ++nbP; + } + else + { + --col; + --nbP; + } + } + while ( col != limitcol ); + + pbm_writepbmrow( stdout, newbitrow, newcols, 0 ); + + if ( halftone == QT_FS ) + { + temperr = thiserr; + thiserr = nexterr; + nexterr = temperr; + direction = ! direction; + } + } + + pm_close( ifp ); + pm_close( stdout ); + + exit( 0 ); + } + + |