108 lines
2.9 KiB
C
108 lines
2.9 KiB
C
#include <stdlib.h>
|
|
#define QOI_IMPLEMENTATION
|
|
#include <qoi.h>
|
|
#include <allegro5/allegro5.h>
|
|
#include <allegro5/bitmap.h>
|
|
#include <allegro5/bitmap_io.h>
|
|
#include <allegro5/bitmap_lock.h>
|
|
#include <allegro5/color.h>
|
|
#include <allegro5/file.h>
|
|
#include <allegro5/allegro_font.h>
|
|
|
|
ALLEGRO_FONT* _al_load_bitmap_font(const char *filename, int size, int flags);
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
ALLEGRO_BITMAP* _al_load_qoi_f(ALLEGRO_FILE* file, int flags) {
|
|
qoi_desc meta;
|
|
ALLEGRO_PIXEL_FORMAT fmt;
|
|
uint8_t* file_bytes = malloc(al_fsize(file));
|
|
memset(file_bytes, 0, al_fsize(file));
|
|
void* file_pos = file_bytes;
|
|
#define chunk_size 1024
|
|
al_fseek(file, 0, SEEK_SET);
|
|
while (!al_feof(file))
|
|
file_pos += al_fread(file, file_pos, chunk_size);
|
|
|
|
void* data = qoi_decode(file_bytes, al_fsize(file), &meta, 0);
|
|
free(file_bytes); if (!data) return NULL;
|
|
|
|
int oldflags = al_get_new_bitmap_flags();
|
|
al_set_new_bitmap_flags(flags);
|
|
switch (meta.channels) {
|
|
case 3: fmt = ALLEGRO_PIXEL_FORMAT_BGR_888; break;
|
|
case 4: fmt = ALLEGRO_PIXEL_FORMAT_ABGR_8888; break;
|
|
default: free(data); return NULL; break;
|
|
}
|
|
ALLEGRO_BITMAP* bmp = al_create_bitmap(meta.width, meta.height);
|
|
ALLEGRO_LOCKED_REGION* lock = al_lock_bitmap(
|
|
bmp, fmt,
|
|
ALLEGRO_LOCK_WRITEONLY
|
|
);
|
|
al_set_new_bitmap_flags(oldflags);
|
|
if (!lock) return NULL;
|
|
|
|
const int qoi_pitch = meta.width * meta.channels;
|
|
for (int i = 0; i < meta.height; i++) {
|
|
memcpy(lock->data + lock->pitch*i, data + qoi_pitch*i, qoi_pitch);
|
|
if (fmt == ALLEGRO_PIXEL_FORMAT_ABGR_8888
|
|
&& !(flags & ALLEGRO_NO_PREMULTIPLIED_ALPHA))
|
|
for (int p = 0; p < meta.width; p++) {
|
|
uint8_t* pixbytes = (lock->data + lock->pitch*i + p*4);
|
|
pixbytes[0] *= pixbytes[3]/255.0;
|
|
pixbytes[1] *= pixbytes[3]/255.0;
|
|
pixbytes[2] *= pixbytes[3]/255.0;
|
|
}
|
|
}
|
|
|
|
al_unlock_bitmap(bmp);
|
|
free(data); return bmp;
|
|
}
|
|
|
|
ALLEGRO_BITMAP* _al_load_qoi(const char* filename, int flags) {
|
|
ALLEGRO_FILE* fp;
|
|
ALLEGRO_BITMAP* bmp;
|
|
|
|
ALLEGRO_ASSERT(filename);
|
|
|
|
fp = al_fopen(filename, "rb");
|
|
if (!fp) {
|
|
//ALLEGRO_ERROR("Unable to open %s for reading.\n", filename);
|
|
return NULL;
|
|
}
|
|
|
|
bmp = _al_load_qoi_f(fp, flags);
|
|
|
|
al_fclose(fp);
|
|
return bmp;
|
|
}
|
|
|
|
bool _al_identify_qoi(ALLEGRO_FILE* f) {
|
|
uint32_t magic_expected = 1718185841;
|
|
uint32_t magic_found = al_fread32le(f);
|
|
if (magic_found != magic_expected)
|
|
return false;
|
|
if (!al_fseek(f, 14 - 4, ALLEGRO_SEEK_CUR)) // check for min size 14-byte header minus 32-bit magic
|
|
return false;
|
|
return true;
|
|
}
|
|
|
|
bool al_init_qoi() {
|
|
int insane = 0;
|
|
insane |= al_register_bitmap_loader(".qoi", _al_load_qoi);
|
|
insane |= al_register_bitmap_loader_f(".qoi", _al_load_qoi_f);
|
|
insane |= al_register_bitmap_identifier(".qoi", _al_identify_qoi);
|
|
return insane;
|
|
}
|
|
|
|
bool al_init_qoi_font() {
|
|
int insane = 0;
|
|
insane |= al_register_font_loader(".qoi", _al_load_bitmap_font);
|
|
return insane;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif |