From 9c181bcf2a9deaf039a8023d58755b60861da683 Mon Sep 17 00:00:00 2001 From: giraffedata Date: Sat, 21 Oct 2006 17:29:12 +0000 Subject: Use packed PBM functions for efficiency git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@100 9d0c8265-081b-0410-96cb-a4ca84ce46f8 --- converter/pbm/mgrtopbm.c | 148 +++++++++++++-------------- converter/pbm/pbmtocmuwm.c | 161 ++++++++++++++--------------- converter/pbm/pbmtoicon.c | 246 ++++++++++++++++++++++++++++----------------- converter/pbm/pbmtomgr.c | 169 +++++++++++++++---------------- 4 files changed, 378 insertions(+), 346 deletions(-) (limited to 'converter') diff --git a/converter/pbm/mgrtopbm.c b/converter/pbm/mgrtopbm.c index cea4be48..79b918fb 100644 --- a/converter/pbm/mgrtopbm.c +++ b/converter/pbm/mgrtopbm.c @@ -1,4 +1,4 @@ -/* mgrtopbm.c - read a MGR bitmap and produce a portable bitmap +/* mgrtopbm.c - read a MGR bitmap and produce a PBM image. ** ** Copyright (C) 1989 by Jef Poskanzer. ** @@ -10,6 +10,15 @@ ** implied warranty. */ +/* 2006.10 (afu) + Changed bitrow from plain to raw, read function from getc() to fread(), + write function from pbm_writepbmrow() to pbm_writepbmrow_packed(). + Retired bitwise transformation functions. + + NOT tested for old-style format files. Only one zz file in mgrsrc-0.69 . + +*/ + #include #include @@ -17,29 +26,29 @@ #include "mgr.h" -static unsigned char item; -static int bitsperitem, bitshift; static void -getinit(FILE * const file, - int * const colsP, - int * const rowsP, - int * const depthP, - int * const padrightP, - int * const bitsperitemP) { - +readMgrHeader(FILE * const ifP, + unsigned int * const colsP, + unsigned int * const rowsP, + unsigned int * const depthP, + unsigned int * const padrightP ) { + struct b_header head; - int pad; + unsigned int pad; + size_t bytesRead; - if (fread(&head, sizeof(struct old_b_header), 1, file ) != 1) + bytesRead = fread(&head, sizeof(struct old_b_header), 1, ifP); + if (bytesRead != 1) pm_error("Unable to read 1st byte of file. " "fread() returns errno %d (%s)", errno, strerror(errno)); if (head.magic[0] == 'y' && head.magic[1] == 'z') { /* new style bitmap */ - if (fread(&head.depth, - sizeof(head) - sizeof(struct old_b_header), 1, file) - != 1 ) + size_t bytesRead; + bytesRead = fread(&head.depth, + sizeof(head) - sizeof(struct old_b_header), 1, ifP); + if (bytesRead != 1 ) pm_error("Unable to read header after 1st byte. " "fread() returns errno %d (%s)", errno, strerror(errno)); @@ -60,7 +69,7 @@ getinit(FILE * const file, } else { pm_error("bad magic chars in MGR file: '%c%c'", head.magic[0], head.magic[1] ); - pad = -1; /* should never reach here */ + pad = 0; /* should never reach here */ } if (head.h_wide < ' ' || head.l_wide < ' ') @@ -71,75 +80,56 @@ getinit(FILE * const file, *colsP = (((int)head.h_wide - ' ') << 6) + ((int)head.l_wide - ' '); *rowsP = (((int)head.h_high - ' ') << 6) + ((int) head.l_high - ' '); *padrightP = ( ( *colsP + pad - 1 ) / pad ) * pad - *colsP; - - *bitsperitemP = 8; } -static bit -getbit( file ) - FILE* file; - { - bit b; - - if ( bitsperitem == 8 ) - { - item = getc( file ); - bitsperitem = 0; - bitshift = 7; - } - bitsperitem++; - b = ( ( item >> bitshift) & 1 ) ? PBM_BLACK : PBM_WHITE; - bitshift--; - return b; - } - - - int -main( argc, argv ) - int argc; - char* argv[]; - { - FILE* ifp; - bit* bitrow; - register bit* bP; - int rows, cols, depth, padright, row, col; - +main(int argc, + char * argv[]) { + + FILE * ifP; + unsigned char * bitrow; + unsigned int rows, cols, depth; + unsigned int padright; + unsigned int row; + unsigned int itemCount; + 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 + inputFileName = "-"; + + ifP = pm_openr(inputFileName); - pbm_init( &argc, argv ); + readMgrHeader(ifP, &cols, &rows, &depth, &padright); + if (depth != 1) + pm_error("MGR file has depth of %u, must be 1", depth); - if ( argc > 2 ) - pm_usage( "[mgrfile]" ); + pbm_writepbminit(stdout, cols, rows, 0); - if ( argc == 2 ) - ifp = pm_openr( argv[1] ); - else - ifp = stdin; - - getinit( ifp, &cols, &rows, &depth, &padright, &bitsperitem ); - if ( depth != 1 ) - pm_error( "MGR file has depth of %d, must be 1", depth ); - - pbm_writepbminit( stdout, cols, rows, 0 ); - bitrow = pbm_allocrow( cols ); - - for ( row = 0; row < rows; row++ ) - { - /* Get data, bit-reversed within each byte. */ - for ( col = 0, bP = bitrow; col < cols; col++, bP++ ) - *bP = getbit( ifp ); - /* Discard line padding */ - for ( col = 0; col < padright; col ++ ) - (void) getbit( ifp ); - pbm_writepbmrow( stdout, bitrow, cols, 0 ); - } - - pm_close( ifp ); - pm_close( stdout ); - - exit( 0 ); + bitrow = pbm_allocrow_packed(cols + padright); + + itemCount = (cols + padright ) / 8; + + for (row = 0; row < rows; ++row) { + /* The raster formats are nearly identical. + MGR may have rows padded to 16 or 32 bit boundaries. + */ + size_t bytesRead; + bytesRead = fread(bitrow, 1, itemCount, ifP); + if (bytesRead < itemCount) + pm_error("fread() failed to read mgr bitmap data"); + + pbm_writepbmrow_packed(stdout, bitrow, cols, 0); } - - + pm_close(ifP); + pm_close(stdout); + return 0; +} diff --git a/converter/pbm/pbmtocmuwm.c b/converter/pbm/pbmtocmuwm.c index f22ffff3..773d988b 100644 --- a/converter/pbm/pbmtocmuwm.c +++ b/converter/pbm/pbmtocmuwm.c @@ -1,4 +1,4 @@ -/* pbmtocmuwm.c - read a portable bitmap and produce a CMU window manager bitmap +/* pbmtocmuwm.c - read a PBM image and produce a CMU window manager bitmap ** ** Copyright (C) 1989 by Jef Poskanzer. ** @@ -10,102 +10,95 @@ ** implied warranty. */ -#include "pbm.h" -#include "cmuwm.h" - -static void putinit ARGS(( int rows, int cols )); -static void putbit ARGS(( bit b )); -static void putrest ARGS(( void )); -static void putitem ARGS(( void )); +/* 2006.10 (afu) + Changed bitrow from plain to raw, read function from pbm_readpbmrow() to + pbm_readpbmrow_packed(), write function from putc() to fwrite(). -int -main( argc, argv ) - int argc; - char* argv[]; - { - FILE* ifp; - bit* bitrow; - register bit* bP; - int rows, cols, format, padright, row, col; + Retired bitwise transformation functions. +*/ +#include "pbm.h" +#include "cmuwm.h" - pbm_init( &argc, argv ); +static void +putinit(unsigned int const rows, + unsigned int const cols) { - if ( argc > 2 ) - pm_usage( "[pbmfile]" ); + const char * const initWriteError = + "CMU window manager header write error"; - if ( argc == 2 ) - ifp = pm_openr( argv[1] ); - else - ifp = stdin; + int rc; - pbm_readpbminit( ifp, &cols, &rows, &format ); - bitrow = pbm_allocrow( cols ); - - /* Round cols up to the nearest multiple of 8. */ - padright = ( ( cols + 7 ) / 8 ) * 8 - cols; + rc = pm_writebiglong(stdout, CMUWM_MAGIC); + if (rc == -1) + pm_error(initWriteError); + rc = pm_writebiglong(stdout, cols); + if (rc == -1) + pm_error(initWriteError); + rc = pm_writebiglong(stdout, rows); + if (rc == -1) + pm_error(initWriteError); + rc = pm_writebigshort(stdout, (short) 1); + if (rc == -1) + pm_error(initWriteError); +} - putinit( rows, cols ); - for ( row = 0; row < rows; row++ ) - { - pbm_readpbmrow( ifp, bitrow, cols, format ); - for ( col = 0, bP = bitrow; col < cols; col++, bP++ ) - putbit( *bP ); - for ( col = 0; col < padright; col++ ) - putbit( 0 ); - } - pm_close( ifp ); - putrest( ); +int +main(int argc, + char * argv[]) { - exit( 0 ); - } + FILE * ifP; + unsigned char * bitrow; + int rows, cols; + int format; + unsigned int row; + const char * inputFileName; -static unsigned char item; -static int bitsperitem, bitshift; + pbm_init(&argc, argv); -static void -putinit( rows, cols ) - int rows, cols; - { - if ( pm_writebiglong( stdout, CMUWM_MAGIC ) == -1 ) - pm_error( "write error" ); - if ( pm_writebiglong( stdout, cols ) == -1 ) - pm_error( "write error" ); - if ( pm_writebiglong( stdout, rows ) == -1 ) - pm_error( "write error" ); - if ( pm_writebigshort( stdout, (short) 1 ) == -1 ) - pm_error( "write error" ); - - item = 0; - bitsperitem = 0; - bitshift = 7; - } + 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 + inputFileName = "-"; + + ifP = pm_openr(inputFileName); -static void -putbit( bit b ) - { - if ( bitsperitem == 8 ) - putitem( ); - if ( b == PBM_WHITE ) - item += 1 << bitshift; - bitsperitem++; - bitshift--; - } + pbm_readpbminit(ifP, &cols, &rows, &format); + bitrow = pbm_allocrow_packed(cols); -static void -putrest( ) - { - if ( bitsperitem > 0 ) - putitem( ); + putinit(rows, cols); + + /* Convert PBM raster data to CMUWM and write */ + for (row = 0; row < rows; ++row) { + unsigned int const bytesPerRow = pbm_packed_bytes(cols); + unsigned char const padding = + (cols % 8 == 0) ? 0x00 : ((unsigned char) ~0 >> (cols % 8)); + + unsigned int i; + size_t bytesWritten; + + pbm_readpbmrow_packed(ifP, bitrow, cols, format); + + /* Invert all bits in row - raster formats are similar. + PBM Black:1 White:0 "Don't care" bits at end of row + CMUWM Black:0 White:1 End of row padded with 1 + */ + + for (i = 0; i < bytesPerRow; ++i) + bitrow[i] = ~bitrow[i]; + + bitrow[bytesPerRow-1] |= padding; /* Set row end pad bits */ + + bytesWritten = fwrite(bitrow, 1, bytesPerRow, stdout); + if (bytesWritten != bytesPerRow) + pm_error("fwrite() failed to write CMU window manager bitmap"); } -static void -putitem( ) - { - (void) putc( item, stdout ); - item = 0; - bitsperitem = 0; - bitshift = 7; - } + pm_close(ifP); + return 0; +} diff --git a/converter/pbm/pbmtoicon.c b/converter/pbm/pbmtoicon.c index e61ccf13..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,119 +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"); } +} + + static void -putbit( bit b ) - { - 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; +} + diff --git a/converter/pbm/pbmtomgr.c b/converter/pbm/pbmtomgr.c index 816e2a69..56c4fdd6 100644 --- a/converter/pbm/pbmtomgr.c +++ b/converter/pbm/pbmtomgr.c @@ -1,4 +1,4 @@ -/* pbmtomgr.c - read a portable bitmap and produce a MGR bitmap +/* pbmtomgr.c - read a PBM image and produce a MGR bitmap ** ** Copyright (C) 1989 by Jef Poskanzer. ** @@ -10,105 +10,96 @@ ** implied warranty. */ -#include "pbm.h" -#include "mgr.h" - -static void putinit ARGS(( int rows, int cols )); -static void putbit ARGS(( bit b )); -static void putrest ARGS(( void )); -static void putitem ARGS(( void )); - -int -main( argc, argv ) - int argc; - char* argv[]; - { - FILE* ifp; - bit* bitrow; - register bit* bP; - int rows, cols, format, padright, row, col; +/* 2006.10 (afu) + Changed bitrow from plain to raw, read function from pbm_readpbmrow() to + pbm_readpbmrow_packed(), write function from putc() to fwrite(). + Retired bitwise transformation functions. + + Produces only new style bitmap (8 bit padding.) See mgrtopbm.c . +*/ - pbm_init( &argc, argv ); - - 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 ); - - /* Round cols up to the nearest multiple of 8. */ - padright = ( ( cols + 7 ) / 8 ) * 8 - cols; - - putinit( rows, cols ); - for ( row = 0; row < rows; ++row ) - { - pbm_readpbmrow( ifp, bitrow, cols, format ); - for ( col = 0, bP = bitrow; col < cols; ++col, ++bP ) - putbit( *bP ); - for ( col = 0; col < padright; ++col ) - putbit( 0 ); - } - - pm_close( ifp ); - - putrest( ); - - exit( 0 ); - } - -static unsigned char item; -static int bitsperitem, bitshift; +#include "pbm.h" +#include "mgr.h" static void -putinit( rows, cols ) - int rows, cols; - { +putinit(unsigned int const rows, + unsigned int const cols) { + struct b_header head; + size_t writtenCount; head.magic[0] = 'y'; head.magic[1] = 'z'; - head.h_wide = ( ( cols >> 6 ) & 0x3f ) + ' '; - head.l_wide = ( cols & 0x3f ) + ' '; - head.h_high = ( ( rows >> 6 ) & 0x3f ) + ' '; - head.l_high = ( rows & 0x3f ) + ' '; - head.depth = ( 1 & 0x3f ) + ' '; + head.h_wide = ((cols >> 6) & 0x3f) + ' '; + head.l_wide = (cols & 0x3f) + ' '; + head.h_high = (( rows >> 6) & 0x3f) + ' '; + head.l_high = (rows & 0x3f) + ' '; + head.depth = (1 & 0x3f) + ' '; head._reserved = ' '; - fwrite( &head, sizeof(head), 1, stdout ); + writtenCount = fwrite(&head, sizeof(head), 1, stdout); + if (writtenCount != 1) + pm_error("fwrite() failed to write the MGR header."); +} - item = 0; - bitsperitem = 0; - bitshift = 7; - } -static void -putbit( bit b ) - { - if ( bitsperitem == 8 ) - putitem( ); - ++bitsperitem; - if ( b == PBM_BLACK ) - item += 1 << bitshift; - --bitshift; - } -static void -putrest( ) - { - if ( bitsperitem > 0 ) - putitem( ); - } +int +main(int argc, + char * argv[]) { + + FILE * ifP; + unsigned char * bitrow; + int rows; + int cols; + int format; + unsigned int row; + unsigned int bytesPerRow; + /* Number of packed bytes (8 columns per byte) in a row. */ + unsigned int padright; + /* Number of columns added to the right of each row to get up to + a multiple of 8, i.e. an integral number of packed bytes. + */ + 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 + inputFileName = "-"; + + ifP = pm_openr(inputFileName); -static void -putitem( ) - { - fwrite( &item, sizeof(item), 1, stdout ); - item = 0; - bitsperitem = 0; - bitshift = 7; + pbm_readpbminit(ifP, &cols, &rows, &format); + + bitrow = pbm_allocrow_packed(cols); + bytesPerRow = pbm_packed_bytes(cols); + padright = bytesPerRow * 8 - cols; + + putinit(rows, cols); + + for (row = 0; row < rows; ++row) { + /* The raster formats are identical. + The row end pad bits are set to 0 in mgr. + */ + size_t bytesWritten; + + pbm_readpbmrow_packed(ifP, bitrow, cols, format); + + if (padright > 0) { + bitrow[bytesPerRow-1] >>= padright; + bitrow[bytesPerRow-1] <<= padright; + } + + bytesWritten = fwrite(bitrow, 1, bytesPerRow, stdout); + if (bytesWritten != bytesPerRow ) + pm_error("fwrite() failed to write MGR bitmap " + "to Standard Output."); } + pm_close(ifP); + return 0; +} -- cgit 1.4.1