#include #include #include #include #ifdef DOS_MODE #include #include #endif void dwordSwap( unsigned long * dword ); void wordSwap( unsigned short * word ); int isBigEndian( void ); typedef unsigned long DWORD; typedef unsigned short WORD; typedef long LONG; typedef struct tagBITMAPFILEHEADER { DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; typedef struct tagBITMAPINFOHEADER{ DWORD biSize; LONG biWidth; LONG biHeight; WORD biPlanes; WORD biBitCount; DWORD biCompression; DWORD biSizeImage; LONG biXPelsPerMeter; LONG biYPelsPerMeter; DWORD biClrUsed; DWORD biClrImportant; } BITMAPINFOHEADER; void WriteBMP(FILE* infile, FILE *outfile, int sizeX, int sizeY ); int isRGBfile( FILE *infile, int sizeX, int sizeY ); char * CreateFilename( char * sourcefilename ); int isNumber( char * string ); #define MAX_IMAGE_X 2048 void main( int argc, char * argv[] ) { FILE *infile; FILE *outfile; char * outfilename; int i; int sfArg = 1; /* index to start of filename argument. */ /* size of bitmap, default to 512 * 512 */ int sizeX = 512; int sizeY = 512; if ( argc > 1 ) { /* Figure out bitmap size from optional first two arguments. */ if ( isNumber( argv[1] ) ) { sizeX = atoi( argv[1] ); sfArg = 2; if ( argc > 2 ) { if ( isNumber( argv[2] ) ) { sizeY = atoi( argv[2] ); sfArg = 3; } else { sizeY = sizeX; } } } else { sizeX = 512; } if ( sizeX > MAX_IMAGE_X || sizeY > MAX_IMAGE_X ) { printf( "Maximum resolution is %d. Aborting.\n", MAX_IMAGE_X ); return; } for ( i = sfArg; (i + 1) <= argc; i++ ) { infile = fopen( argv[i], "rb" ); if ( infile != NULL && isRGBfile( infile, sizeX, sizeY )) { /* Validated inputfile */ /* Create output filename. */ outfilename = CreateFilename( argv[i] ); outfile = fopen( outfilename, "wb" ); if ( outfile != NULL ) { WriteBMP( infile, outfile, sizeX, sizeY ); } else { fprintf( stderr, "Cannot open %s for output.\n", outfilename ); } } else { fprintf( stderr, "%s is not a valid %d x %d, 24 bit rgb file.\n", argv[i], sizeX, sizeY ); if ( infile != NULL ) { fclose( infile ); } } } } else { #ifdef DOS_MODE /* Set "stdin" and "stdout" to have binary mode: */ if ( _setmode( _fileno( stdin ), _O_BINARY ) == -1 || _setmode( _fileno( stdout ), _O_BINARY ) == -1 ) { perror( "Cannot set stdin and stdout to binary mode" ); abort(); } #endif WriteBMP( stdin, stdout, sizeX, sizeY ); } } void WriteBMP(FILE* infile, FILE *outfile, int sizeX, int sizeY ) { int nSize; int red, green, blue; int row, column; static char PadBuf[10]; BITMAPFILEHEADER bmfh; BITMAPINFOHEADER bmih; nSize = sizeof(BITMAPINFOHEADER) + sizeX * sizeY * 3; bmfh.bfSize = nSize + sizeof(BITMAPFILEHEADER) + 2; /* meaning of bfSize open to interpretation (bytes, words, dwords?) -- we won't use it */ bmfh.bfReserved1 = bmfh.bfReserved2 = 0; bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2; bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biWidth = sizeX; bmih.biHeight = sizeY; bmih.biPlanes = 1; bmih.biBitCount = 24; bmih.biCompression = 0; bmih.biSizeImage = sizeX * sizeY * 3; bmih.biXPelsPerMeter = 0; bmih.biYPelsPerMeter = 0; bmih.biClrUsed = 0; bmih.biClrImportant = 0; if ( isBigEndian() ) { dwordSwap( &bmfh.bfSize ); dwordSwap( &bmfh.bfOffBits ); dwordSwap( &bmih.biSize ); dwordSwap( &bmih.biWidth ); dwordSwap( &bmih.biHeight ); wordSwap( &bmih.biPlanes ); wordSwap( &bmih.biBitCount ); dwordSwap( &bmih.biSizeImage ); } fputs ( "BM", outfile ); fwrite( &bmfh, sizeof(BITMAPFILEHEADER), 1, outfile ); fwrite( &bmih, sizeof(BITMAPINFOHEADER), 1, outfile ); for ( row = 0; row < sizeY; row++ ) { for ( column = 0; column < sizeX; column++ ) { red = fgetc( infile ) ; green = fgetc( infile ) ; blue = fgetc( infile ) ; fputc( blue, outfile ); /* reverse order for BMP. */ fputc( green, outfile ); fputc( red, outfile ); } /* pad rows to 4 byte boundary */ fwrite( PadBuf, 1, (4 - ( (sizeX * 3) % 4 )) % 4, outfile ); } } int isRGBfile( FILE *infile, int sizeX, int sizeY ) { long position; rewind( infile ); fseek( infile, 0, SEEK_END ); position = ftell( infile ); rewind( infile ); if ( position == sizeX * sizeY * 3 ) { return 1; } else { return 0; } } char * CreateFilename( char * sourcefilename ) { static char *string = NULL; char * dummystr; char * dotchar; if ( string != NULL ) { free( string ); string = NULL; } dummystr = strdup( sourcefilename ); dotchar = strrchr( dummystr, '.' ); if ( dotchar != NULL ) { *dotchar = '\0'; } string = malloc( strlen( dummystr ) + 5 ); strcpy( string, dummystr ); strcat( string, ".bmp" ); free( dummystr ); return string; } int isNumber( char * string ) { int i; int iFlag = 0; int iStop = 0; for ( i = 0; string[i] != '\0' && iStop == 0; i++ ) { if( isdigit( string[i] ) ) { iFlag = 1; } else { iFlag = 0; iStop = 1; } } return iFlag; } void dwordSwap( unsigned long * dword ) { unsigned char dummy; union words { unsigned long dword; unsigned char byte[4]; } data; data.dword = *dword; dummy = data.byte[0]; data.byte[0] = data.byte[3]; data.byte[3] = dummy; dummy = data.byte[1]; data.byte[1] = data.byte[2]; data.byte[2] = dummy; *dword = data.dword; } void wordSwap( unsigned short * word ) { unsigned char dummy; union words { unsigned short word; unsigned char byte[2]; } data; data.word = *word; dummy = data.byte[0]; data.byte[0] = data.byte[1]; data.byte[1] = dummy; *word = data.word; } int isBigEndian( void ) { union words { unsigned long dword; unsigned short word[2]; } data; data.dword = 1; if ( data.word[0] == 0 ) { /* fputs( "BigEndian!\n", stderr ); */ return 1; } else { /* fputs( "LittleEndian!\n", stderr ); */ return 0; } }