Article View: be.comp.programming
Article #14326BMP to C
From: Kurt
Date: Wed, 28 Feb 2001 21:59
Date: Wed, 28 Feb 2001 21:59
588 lines
14978 bytes
14978 bytes
This is a multi-part message in MIME format.
--------------A0C5D7A0C773EDFE7BFBCC72
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Hallo.
Ik zoek een programma dat BMP files omzet naar C-code. De C is dan
eigenlijk een array vol met chars. Meestal zit er nog een stukje achter
waarin het aantal pixels staat (voor X en Y). Ik heb al iets dergelijk
gevonden maar deze code gaat maar tot 60x70 pixels en ik zou hem tot
max. 320x240 willen laten gaan. Ik ken er zelf niet genoeg van om dit
aan te passen..
Kurt
--------------A0C5D7A0C773EDFE7BFBCC72
Content-Type: text/plain; charset=us-ascii;
name="bmptoc.c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="bmptoc.c"
/******************************************************************************
Microsoft Bitmap Format Files to "C" text file convertor.
Currently only supports 2 color (monochrome) uncompressed bitmap files.
Can read 2.x, 3.x, 4.x format bitmap files.
Copyright (c) 1999 by David Williams.
Permission to use, copy, modify, and distribute this software for any
purpose without fee is hereby granted, provided that this entire notice
is included in all copies of any software which is or includes a copy
or modification of this software and in all copies of the supporting
documentation for such software.
THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
WARRANTY. IN PARTICULAR, THE AUTHOR DOES NOT MAKE ANY REPRESENTATION OR
WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS SOFTWARE OR ITS
FITNESS FOR ANY PARTICULAR PURPOSE.
Please report bugs/send useful modifications/send e-postcards to
David Williams
email: davidwilliams@ozemail.com.au
Development History
24 Nov 99 - First public release
Last change: DW 24 Nov 1999 9:23 am
*******************************************************************************/
/*
This program was compiled with DJGPP (a port of GCC for DOS)
See http://www.delorie.com/djgpp
something like "gcc -Wall -O3 bmptoc.c -o bmptoc.exe" should compile it nicely:)
*/
/*
Command Format:
bmptoc <input bmp filename> <output C source filename>
Note: name of created data array will be same as bmp file name (less extention) + "Data"
Also creates a C structure that defines bitmap as follows.
typedef struct
{
uint8 pixelsWide; * width of bitmap in pixels
uint8 pixelsHigh; * height of bitmap in pixels (scanlines)
uint8 bytesWide; * number of bytes per line (scanline)
byte* pixelData; * pointer to data for bitmap
} GRPBitmap;
*/
/*
Required includes
*/
#include <stdio.h>
#include <dir.h>
/*
Integer numerics
*/
typedef signed char int8;
typedef short int16;
typedef int intd;
typedef int int32;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned int uintd;
typedef unsigned int uint32;
/*
Memory Types
*/
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned int lword;
/**
Truth values - boolean type
**/
typedef byte bool;
/*
Truth constants for use with the boolean type
*/
#undef TRUE
#undef FALSE
#define TRUE ((bool)1)
#define FALSE ((bool)0)
/**
ASCII CHARACTER/STRING types
**/
typedef byte ascii;
#define ASCII_NUL '\000'
#define MAX_BMP_WIDTH 68
#define MAX_BMP_HEIGHT 70
bool readInt8Little(FILE *f, int8 *i);
bool readUint8Little(FILE *f, uint8 *i);
bool readInt16Little(FILE *f, int16 *i);
bool readUint16Little(FILE *f, uint16 *i);
bool readInt32Little(FILE *f, int32 *i);
bool readUint32Little(FILE *f, uint32 *i);
bool readHeader(void);
bool readData(void);
bool writeData(void);
static FILE* bitmapFile = NULL;
static FILE* capFile = NULL;
static uint32 dataOffset;
static uint32 headerSize;
static int32 width = MAX_BMP_WIDTH;
static int32 height = MAX_BMP_HEIGHT; /* positive = 'bottom-up' scan line data, negative = 'top-down' scan line data */
static uint16 planes;
static uint16 bitsPerPixel = 0;
static uint32 compression = 0;
static int16 bytesPerLine;
static ascii bitmapFilename[MAXFILE];
static ascii *compressionMethod[4] = {"Uncompressed","8bit RLE", "4bit RLE", "bitfield encoding"};
#define PAD_TO_4BYTE_BOUNDARY(byteWidth) (((4-(byteWidth&0x03))&0x03)+byteWidth)
#define BYTES_PER_LINE(pixelWidth) ( (pixelWidth>>3) + ((pixelWidth&0x07) > 0) )
/*
Define an array of bytes large enough to hold largest bitmap that can be converted
*/
static byte bitmapData[PAD_TO_4BYTE_BOUNDARY(BYTES_PER_LINE(MAX_BMP_WIDTH))*MAX_BMP_HEIGHT];
int main( int argc, char *argv[] )
{
int exitValue = 1;
printf("\nBMPTOC V1.0 (C) David Williams 1999\n\n");
if ( argc == 3 )
{
if ((bitmapFile = fopen(argv[1],"rb")) != NULL)
{
/*
extract filename from bitmap drive,path,filename,extention
*/
fnsplit(argv[1],NULL,NULL,bitmapFilename,NULL);
if ((capFile = fopen(argv[2],"a")) != NULL)
{
if (readHeader())
{
if (readData())
{
if (writeData())
{
printf("Bitmap conversion successful\n");
exitValue = 0;
}
else
{
printf("Error writing bitmap data\n");
}
}
else
{
printf("Error reading bitmap data\n");
}
}
else
{
printf("Error reading bitmap header\n");
}
}
else
{
printf("Unable to create cap file '%s'\n",argv[2]);
}
}
else
{
printf("Unable to open bitmap file '%s'\n",argv[1]);
}
}
else
{
printf("Invalid number of arguments :\nCommand format : bmptoc <bitmapfilename> <cfilename>\n");
}
/*
Close files whether open or not
*/
fclose(bitmapFile);
fclose(capFile);
exit(exitValue);
}
bool readHeader(void)
{
bool retValue = FALSE;
uint16 wordRead;
uint32 dwordRead;
int16 swidth;
int16 sheight;
/*
Check for 'BM' as first two bytes of file. Ie bitmap format file
*/
if ( readUint16Little(bitmapFile,&wordRead) )
{
if ( wordRead == 0x4D42 )
{
if ( readUint32Little(bitmapFile,&dwordRead) )
{
printf("Bitmap contains %xh bytes\n",dwordRead);
if ( readUint32Little(bitmapFile,&dwordRead) )
{
if ( readUint32Little(bitmapFile,&dataOffset) )
{
printf("Data is at offset %xh bytes from beginning\n",dataOffset);
if ( readUint32Little(bitmapFile,&headerSize) )
{
printf("Header size is %d bytes\n",headerSize);
switch ( headerSize )
{
case 12:
printf("Windows 2.x BMP format file\n");
if ( readInt16Little(bitmapFile,&swidth) )
{
if ( readInt16Little(bitmapFile,&sheight) )
{
if ( readUint16Little(bitmapFile,&planes) )
{
if ( readUint16Little(bitmapFile,&bitsPerPixel) )
{
width = (int32)swidth;
height = (int32)sheight;
compression = 0;
retValue = TRUE;
}
}
}
}
break;
case 108:
printf("Windows 4.x BMP format file\n");
case 40:
if ( headerSize == 40 )
{
printf("Windows 3.x BMP format file\n");
}
if ( readInt32Little(bitmapFile,&width) )
{
if ( readInt32Little(bitmapFile,&height) )
{
if ( readUint16Little(bitmapFile,&planes) )
{
if ( readUint16Little(bitmapFile,&bitsPerPixel) )
{
if ( readUint32Little(bitmapFile,&compression) )
{
retValue = TRUE;
}
}
}
}
}
break;
default:
printf("Unknown bitmap format\n");
break;
}
if ( retValue == TRUE )
{
printf("Bitmap is %d pixels wide, %d pixels high, Bitmap uses %hd bits per pixel\n",width,height,bitsPerPixel);
if ( compression < 4 )
{
printf("Bitmap compression method: %s\n",compressionMethod[compression]);
}
else
{
printf("Unknown compression method: %d\n",compression);
}
}
}
}
}
}
}
else
{
printf("Not a valid bitmap file\n");
}
}
return retValue;
}
bool readData(void)
{
bool retValue = FALSE;
bool topDown = FALSE;
int16 lineNumber;
int16 endLineNumber;
byte *dataBufPos;
if ( height < 0 )
{
topDown = TRUE;
height = -height;
printf("Bitmap data is top-down\n");
}
else
{
printf("Bitmap data is bottom-up\n");
}
if ( (width <= MAX_BMP_WIDTH) && (height <= MAX_BMP_HEIGHT) )
{
if ( bitsPerPixel == 1)
{
if ( compression == 0 )
{
bytesPerLine = (int16)PAD_TO_4BYTE_BOUNDARY(BYTES_PER_LINE(width));
printf("Bytes per scan line = %hd\n",bytesPerLine);
if (fseek(bitmapFile,dataOffset,SEEK_SET) == 0)
{
lineNumber = topDown ? 0 : height-1;
endLineNumber = topDown ? height : -1;
while (lineNumber != endLineNumber)
{
dataBufPos = bitmapData + (lineNumber * bytesPerLine);
if (fread(dataBufPos,bytesPerLine,1,bitmapFile) != 1)
{
printf("Error reading data\n");
break;
}
printf("Processing Line %hd \r",lineNumber);
lineNumber += topDown ? 1 : -1;
}
printf("\n");
if ( lineNumber == endLineNumber )
{
printf("Read of data successful\n");
retValue = TRUE;
}
}
else
{
printf("Error seeking to data in file\n");
}
}
else
{
printf("Bitmap is compressed - only uncompressed bitmaps are supported\n");
}
}
else
{
printf("Too many colors : Only monochrome (2 color) bitmaps are supported\n");
}
}
else
{
printf("Bitmap too big - max of %d wide, %d high\n",MAX_BMP_WIDTH,MAX_BMP_HEIGHT);
}
return retValue;
}
bool writeData(void)
{
int16 lineNumber;
byte *dataByte;
int16 dataBytesPerLine;
int16 byteInLine;
fprintf(capFile,"static byte %sData[] = {\n\t",bitmapFilename);
dataByte = bitmapData;
dataBytesPerLine = (int16)BYTES_PER_LINE(width);
for(lineNumber = 0; lineNumber < height; lineNumber++)
{
for ( byteInLine = 0; byteInLine < bytesPerLine; byteInLine++)
{
if ( byteInLine < dataBytesPerLine )
{
if ( byteInLine > 0 )
{
fputc((int)',',capFile);
}
fprintf(capFile,"0x%hX",(uint16)*dataByte);
}
dataByte++;
}
if ( lineNumber == (height-1) )
{
fputs("\n",capFile);
}
else
{
fputs(",\n\t",capFile);
}
}
fprintf(capFile,"};\nGRPBitmap USR%s = {%d,%d,%d,%sData};\n",
bitmapFilename,width,height,dataBytesPerLine,bitmapFilename);
return TRUE;
}
/*
* These functions read and write our basic integer types from a little-endian
* file. The endian and word-size of the host machine will not affect this
* code. The only assumption made is that the C data type (char) is one byte
* long. This should be a safe assumption.
*/
/*****************************************************************************
*
* Read functions. All read functions take an open file pointer as the first
* parameter and a pointer to data as the second parameter. The return value
* will be TRUE on success, and FALSE on failure. If successful, the second
* parameter will point to the data read.
*/
/*
* The int8 and uint8 types are stored as a single byte on disk. The int8
* type is a signed integer with range (-128..127). The uint8 type is an
* unsigned integer with range (0..255).
*/
bool readInt8Little(FILE *f, int8 *i)
{
int rc;
if ((rc = fgetc(f)) == EOF)
{
return FALSE;
}
*i = (rc & 0xff);
return TRUE;
}
bool readUint8Little(FILE *f, uint8 *i)
{
int rc;
if ((rc = fgetc(f)) == EOF)
{
return FALSE;
}
*i = (rc & 0xff);
return TRUE;
}
/*
* The int16 and uint16 types are stored as two bytes on disk. The int16 type
* is a signed integer with range (-32768..32767). The uint16 type is an
* unisgned integer with range (0..65535).
*/
bool readInt16Little(FILE *f, int16 *i)
{
int rc;
int16 temp = 0;
temp = (fgetc(f) & 0xff);
if ((rc = fgetc(f)) == EOF)
{
return FALSE;
}
temp |= ((rc & 0xff) << 8);
*i = temp;
return TRUE;
}
bool readUint16Little(FILE *f, uint16 *i)
{
int rc;
uint16 temp = 0;
temp = (fgetc(f) & 0xff);
if ((rc = fgetc(f)) == EOF)
{
return FALSE;
}
temp |= ((rc & 0xff) << 8);
*i = temp;
return TRUE;
}
/*
* The int32 and uint32 types are stored as four bytes on disk. The int32
* type is a signed integer with range (-2147483648..2147483647). The uint32
* type is an unisgned integer with range (0..4294967295).
*/
bool readInt32Little(FILE *f, int32 *i)
{
int rc;
int32 temp = 0;
temp = ((long)fgetc(f) & 0xff);
temp |= (((long)fgetc(f) & 0xff) << 8);
temp |= (((long)fgetc(f) & 0xff) << 16);
if ((rc = fgetc(f)) == EOF)
{
return FALSE;
}
temp |= (((long)rc & 0xff) << 24);
*i = temp;
return TRUE;
}
bool readUint32Little(FILE *f, uint32 *i)
{
int rc;
uint32 temp = 0;
temp = ((long)fgetc(f) & 0xff);
temp |= (((long)fgetc(f) & 0xff) << 8);
temp |= (((long)fgetc(f) & 0xff) << 16);
if ((rc = fgetc(f)) == EOF)
{
return FALSE;
}
temp |= (((long)rc & 0xff) << 24);
*i = temp;
return TRUE;
}
--------------A0C5D7A0C773EDFE7BFBCC72--
Technical Details
Message-ID:
<3A9D7476.54601591@pandora.be>Path:
arc1-ca.pugleaf.net!supernews.google.com!sn-xit-03!supernews.com!nntp.cs.ubc.ca!cyclone.bc.net!newsfeeds.belnet.be!news.belnet.be!afrodite.telenet-ops.be!not-for-mailShow Full Headers
Complete Article Headers
X-Google-Language: DUTCH,ASCII-7-bit X-Google-Thread: fcea4,4d195f5a6eb026f,start X-Google-Attributes: gidfcea4,public X-Google-ArrivalTime: 2001-02-28 14:00:20 PST Path: arc1-ca.pugleaf.net!supernews.google.com!sn-xit-03!supernews.com!nntp.cs.ubc.ca!cyclone.bc.net!newsfeeds.belnet.be!news.belnet.be!afrodite.telenet-ops.be!not-for-mail Message-ID: <3A9D7476.54601591@pandora.be> From: Kurt <kurt.stremerch@pandora.be> X-Mailer: Mozilla 4.72 [en] (Windows NT 5.0; I) X-Accept-Language: en MIME-Version: 1.0 Newsgroups: be.comp.programming Subject: BMP to C Content-Type: multipart/mixed; boundary="------------A0C5D7A0C773EDFE7BFBCC72" Lines: 589 Date: Wed, 28 Feb 2001 21:59:45 GMT NNTP-Posting-Host: 195.130.144.24 X-Complaints-To: abuse@pandora.be X-Trace: afrodite.telenet-ops.be 983397585 195.130.144.24 (Wed, 28 Feb 2001 22:59:45 MET) NNTP-Posting-Date: Wed, 28 Feb 2001 22:59:45 MET Organization: Telenet Internet