diff options
Diffstat (limited to 'converter/pbm/pbmtoicon.c')
-rw-r--r-- | converter/pbm/pbmtoicon.c | 252 |
1 files changed, 152 insertions, 100 deletions
diff --git a/converter/pbm/pbmtoicon.c b/converter/pbm/pbmtoicon.c index 0e21c202..d5fefb76 100644 --- a/converter/pbm/pbmtoicon.c +++ b/converter/pbm/pbmtoicon.c @@ -1,4 +1,4 @@ -/* pbmtoicon.c - read a portable bitmap and produce a Sun icon file +/* pbmtoicon.c - read a PBM image and produce a Sun icon file ** ** Copyright (C) 1988 by Jef Poskanzer. ** @@ -10,125 +10,177 @@ ** implied warranty. */ +/* 2006.10 (afu) + Changed bitrow from plain to raw, read function from pbm_readpbmrow() to + pbm_readpbmrow_packed. Applied wordint to scoop up 16 bit output items. + putitem changed to better express the output format. + Retired bitwise transformation functions. +*/ + +#include "wordaccess.h" #include "pbm.h" -static void putinit ARGS(( void )); -static void putbit ARGS(( bit b )); -static void putrest ARGS(( void )); -static void putitem ARGS(( void )); +static unsigned short int itemBuff[8]; +static unsigned int itemCnt; /* takes values 0 to 8 */ +FILE * putFp; -int -main( argc, argv ) - int argc; - char* argv[]; - { - FILE* ifp; - bit* bitrow; - register bit* bP; - int rows, cols, format, pad, padleft, padright, row, col; - pbm_init( &argc, argv ); +static void +putinit(FILE * const ofP) { + putFp = ofP; + itemCnt = 0; +} - if ( argc > 2 ) - pm_usage( "[pbmfile]" ); - if ( argc == 2 ) - ifp = pm_openr( argv[1] ); - else - ifp = stdin; - pbm_readpbminit( ifp, &cols, &rows, &format ); - bitrow = pbm_allocrow( cols ); +static void +putitem(wordint const item) { + + if (itemCnt == 8 ) { + /* Buffer is full. Write out one line. */ + int rc; - /* Round cols up to the nearest multiple of 16. */ - pad = ( ( cols + 15 ) / 16 ) * 16 - cols; - padleft = pad / 2; - padright = pad - padleft; - - printf( "/* Format_version=1, Width=%d, Height=%d", cols + pad, rows ); - printf( ", Depth=1, Valid_bits_per_item=16\n */\n" ); - - putinit( ); - for ( row = 0; row < rows; ++row ) - { - pbm_readpbmrow( ifp, bitrow, cols, format ); - for ( col = 0; col < padleft; ++col ) - putbit( 0 ); - for ( col = 0, bP = bitrow; col < cols; ++col, ++bP ) - putbit( *bP ); - for ( col = 0; col < padright; ++col ) - putbit( 0 ); - } + rc = fprintf(putFp, + "\t0x%04x,0x%04x,0x%04x,0x%04x," + "0x%04x,0x%04x,0x%04x,0x%04x,\n", + itemBuff[0],itemBuff[1],itemBuff[2],itemBuff[3], + itemBuff[4],itemBuff[5],itemBuff[6],itemBuff[7]); + if (rc < 0) + pm_error("fprintf() failed to write Icon bitmap"); + + itemCnt = 0; + } + itemBuff[itemCnt++] = item & 0xffff; /* Only lower 16 bits are used */ +} - pm_close( ifp ); - putrest( ); - exit( 0 ); - } +static void +putterm(void) { -static int item, bitsperitem, bitshift, itemsperline, firstitem; + unsigned int i; -static void -putinit( ) - { - itemsperline = 0; - bitsperitem = 0; - item = 0; - bitshift = 15; - firstitem = 1; + for (i = 0; i < itemCnt; ++i) { + int rc; + rc = fprintf(putFp, "%s0x%04x%c", i == 0 ? "\t" : "", itemBuff[i], + i == itemCnt - 1 ? '\n' : ','); + if (rc < 0) + pm_error("fprintf() failed to write Icon bitmap"); } +} + + -#if __STDC__ -static void -putbit( bit b ) -#else /*__STDC__*/ static void -putbit( b ) -bit b; -#endif /*__STDC__*/ - { - if ( bitsperitem == 16 ) - putitem( ); - ++bitsperitem; - if ( b == PBM_BLACK ) - item += 1 << bitshift; - --bitshift; - } +writeIconHeader(FILE * const ofP, + unsigned int const width, + unsigned int const height) { + + int rc; + + rc = fprintf(ofP, + "/* Format_version=1, Width=%u, Height=%u", width, height); + if (rc < 0) + pm_error("fprintf() failed to write Icon header"); + + rc = fprintf(ofP, ", Depth=1, Valid_bits_per_item=16\n */\n"); + if (rc < 0) + pm_error("fprintf() failed to write Icon header"); +} + + static void -putrest( ) - { - if ( bitsperitem > 0 ) - putitem( ); - putchar( '\n' ); +writeIcon(FILE * const ifP, + unsigned int const cols, + unsigned int const rows, + int const format, + FILE * const ofP) { + + unsigned int const wordintSize = sizeof(wordint) * 8; + /* wordintSize is usually 32 or 64 bits. Must be at least 24. */ + unsigned int const items = (cols + 15) / 16; + unsigned int const bitrowBytes = pbm_packed_bytes(cols); + unsigned int const pad = items * 16 - cols; + /* 'padleft' is added to the output. 'padbyte' is for cleaning + the input + */ + unsigned int const padleft = pad / 2; + unsigned int const padbyte = bitrowBytes * 8 - cols; + unsigned int const shift = (wordintSize - 24) + padleft; + + unsigned char * bitbuffer; + unsigned char * bitrow; + unsigned int row; + + bitbuffer = pbm_allocrow_packed(cols + wordintSize); + bitrow = &bitbuffer[1]; + bitbuffer[0] = 0; + bitrow[bitrowBytes] = 0; + + writeIconHeader(ofP, cols + pad, rows); + + putinit(ofP); + + for (row = 0; row < rows; ++row) { + unsigned int itemSeq; + pbm_readpbmrow_packed(ifP, bitrow, cols, format); + + /* Clear post-data junk in final partial byte */ + if (padbyte > 0) { + bitrow[bitrowBytes-1] >>= padbyte; + bitrow[bitrowBytes-1] <<= padbyte; + } + + for (itemSeq = 0; itemSeq < items; ++itemSeq) { + /* Scoop up bits, shift-align, send to format & print function. + + An item is 16 bits, typically spread over 3 bytes due to + left-padding. We use wordint here to scoop up 4 (or more) + consecutive bytes. An item always resides within the higher + 24 bits of each scoop. It is essential to use wordint + (or rather the wordaccess function bytesToWordInt() ); + simple long, uint_32t, etc. do not work for they are not + shift-tolerant. + */ + + wordint const scoop = bytesToWordint(&bitbuffer[itemSeq*2]); + putitem (scoop >> shift); + } } + putterm(); +} -static void -putitem( ) - { - const char* hexits = "0123456789abcdef"; - if ( firstitem ) - firstitem = 0; + +int +main(int argc, + char * argv[]) { + + FILE * ifP; + int rows, cols; + int format; + const char * inputFileName; + + pbm_init(&argc, argv); + + if (argc-1 > 1) + pm_error("Too many arguments (%u). " + "Only argument is optional input file", argc-1); + if (argc-1 == 1) + inputFileName = argv[1]; else - putchar( ',' ); - if ( itemsperline == 8 ) - { - putchar( '\n' ); - itemsperline = 0; - } - if ( itemsperline == 0 ) - putchar( '\t' ); - putchar( '0' ); - putchar( 'x' ); - putchar( hexits[item >> 12] ); - putchar( hexits[( item >> 8 ) & 15] ); - putchar( hexits[( item >> 4 ) & 15] ); - putchar( hexits[item & 15] ); - ++itemsperline; - bitsperitem = 0; - item = 0; - bitshift = 15; - } + inputFileName = "-"; + + ifP = pm_openr(inputFileName); + + pbm_readpbminit(ifP, &cols, &rows, &format); + + writeIcon(ifP, cols, rows, format, stdout); + + pm_close(ifP); + + return 0; +} + |