Yesterday, I had to write a customized bitmap loader to replace STB. As much as I like STB, it automatically converts 8-bit palettized textures to 24 or 32-bit. For this particular project, this is not ideal because I need the actual 8-bit pixels and palette data from each .bmp file. Aside from that, STB hasn't been decoding these .bmp files properly anyway.
My bitmap loader appears to work, however, when used to load a large set of bitmaps, there's a memory corruption problem that arises, and I have absolutely no idea what's causing it. I really hate dumping code on you all, but I've spent a long time trying to fix this stupid thing
The bitmap loader:
int bitmap_open_from_memory( const unsigned char* ptr, unsigned int size, struct bitmap_t* bmp )
{
long index = 0;
unsigned short colours;
int x, p = 0;
/* Did we open this file? */
if( ptr == NULL )
return 0;
memset( bmp, 0, sizeof( struct bitmap_t ) );
/* Is this a bitmap file? */
if( ptr[p++] != 'B' || ptr[p++] != 'M' )
{
return 0;
}
/* read in the width and height of the image, and the
number of colours used; ignore the rest */
p+=16;
bmp->width = ptr[p++];
bmp->width |= ptr[p++] << 8;
p+=2;
bmp->height = ptr[p++];
bmp->height |= ptr[p++] << 8;
p+=22;
colours = ptr[p++];
colours |= ptr[p++] << 8;
p+=6;
/* assume we are working with an 8-bit file */
if( colours == 0 )
colours = 256;
bmp->bpp = colours/256;
/* try to allocate memory */
if( ( bmp->data = (byte*) malloc( (word)( bmp->width * bmp->height ) ) ) == NULL )
{
return 0;
}
/* allocate palettes */
if( ( bmp->palette = (byte*) malloc( (word)(3*256) ) ) == NULL )
{
return 0;
}
/* read the palette information */
for( index = 0; index < colours; index++ )
{
bmp->palette[(int)(index*3+2)] = ptr[p++] >> 2;
bmp->palette[(int)(index*3+1)] = ptr[p++] >> 2;
bmp->palette[(int)(index*3+0)] = ptr[p++] >> 2;
x = ptr[p++];
}
/* read the bitmap */
for( index = ( bmp->height-1 ) * bmp->width; index >= 0; index -= bmp->width )
for( x = 0; x < bmp->width; x++ )
bmp->data[(word)(index+x)] = (byte)ptr[p++];
return 1;
}
void bitmap_close( struct bitmap_t* bmp )
{
if( bmp )
{
if( bmp->data )
free(bmp->data);
if( bmp->palette )
free(bmp->palette);
}
}
Intended usage:
int resource_load_texture( char* strname, struct texture_t* texture )
{
void* fileptr = NULL;
// void* dataptr = NULL;
int size = 0;
struct bitmap_t bmp;
/* Sanity check */
if( !texture )
return 0;
/* Attempt to locate this file */
/* If we find it, go ahead and lock this file and return a pointer to it. */
if( !resource_load_raw( strname, &fileptr, &size ) )
return 0;
if( fileptr != NULL )
{
size_t strl = strlen(strname);
/* Attempt to extract texture data from this file, but before we can do this, we need
to find out what type of texture this is. Check for an SGI texture format. If it is,
then use an SGI texture loading routine. If not, just use the STBI routine. */
if( strname[strl-3] == '.' && strname[strl-2] == 'b' && strname[strl-1] == 'w' )
{
/* TODO: Write a SGI texture loader that opens from a resource */
}
else if( strname[strl-4] == '.' && strname[strl-3] == 'r' && strname[strl-2] == 'g' && strname[strl-1] == 'b' )
{
/* TODO: See above */
}
else
{
/*dataptr = stbi_load_from_memory( fileptr, size, &texture->width, &texture->height, &texture->bpp, STBI_default );*/
if( !bitmap_open_from_memory( fileptr, size, &bmp ) )
printf( "\nError reading %s\n", strname );
texture->width = bmp.width;
texture->height = bmp.height;
texture->bpp = bmp.bpp;
}
/* Create the texture */
texture->handle = create_texture( bmp.data, texture->width, texture->height, texture->bpp );
/* Delete the data and file pointer */
free( fileptr );
bitmap_close(&bmp);
//free( dataptr );
}
return 1;
}
This isn't making any sense. When I used STB, everything was fine minus the desired effect. Now, it crashes around the 5th or 6th use, and I have no idea why. This sucks. Any ideas? Thanks.
Shogun.
EDIT: I forgot to include the actual error message:
"malloc: *** error for object 0x1008f5e08: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug"
Which doesn't make any sense because I've never modified any pointers after it's release.