diff options
Diffstat (limited to 'converter/pgm/lispmtopgm.c')
-rw-r--r-- | converter/pgm/lispmtopgm.c | 258 |
1 files changed, 136 insertions, 122 deletions
diff --git a/converter/pgm/lispmtopgm.c b/converter/pgm/lispmtopgm.c index 40dd3fb4..29f280f3 100644 --- a/converter/pgm/lispmtopgm.c +++ b/converter/pgm/lispmtopgm.c @@ -16,6 +16,8 @@ ** this doesn't matter if you're using only single plane images. */ +#include <assert.h> +#include <limits.h> #include <stdio.h> #include <string.h> @@ -24,149 +26,161 @@ #define LISPM_MAGIC "This is a BitMap file" -static void getinit ARGS(( FILE* file, short* colsP, short* rowsP, short* depthP, short* padrightP )); -static int depth_to_word_size ARGS(( int depth )); -static unsigned int getval ARGS(( FILE* file )); - -int -main( argc, argv ) - int argc; - char* argv[]; - { - FILE* ifp; - gray* grayrow; - register gray* gP; - short rows, cols, padright, row, col; - short depth; - int maxval; - pgm_init( &argc, argv ); - - if ( argc > 2 ) - pm_usage( "[lispmfile]" ); +static long item, bitmask; +static unsigned int bitsperitem, maxbitsperitem, bitshift; - if ( argc == 2 ) - ifp = pm_openr( argv[1] ); - else - ifp = stdin; - - getinit( ifp, &cols, &rows, &depth, &padright ); - maxval = 1 << depth; - - if ( maxval > PGM_OVERALLMAXVAL ) - pm_error( "depth (%d bits) is too large", depth); - - pgm_writepgminit( stdout, cols, rows, (gray) maxval, 0 ); - grayrow = pgm_allocrow( ( cols + 7 ) / 8 * 8 ); - - for ( row = 0; row < rows; ++row ) - { - for ( col = 0, gP = grayrow; col < cols; ++col, ++gP ) - *gP = getval( ifp ); - pgm_writepgmrow( stdout, grayrow, cols, (gray) maxval, 0 ); - } - pm_close( ifp ); - pm_close( stdout ); - exit( 0 ); +static unsigned int +wordSizeFmDepth(unsigned int const depth) { +/*---------------------------------------------------------------------------- + Lispm architecture specific - if a bitmap is written out with a depth of 5, + it really has a depth of 8, and is stored that way in the file. +-----------------------------------------------------------------------------*/ + if (depth==0 || depth==1) return 1; + else if (depth == 2) return 2; + else if (depth <= 4) return 4; + else if (depth <= 8) return 8; + else if (depth <= 16) return 16; + else if (depth <= 32) return 32; + else { + pm_error("depth was %u, which is not in the range 1-32.", depth); + assert(false); } +} + -static long item, bitmask; -static unsigned int bitsperitem, maxbitsperitem, bitshift; static void -getinit( file, colsP, rowsP, depthP, padrightP ) - FILE* file; - short* colsP; - short* rowsP; - short* padrightP; - short* depthP; - { - short cols_32; +getinit(FILE * const ifP, + unsigned int * const colsP, + unsigned int * const rowsP, + unsigned int * const depthP, + unsigned int * const padrightP) { + + short cols, rows, cols32; char magic[sizeof(LISPM_MAGIC)]; - int i; + unsigned int i; + + for (i = 0; i < sizeof(magic)-1; ++i) + magic[i] = getc(ifP); - for ( i = 0; i < sizeof(magic)-1; ++i ) - magic[i] = getc( file ); magic[i]='\0'; + if (!streq(LISPM_MAGIC, magic)) - pm_error( "bad id string in Lispm file" ); - - if ( pm_readlittleshort( file, colsP ) == -1 ) - pm_error( "EOF / read error" ); - if ( pm_readlittleshort( file, rowsP ) == -1 ) - pm_error( "EOF / read error" ); - if ( pm_readlittleshort( file, &cols_32 ) == -1 ) - pm_error( "EOF / read error" ); - *depthP = getc( file ); - - if ( *depthP == 0 ) - *depthP = 1; /* very old file */ - - *padrightP = ( ( *colsP + 31 ) / 32 ) * 32 - *colsP; - - if ( *colsP != (cols_32 - *padrightP) ) { -/* pm_message( "inconsistent input: Width and Width(mod32) fields don't agree" ); */ -/* *padrightP = cols_32 - *colsP; */ /* hmmmm.... */ - /* This is a dilemma. Usually the output is rounded up to mod32, but not always. - * For the Lispm code to not round up, the array size must be the same size as the - * portion being written - that is, the array itself must be an odd size, not just - * the selected portion. Since arrays that are odd sizes can't be handed to bitblt, - * such arrays are probably not image data - so punt on it for now. - * - * Also, the lispm code for saving bitmaps has a bug, in that if you are writing a - * bitmap which is not mod32 across, the file may be up to 7 bits too short! They - * round down instead of up. - * - * The code in 'pgmtolispm.c' always rounds up to mod32, which is totally reasonable. - */ - } - bitsperitem = 0; - maxbitsperitem = depth_to_word_size( *depthP ); - bitmask = ( 1 << maxbitsperitem ) - 1; /* for depth=3, mask=00000111 */ + pm_error("bad id string in Lispm file"); + + pm_readlittleshort(ifP, &cols); + pm_readlittleshort(ifP, &rows); + pm_readlittleshort(ifP, &cols32); + + *colsP = cols; + *rowsP = rows; + + *depthP = getc(ifP); + + if (*depthP == 0) + *depthP = 1; /* very old file */ - for ( i = 0; i < 9; ++i ) - getc( file ); /* discard bytes reserved for future use */ + assert(*colsP < UINT_MAX - 31); + + *padrightP = ROUNDUP(*colsP, 32) - *colsP; + +# if 0 + if (*colsP != (cols32 - *padrightP)) { + pm_message("inconsistent input: " + "Width and Width(mod32) fields don't agree" ); + *padrightP = cols32 - *colsP; /* hmmmm.... */ + + /* This is a dilemma. Usually the output is rounded up to mod32, but + not always. For the Lispm code to not round up, the array size + must be the same size as the portion being written - that is, the + array itself must be an odd size, not just the selected portion. + Since arrays that are odd sizes can't be handed to bitblt, such + arrays are probably not image data - so punt on it for now. + + Also, the lispm code for saving bitmaps has a bug, in that if you + are writing a bitmap which is not mod32 across, the file may be up + to 7 bits too short! They round down instead of up. + + The code in 'pgmtolispm.c' always rounds up to mod32, which is + totally reasonable. + */ } +#endif + bitsperitem = 0; + maxbitsperitem = wordSizeFmDepth(*depthP); + bitmask = (1 << maxbitsperitem) - 1; /* for depth=3, mask=00000111 */ -static int -depth_to_word_size (depth) - int depth; - /* Lispm architecture specific - if a bitmap is written */ - /* out with a depth of 5, it really has a depth of 8, and */ - /* is stored that way in the file. */ -{ - if (depth==0 || depth==1) return ( 1); - else if (depth == 2) return ( 2); - else if (depth <= 4) return ( 4); - else if (depth <= 8) return ( 8); - else if (depth <= 16) return (16); - else if (depth <= 32) return (32); - else { - pm_error( "depth was %d, which is not in the range 1-32.", depth ); - /* Should never reach here */ - return(-1); - } + for (i = 0; i < 9; ++i) + getc(ifP); /* discard bytes reserved for future use */ } static unsigned int -getval( file ) - FILE* file; - { +getval(FILE * const ifP) { + unsigned int b; - if ( bitsperitem == 0 ) - { - if ( pm_readlittlelong( file, &item ) == -1 ) - pm_error( "EOF / read error" ); - bitsperitem = 32; - bitshift = 0; - item = ~item; - } - b = ( ( item >> bitshift ) & bitmask ); + if (bitsperitem == 0) { + pm_readlittlelong(ifP, &item); + bitsperitem = 32; + bitshift = 0; + item = ~item; + } + b = ((item >> bitshift ) & bitmask); bitsperitem = bitsperitem - maxbitsperitem; - bitshift = bitshift + maxbitsperitem; + bitshift = bitshift + maxbitsperitem; return b; +} + + + +int +main(int argc, const char ** argv) { + + FILE * ifP; + gray * grayrow; + unsigned int rows, cols, depth, padright; + unsigned int row; + gray maxval; + + + pm_proginit(&argc, argv); + + if (argc-1 > 1) + pm_error("Too many arguments. The only possible argument is the " + "input file name"); + + if (argc-1 == 1) + ifP = pm_openr(argv[1]); + else + ifP = stdin; + + getinit(ifP, &cols, &rows, &depth, &padright); + + if (depth > 16) + pm_error("Invalid depth (%u bits). Maximum is 15", depth); + + maxval = (1 << depth); + + pgm_writepgminit(stdout, cols, rows, maxval, 0); + + grayrow = pgm_allocrow(ROUNDUP(cols, 8)); + + for (row = 0; row < rows; ++row) { + unsigned int col; + + for (col = 0; col < cols; ++col) + grayrow[col] = getval(ifP); + + pgm_writepgmrow(stdout, grayrow, cols, maxval, 0); } + pm_close(ifP); + pm_close(stdout); + exit(0); +} + + + |