generalnmx
Playful/Fascist Mod
I'm having trouble reading bitmaps. The headers are read correctly, but it seems the image data either isn't being converted properly, or I need to do something with palletes. Right now, I'm using the GP32 SDK for simplicy (I'll optimize later as everything is wrapped).
Here's my code:
Here's my code:
Code:
#define CORRECT_BITMAP_TYPE 19778
/* File information header
* provides general information about the file */
typedef struct tagBITMAPFILEHEADER {
uword16 bfType; /* 00h: if this is not 19778, then it is not a bitmap (represents the 'BM') */
udword32 bfSize; /* 02h: total size of the file, including the headers */
uword16 bfReserved1; /* 06h: should contain all zeros */
uword16 bfReserved2; /* 08h: " " " " */
udword32 bfOffBits; /* 0Ah: offset to the image data, varies depending on if a pallete exists */
} BITMAPFILEHEADER, *PBITMAPFILEHEADER;
/* Bitmap information header
* provides information specific to the image data */
typedef struct tagBITMAPINFOHEADER{
uword16 biSize; /* 0Eh: size of remaining header. Should be 40 (size of BITMAPINFOHEADER). */
udword32 biWidth; /* 12h: width of the image in pixels */
udword32 biHeight; /* 16h: height of the image in pixels */
uword16 biPlanes; /* 1Ah: number of bit planes, should be 1 */
uword16 biBitCount; /* 1Ch: number of bits per pixel for colours */
udword32 biCompression; /* 1Eh: 0 for no compression */
udword32 biSizeImage; /* 22h: size of the image data (could be 0) */
udword32 biXPelsPerMeter; /* 26h: horizontal resolution in pixels per meter */
udword32 biYPelsPerMeter; /* 2Ah: vertical resolution in pixels per meter */
udword32 biClrUsed; /* 2Eh: number of colours used from the pallete (24-bit has this as 0)*/
udword32 biClrImportant; /* 32h: number of colour indexes that are important (0 means all are important) */
} BITMAPINFOHEADER, *PBITMAPINFOHEADER;
/* Colour palette */
typedef struct tagRGBQUAD {
ubyte8 rgbBlue; /* number in blue range */
ubyte8 rgbGreen; /* number in green range */
ubyte8 rgbRed; /* number in red range */
ubyte8 rgbReserved; /* reserved byte (should be 0) */
} RGBQUAD;
Code:
void* IGraphicsBitmapLoad(const_char8* filename, ubyte8 bbp, uint32* bitmap_width, uint32* bitmap_height)
{
/* open file with read access */
if ( ISystemFileOpen(filename, FILE_READ) ) /* check to make sure we could open the file */
{
BITMAPFILEHEADER bmfh; /* see igraphics.h */
BITMAPINFOHEADER bmih;
RGBQUAD* pallete = NULL; /* colour table */
uint32 numColours; /* number of colours in pallete */
void* pixelArray = NULL; /* new pixel array to return */
uint32 bytesRead = 0;
uint32 byteWidth = 0, padWidth = 0; /* to counteract byte padding */
int32 j, i; /* used in for loop below */
/* read in the bitmap piece by piece (for crossplatform compatability) */
/* bitmap header */
bytesRead += ISystemFileRead(&bmfh.bfType, sizeof(uword16) );
bytesRead += ISystemFileRead(&bmfh.bfSize, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmfh.bfReserved1, sizeof(uword16) );
bytesRead += ISystemFileRead(&bmfh.bfReserved2, sizeof(uword16) );
bytesRead += ISystemFileRead(&bmfh.bfOffBits, sizeof(udword32) );
if (bmfh.bfType != CORRECT_BITMAP_TYPE)
return(NULL);
/* image data (rest of header) */
bytesRead = 0;
bytesRead += ISystemFileRead(&bmih.biSize, sizeof(uword16) );
bytesRead += ISystemFileRead(&bmfh.bfReserved1, sizeof(uword16) ); /* throw this away */
bytesRead += ISystemFileRead(&bmih.biWidth, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmih.biHeight, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmih.biPlanes, sizeof(uword16) );
bytesRead += ISystemFileRead(&bmih.biBitCount, sizeof(uword16) );
bytesRead += ISystemFileRead(&bmih.biCompression, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmih.biSizeImage, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmih.biXPelsPerMeter, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmih.biYPelsPerMeter, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmih.biClrUsed, sizeof(udword32) );
bytesRead += ISystemFileRead(&bmih.biClrImportant, sizeof(udword32) );
/* given bit-per-pixel should equal the bit count */
if (bbp != bmih.biBitCount)
{
return(NULL);
}
/* set the number of colours */
numColours= 1 << bmih.biBitCount;
/* load for 8 bits per pixel */
if (bmih.biBitCount == 8)
{
pallete = (RGBQUAD*)ISystemMemoryAllocate( sizeof(RGBQUAD) * numColours ); /* array of size numColours */
bytesRead = ISystemFileReadByBytes(pallete, sizeof(RGBQUAD), numColours);
if (bytesRead < numColours )
{
ISystemMemoryFree(pallete);
return(NULL);
}
}
ISystemMemoryFree(pallete);
/* and here we would load up the pixel array */
if (bbp == 8)
{
ubyte8* tempPixelArray = NULL; /* temporary array, need to fix padding */
tempPixelArray = (ubyte8*)ISystemMemoryAllocate( sizeof(ubyte8) * (bmfh.bfSize-bmfh.bfOffBits) );
bytesRead = ISystemFileReadByBytes(tempPixelArray, sizeof(ubyte8), bmfh.bfSize-bmfh.bfOffBits);
if (bytesRead < bmfh.bfSize-bmfh.bfOffBits)
{
ISystemMemoryFree(pallete);
ISystemMemoryFree(tempPixelArray);
}
/* get actual width of bitmap */
byteWidth=padWidth=(udword32)((float)bmih.biWidth*(float)bmih.biBitCount/8.0f);
/* skip through padding */
while( (padWidth % 4) != 0 ) {
padWidth++;
}
/* new array should be actual size (no padding) */
pixelArray = (ubyte8*)ISystemMemoryAllocate( sizeof(ubyte8) * (bmih.biHeight*byteWidth) );
/* to fix padding problems */
if (pixelArray && tempPixelArray && bmih.biHeight > 0)
{
j = (bmfh.bfSize-bmfh.bfOffBits)-3;
for(i = 0; i < (bmfh.bfSize-bmfh.bfOffBits); i+=3)
{
if( ((i+1) % padWidth) == 0 ) {
i += padWidth-byteWidth;
}
*((ubyte8*)pixelArray+j+2) = *(tempPixelArray+i);
*((ubyte8*)pixelArray+j+1) = *(tempPixelArray+i+1);
*((ubyte8*)pixelArray+j) = *(tempPixelArray+i+2);
j++;
} /* end of for loop */
} /* end of height check */
} /* end of bbp == 8 check */
/* assign bitmap size */
if (bitmap_width) *bitmap_width = bmih.biWidth;
if (bitmap_height) *bitmap_height = bmih.biHeight;
return(pixelArray);
}
return(NULL); /* could not open file! */
}