Show readbmp.c syntax highlighted
/* ______ ___ ___
* /\ _ \ /\_ \ /\_ \
* \ \ \L\ \\//\ \ \//\ \ __ __ _ __ ___
* \ \ __ \ \ \ \ \ \ \ /'__`\ /'_ `\/\`'__\/ __`\
* \ \ \/\ \ \_\ \_ \_\ \_/\ __//\ \L\ \ \ \//\ \L\ \
* \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
* \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
* /\____/
* \_/__/
*
* Top level bitmap reading routines.
*
* By Shawn Hargreaves.
*
* See readme.txt for copyright information.
*/
#include <string.h>
#include "allegro.h"
#include "allegro/internal/aintern.h"
typedef struct AL_BITMAP_TYPE_INFO
{
char *ext;
AL_BITMAP *(*load)(AL_CONST char *filename, AL_RGB *pal);
int (*save)(AL_CONST char *filename, AL_BITMAP *bmp, AL_CONST AL_RGB *pal);
struct AL_BITMAP_TYPE_INFO *next;
} AL_BITMAP_TYPE_INFO;
static AL_BITMAP_TYPE_INFO *bitmap_type_list = NULL;
/* al_register_bitmap_file_type:
* Informs Allegro of a new image file type, telling it how to load and
* save files of this format (either function may be NULL).
*/
void al_register_bitmap_file_type(AL_CONST char *ext, AL_BITMAP *(*load)(AL_CONST char *filename, AL_RGB *pal), int (*save)(AL_CONST char *filename, AL_BITMAP *bmp, AL_CONST AL_RGB *pal))
{
char tmp[32], *aext;
AL_BITMAP_TYPE_INFO *iter = bitmap_type_list;
aext = al_uconvert_to_ascii(ext, tmp);
if (strlen(aext) == 0) return;
if (!iter)
iter = bitmap_type_list = malloc(sizeof(struct AL_BITMAP_TYPE_INFO));
else {
for (iter = bitmap_type_list; iter->next; iter = iter->next);
iter = iter->next = malloc(sizeof(struct AL_BITMAP_TYPE_INFO));
}
if (iter) {
iter->load = load;
iter->save = save;
iter->ext = strdup(aext);
iter->next = NULL;
}
}
/* al_load_bitmap:
* Loads a bitmap from disk.
*/
AL_BITMAP *al_load_bitmap(AL_CONST char *filename, AL_RGB *pal)
{
char tmp[32], *aext;
AL_BITMAP_TYPE_INFO *iter;
aext = al_uconvert_to_ascii(get_extension_const(filename), tmp);
for (iter = bitmap_type_list; iter; iter = iter->next) {
if (stricmp(iter->ext, aext) == 0) {
if (iter->load)
return iter->load(filename, pal);
return NULL;
}
}
return NULL;
}
/* al_save_bitmap:
* Writes a bitmap to disk.
*/
int al_save_bitmap(AL_CONST char *filename, AL_BITMAP *bmp, AL_CONST AL_RGB *pal)
{
char tmp[32], *aext;
AL_BITMAP_TYPE_INFO *iter;
aext = al_uconvert_to_ascii(get_extension_const(filename), tmp);
for (iter = bitmap_type_list; iter; iter = iter->next) {
if (stricmp(iter->ext, aext) == 0) {
if (iter->load)
return iter->save(filename, bmp, pal);
return 1;
}
}
return 1;
}
/* _fixup_loaded_bitmap:
* Helper function for adjusting the color depth of a loaded image.
*/
AL_BITMAP *_fixup_loaded_bitmap(AL_BITMAP *bmp, AL_PALETTE pal, int bpp)
{
AL_BITMAP *b2;
b2 = al_create_bitmap_ex(bpp, bmp->w, bmp->h);
if (!b2) {
al_destroy_bitmap(bmp);
return NULL;
}
if (bpp == 8) {
AL_RGB_MAP *old_map = al_rgb_map;
al_generate_optimized_palette(bmp, pal, NULL);
al_rgb_map = malloc(sizeof(AL_RGB_MAP));
if (al_rgb_map != NULL)
al_create_rgb_table(al_rgb_map, pal, NULL);
al_blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h);
if (al_rgb_map != NULL)
free(al_rgb_map);
al_rgb_map = old_map;
}
else if (al_bitmap_color_depth(bmp) == 8) {
al_select_palette(pal);
al_blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h);
al_unselect_palette();
}
else {
al_blit(bmp, b2, 0, 0, 0, 0, bmp->w, bmp->h);
}
al_destroy_bitmap(bmp);
return b2;
}
/* register_bitmap_file_type_exit:
* Free list of registered bitmap file types.
*/
static void register_bitmap_file_type_exit(void)
{
AL_BITMAP_TYPE_INFO *iter = bitmap_type_list, *next;
while (iter) {
next = iter->next;
free(iter->ext);
free(iter);
iter = next;
}
bitmap_type_list = NULL;
/* If we are using a destructor, then we only want to prune the list
* down to valid modules. So we clean up as usual, but then reinstall
* the internal modules.
*/
#if defined(CONSTRUCTOR_FUNCTION) && defined(DESTRUCTOR_FUNCTION)
_register_bitmap_file_type_init();
#endif
_remove_exit_func(register_bitmap_file_type_exit);
}
/* _register_bitmap_file_type_init:
* Register built-in bitmap file types.
*/
void _register_bitmap_file_type_init(void)
{
char buf[32];
_add_exit_func(register_bitmap_file_type_exit);
al_register_bitmap_file_type(al_uconvert_ascii("bmp", buf), al_load_bmp, al_save_bmp);
al_register_bitmap_file_type(al_uconvert_ascii("lbm", buf), al_load_lbm, NULL);
al_register_bitmap_file_type(al_uconvert_ascii("pcx", buf), al_load_pcx, al_save_pcx);
al_register_bitmap_file_type(al_uconvert_ascii("tga", buf), al_load_tga, al_save_tga);
}
#if (defined CONSTRUCTOR_FUNCTION) && (defined DESTRUCTOR_FUNCTION)
CONSTRUCTOR_FUNCTION(static void bitmap_filetype_constructor());
DESTRUCTOR_FUNCTION(static void bitmap_filetype_destructor());
/* bitmap_filetype_constructor:
* Register bitmap filetype functions if this object file is linked
* in. This isn't called if the al_load_bitmap() and al_save_bitmap()
* functions aren't used in a program, thus saving a little space
* in statically linked programs.
*/
static void bitmap_filetype_constructor()
{
_register_bitmap_file_type_init();
}
/* bitmap_filetype_destructor:
* Since we only want to destroy the whole list when we *actually*
* quit, not just when al_remove_system() is called, we need to use a
* destructor to accomplish this.
*/
static void bitmap_filetype_destructor()
{
AL_BITMAP_TYPE_INFO *iter = bitmap_type_list, *next;
while (iter) {
next = iter->next;
free(iter->ext);
free(iter);
iter = next;
}
bitmap_type_list = NULL;
_remove_exit_func(register_bitmap_file_type_exit);
}
#endif
See more files for this project here