/*************************************************************************** bmpal.c - creates color/palette maps from/for .BMPS. Created (v.01) as a "sister" program to bmp2map to help map authors determine palette indices for colors used. Copyright(C) 1998 - Silicon Slick's Software, Supplies and Support Services http://www2.cy-net.net/~si_slick si_slick@cy-net.net This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ***************************************************************************/ char *pgmname="BMPAL (v.01) - creates color/palette map from/for a .BMP"; char *copyright1="Copyright(C) 1998 - Silicon Slick's Software, Supplies and Support Services"; char *copyright2="BMPAL comes with ABSOLUTELY NO WARRANTY. See GPL.TXT for details"; #include #include #include typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned long DWORD; #define SAFEVERSION 1 #define MUSTBETYPE (((WORD) 'M' << 8) | 'B') /* 1st 2bytes must=='BM' */ #define BI_RGB 0L /* uncompressed 256 color .BMPs only */ #define FILENAMESIZE 128 /* for all file names */ #define OUTSIZE 512 typedef struct tagBITMAPFILEHEADER { WORD bfType; DWORD bfSize; WORD bfReserved1; WORD bfReserved2; DWORD bfOffBits; } BITMAPFILEHEADER; /* 14 bytes */ typedef struct tagBITMAPINFOHEADER { DWORD biSize; /* 15-18 */ DWORD biWidth; /* 19-22 */ DWORD biHeight; /* 23-26 */ WORD biPlanes; WORD biBitCount; DWORD biCompression; /* 31-34 */ DWORD biSizeImage; /* 35-38 */ DWORD biXPelsPerMeter; /* 39-42 */ DWORD biYPelsPerMeter; /* 43-46 */ DWORD biClrUsed; /* 47-50 */ DWORD biClrImportant; /* 51-54 */ } BITMAPINFOHEADER; typedef struct tagRGBQUAD { BYTE rgbBlue; BYTE rgbGreen; BYTE rgbRed; BYTE rgbReserved; } RGBQUAD; /*** bmpal() - copy bitmap header and palette and create color map ***/ void bmpal( FILE *bmpfp, FILE *outfp, int outsize) { BITMAPFILEHEADER bmfh; /* bit map file header */ BITMAPINFOHEADER bmih; RGBQUAD rgbq; int i, j; /* read file header */ if( fread( &bmfh, sizeof( BITMAPFILEHEADER), 1, bmpfp) != 1) { printf("Error reading .BMP.\n"); exit(1); } /* check to see if it is a valid bitmap file */ if( bmfh.bfType != MUSTBETYPE) { printf(".BMP is not a valid bitmap.\n"); exit(1); } if( bmfh.bfReserved1 || bmfh.bfReserved2) { printf("Reserved fields are not 0?\n"); exit(1); } printf("Input .BMP is %ld bytes long. Image offset is %ld.\n", bmfh.bfSize, bmfh.bfOffBits); printf("Output .BMP is %ld bytes long. Image offset is %ld.\n", bmfh.bfSize=((long)outsize*outsize+bmfh.bfOffBits), bmfh.bfOffBits); fwrite( &bmfh, sizeof( BITMAPFILEHEADER), 1, outfp); /* read info header */ if( fread( &bmih, sizeof( BITMAPINFOHEADER), 1, bmpfp) != 1) { printf("Error reading .BMP\n"); exit(1); } if( bmih.biPlanes != 1) { printf(".BMP has incorrect value (%d) for biPlanes.\n", bmih.biPlanes); exit(1); } /* check for 256 colors */ if( bmih.biBitCount != 8) { printf("Not a 8-bit (256 color) .BMP\n"); exit(1); } /* make sure not .RLE */ if( bmih.biCompression != BI_RGB) { printf("Only uncompressed .BMPs allowed.\n"); exit(1); } printf("Header: %ld bytes Image: %ld bytes\n", bmih.biSize, bmih.biSizeImage); printf("%ld x %ld pixels w/ %ld colors, %ld of which are \"important\"\n", bmih.biWidth, bmih.biHeight, bmih.biClrUsed, bmih.biClrImportant); printf("Pixels/Meter = %ld x %ld\n", bmih.biXPelsPerMeter, bmih.biYPelsPerMeter); bmih.biWidth = bmih.biHeight = outsize; bmih.biSizeImage = (long) outsize * outsize; fwrite( &bmih, sizeof( BITMAPINFOHEADER), 1, outfp); if( bmih.biClrUsed != 256) { printf("\n\n Warning: %d colors used in source .BMP\n", bmih.biClrUsed); printf( " The output .BMP is probably not correct (YMMV).\n\n"); printf( " You might be able to impart this information\n"); printf( " by loading the .BMP into a paint program and then\n"); printf( " explicitly saving it as a 256 color .BMP\n"); } /* palette entries */ for( i = 0; i < bmih.biClrUsed; i++) { if( fread( &rgbq, sizeof(RGBQUAD), 1, bmpfp) != 1) { printf("Error reading palette information.\n"); exit(1); } fwrite( &rgbq, sizeof( RGBQUAD), 1, outfp); #ifdef DEBUG printf("Index: %02x Red: %02x Green: %02x Blue:%02x\n", i, rgbq.rgbRed, rgbq.rgbGreen, rgbq.rgbBlue); #endif } for( i = 0; i < outsize; i++) { for( j = 0; j < outsize; j++) { if( (!(j%(outsize/16))) || (!(i%(outsize/16))))fputc( 0, outfp); else fputc( ((outsize-1)-i/(outsize/16))*16+(j/(outsize/16)), outfp); } } return; } /*** bmpal() ***/ /*** main() - ***/ void main( int argc, char **argv) { char inname[ FILENAMESIZE]; char outname[ FILENAMESIZE]; FILE *infp, *outfp; int outsize = OUTSIZE; /* prepare file names */ if( argc < 3) { printf(".BMP files not specified on command line\n\n"); printf("Command line is:\n\n"); printf("BMPAL []\n\n", OUTSIZE); exit(1); } strcpy( inname, argv[1]); strcpy( outname, argv[2]); if( argc > 2) { sscanf( argv[3], "%d", &outsize); } printf("Output file (%s) will be %dx%d pixels\n", outname, outsize, outsize); #if SAFEVERSION outfp = fopen( outname, "rb"); if( outfp) { printf("File %s already exists and WILL NOT be overwritten\n", outname); printf("Delete this file if you want to use this name.\n"); exit( 1); } #endif outfp = fopen( outname, "wb"); if( ! outfp) { printf("\n Unable to open %s for output\n", outname); exit( 1); } infp = fopen( inname, "rb"); if( ! infp) { printf("\n Unable to open %s for input\n", inname); exit( 1); } bmpal( infp, outfp, outsize); fclose( infp); fclose( outfp); printf("Done.\n"); exit(0); } /*** main() ***/ /*** EOF ***/