From 3b85c09e19ebdd0f54e49d1626f0bef0edd8ec5d Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 23 Oct 2010 18:56:40 +0000 Subject: Use packed bits, work with 32 bit items, work with Depth=8 git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1341 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/pbm/icontopbm.c | 228 ++++++++++++++++++++++++---------------------- 1 file changed, 120 insertions(+), 108 deletions(-) diff --git a/converter/pbm/icontopbm.c b/converter/pbm/icontopbm.c index a0d1bd2b..bad47c24 100644 --- a/converter/pbm/icontopbm.c +++ b/converter/pbm/icontopbm.c @@ -10,150 +10,162 @@ ** implied warranty. */ +/* + Most icon images are monochrome: Depth=1 + Depth=8 images are extremely rare. At least some of these are color + images but we can't tell the pallete color order. + Output will be in pgm. Convert to ppm with pgmtoppm or pamlookup + if necessary. +*/ + +#include #include #include "nstring.h" #include "pbm.h" +#include "pgm.h" + -/* size in bytes of a bitmap */ -#define BitmapSize(width, height) (((((width) + 15) >> 3) &~ 1) * (height)) static void -ReadIconFile(FILE * const file, - int * const widthP, - int * const heightP, - short unsigned int ** const dataP) { +ReadIconFileHeader(FILE * const file, + int * const widthP, + int * const heightP, + int * const depthP, + int * const bitsPerItemP) { - char variable[80+1]; - int ch; - int status, value, i, data_length, gotsome; + unsigned int fieldCt; - gotsome = 0; + fieldCt = 0; *widthP = *heightP = -1; - for ( ; ; ) - { - while ( ( ch = getc( file ) ) == ',' || ch == '\n' || ch == '\t' || - ch == ' ' ) + + for ( ; ; ) { + char variable[80+1]; + int ch; + unsigned int i; + int value; + + while ((ch = getc(file)) == ',' || ch == '\n' || ch == '\t' || + ch == ' ') ; - for ( i = 0; - ch != '=' && ch != ',' && ch != '\n' && ch != '\t' && - ch != ' ' && (i < (sizeof(variable) - 1)); - i++ ) - { + for (i = 0; + ch != '=' && ch != ',' && ch != '\n' && ch != '\t' && + ch != ' ' && (i < (sizeof(variable) - 1)); + ++i) { variable[i] = ch; if ((ch = getc( file )) == EOF) pm_error( "invalid input file -- premature EOF" ); } variable[i] = '\0'; - if ( streq( variable, "*/" )&& gotsome ) + if (streq(variable, "*/") && fieldCt > 0) break; - if ( fscanf( file, "%d", &value ) != 1 ) + if (fscanf( file, "%d", &value ) != 1) continue; - if ( streq( variable, "Width" ) ) - { + if (streq( variable, "Width")) { *widthP = value; - gotsome = 1; - } - else if ( streq( variable, "Height" ) ) - { + ++fieldCt; + } else if (streq( variable, "Height")) { *heightP = value; - gotsome = 1; - } - else if ( streq( variable, "Depth" ) ) - { - if ( value != 1 ) - pm_error( "invalid depth" ); - gotsome = 1; - } - else if ( streq( variable, "Format_version" ) ) - { - if ( value != 1 ) - pm_error( "invalid Format_version" ); - gotsome = 1; - } - else if ( streq( variable, "Valid_bits_per_item" ) ) - { - if ( value != 16 ) - pm_error( "invalid Valid_bits_per_item" ); - gotsome = 1; + ++fieldCt; + } else if (streq( variable, "Depth")) { + if (value != 1 && value != 8) + pm_error("invalid depth"); + *depthP = value; + ++fieldCt; + } else if (streq(variable, "Format_version")) { + if (value != 1) + pm_error("invalid Format_version"); + ++fieldCt; + } else if (streq(variable, "Valid_bits_per_item")) { + if (value != 16 && value !=32) + pm_error("invalid Valid_bits_per_item"); + *bitsPerItemP = value; + ++fieldCt; } } - if ( *widthP <= 0 ) - pm_error( "invalid width (must be positive): %d", *widthP ); - if ( *heightP <= 0 ) - pm_error( "invalid height (must be positive): %d", *heightP ); - - data_length = BitmapSize( *widthP, *heightP ); - *dataP = (short unsigned int *) malloc( data_length ); - if ( *dataP == NULL ) - pm_error( "out of memory" ); - data_length /= sizeof( short ); - - for ( i = 0 ; i < data_length; i++ ) - { - if ( i == 0 ) - status = fscanf( file, " 0x%4hx", *dataP ); - else - status = fscanf( file, ", 0x%4hx", *dataP + i ); - if ( status != 1 ) - pm_error( "error 4 scanning bits item" ); - } -} + if (fieldCt < 5) + pm_error("invalid sun icon file header: " + "only %u out of required 5 fields present", fieldCt); + if (*widthP <= 0) + pm_error("invalid width (must be positive): %d", *widthP); + if (*heightP <= 0) + pm_error("invalid height (must be positive): %d", *heightP); +} -int -main(int argc, char ** argv) { - FILE* ifp; - bit* bitrow; - register bit* bP; - int rows, cols, row, col, shortcount, mask; - short unsigned int * data; +int +main(int argc, const char ** argv) { + FILE * ifP; + bit * bitrow; + gray * grayrow; + int rows, cols, depth, row, format, maxval, colChars, bitsPerItem; - pbm_init( &argc, argv ); + pm_proginit(&argc, argv); - if ( argc > 2 ) - pm_usage( "[iconfile]" ); + if (argc-1 > 1) + pm_error("Too many arguments (%u). Program takes at most one: " + "name of input file", argc-1); - if ( argc == 2 ) - ifp = pm_openr( argv[1] ); + if (argc-1 == 1) + ifP = pm_openr(argv[1]); else - ifp = stdin; - - ReadIconFile( ifp, &cols, &rows, &data ); - - pm_close( ifp ); - - pbm_writepbminit( stdout, cols, rows, 0 ); - bitrow = pbm_allocrow( cols ); - - for ( row = 0; row < rows; row++ ) - { - shortcount = 0; - mask = 0x8000; - for ( col = 0, bP = bitrow; col < cols; col++, bP++ ) - { - if ( shortcount >= 16 ) - { - data++; - shortcount = 0; - mask = 0x8000; - } - *bP = ( *data & mask ) ? PBM_BLACK : PBM_WHITE; - shortcount++; - mask = mask >> 1; + ifP = stdin; + + ReadIconFileHeader(ifP, &cols, &rows, &depth, &bitsPerItem); + + if (depth == 1) { + format = PBM_TYPE; + maxval = 1; + pbm_writepbminit(stdout, cols, rows, 0); + bitrow = pbm_allocrow_packed(cols); + colChars = cols / 8; + } else { + assert(depth == 8); + format = PGM_TYPE; + maxval = 255; + grayrow = pgm_allocrow(cols); + colChars = cols / depth; + } + + for (row = 0; row < rows; ++row) { + unsigned int colChar; + for (colChar = 0; colChar < colChars; ++colChar) { + unsigned int data; + int status; + + /* read 8 bits */ + if (row==0 && colChar == 0) + status = fscanf(ifP, " 0x%2x", &data); + else if (colChar % (bitsPerItem/8) == 0) + status = fscanf(ifP, ", 0x%2x", &data); + else + status = fscanf(ifP, "%2x", &data); + + /* write 8 bits */ + if (status == 1) { + if (format == PBM_TYPE) + bitrow[colChar] = data; + else + grayrow[colChar] = data; + } else + pm_error("error scanning bits item %u" , colChar); } - data++; - pbm_writepbmrow( stdout, bitrow, cols, 0 ); + + /* output row */ + if (format == PBM_TYPE) + pbm_writepbmrow_packed(stdout, bitrow, cols, 0); + else + pgm_writepgmrow(stdout, grayrow, cols, maxval, 0); } - pm_close( stdout ); - exit( 0 ); + pm_close(ifP); + pm_close(stdout); + return 0; } - -- cgit 1.4.1