altra64/src/image.c

182 lines
4.5 KiB
C

#include <libdragon.h>
#include "types.h"
#include "image.h"
//#define STBI_HEADER_FILE_ONLY
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
/*
* Load an image from the rom filesystem, returning a pointer to the
* sprite that hold the image.
*/
sprite_t *loadImageDFS(char *fname) {
int size, x, y, n, fd;
u8 *tbuf;
u8 *ibuf;
sprite_t *sbuf;
fd = dfs_open(fname);
if (fd < 0)
return 0; // couldn't open image
size = dfs_size(fd);
tbuf = malloc(size);
if (!tbuf) {
dfs_close(fd);
return 0; // out of memory
}
dfs_read(tbuf, 1, size, fd);
dfs_close(fd);
ibuf = stbi_load_from_memory(tbuf, size, &x, &y, &n, 4);
free(tbuf);
if (!ibuf)
return 0; // couldn't decode image
sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 2);
if (!sbuf) {
stbi_image_free(ibuf);
return 0; // out of memory
}
sbuf->width = x;
sbuf->height = y;
sbuf->bitdepth = 2;
sbuf->format = 0;
sbuf->hslices = x / 32;
sbuf->vslices = y / 16;
color_t *src = (color_t*)ibuf;
u16 *dst = (u16*)((u32)sbuf + sizeof(sprite_t));
for (int j=0; j<y; j++)
for (int i=0; i<x; i++)
dst[i + j*x] = graphics_convert_color(src[i + j*x]) & 0x0000FFFF;
/* Invalidate data associated with sprite in cache */
data_cache_hit_writeback_invalidate( sbuf->data, sbuf->width * sbuf->height * sbuf->bitdepth );
stbi_image_free(ibuf);
return sbuf;
}
sprite_t *loadImage32(u8 *png, int size) {
int x, y, n, fd;
u8 *tbuf;
u32 *ibuf;
sprite_t *sbuf;
tbuf = malloc(size);
memcpy(tbuf,png,size);
ibuf = (u32*)stbi_load_from_memory(tbuf, size, &x, &y, &n, 4);
free(tbuf);
if (!ibuf)
return 0; // couldn't decode image
sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 4);
if (!sbuf) {
stbi_image_free(ibuf);
return 0; // out of memory
}
sbuf->width = x;
sbuf->height = y;
sbuf->bitdepth = 4;
sbuf->format = 0;
sbuf->hslices = x / 32;
sbuf->vslices = y / 32;
// color_t *src = (color_t*)ibuf;
u32 *dst = (u32*)((u32)sbuf + sizeof(sprite_t));
for (int j=0; j<y; j++)
for (int i=0; i<x; i++)
dst[i + j*x] = ibuf[i + j*x];
/* Invalidate data associated with sprite in cache */
data_cache_hit_writeback_invalidate( sbuf->data, sbuf->width * sbuf->height * sbuf->bitdepth );
stbi_image_free(ibuf);
return sbuf;
}
sprite_t *loadImage32DFS(char *fname) {
int size, x, y, n, fd;
u8 *tbuf;
u32 *ibuf;
sprite_t *sbuf;
fd = dfs_open(fname);
if (fd < 0)
return 0; // couldn't open image
size = dfs_size(fd);
tbuf = malloc(size);
if (!tbuf) {
dfs_close(fd);
return 0; // out of memory
}
dfs_read(tbuf, 1, size, fd);
dfs_close(fd);
ibuf = (u32*)stbi_load_from_memory(tbuf, size, &x, &y, &n, 4);
free(tbuf);
if (!ibuf)
return 0; // couldn't decode image
sbuf = (sprite_t*)malloc(sizeof(sprite_t) + x * y * 4);
if (!sbuf) {
stbi_image_free(ibuf);
return 0; // out of memory
}
sbuf->width = x;
sbuf->height = y;
sbuf->bitdepth = 4;
sbuf->format = 0;
sbuf->hslices = x / 32;
sbuf->vslices = y / 32;
// color_t *src = (color_t*)ibuf;
u32 *dst = (u32*)((u32)sbuf + sizeof(sprite_t));
for (int j=0; j<y; j++)
for (int i=0; i<x; i++)
dst[i + j*x] = ibuf[i + j*x];
/* Invalidate data associated with sprite in cache */
data_cache_hit_writeback_invalidate( sbuf->data, sbuf->width * sbuf->height * sbuf->bitdepth );
stbi_image_free(ibuf);
return sbuf;
}
/*
* Draw an image to the screen using the sprite passed.
*/
void drawImage(display_context_t dcon, sprite_t *sprite) {
int x, y = 0;
rdp_sync(SYNC_PIPE);
rdp_set_default_clipping();
rdp_enable_texture_copy();
rdp_attach_display(dcon);
// Draw image
for (int j=0; j<sprite->vslices; j++) {
x = 0;
for (int i=0; i<sprite->hslices; i++) {
rdp_sync(SYNC_PIPE);
rdp_load_texture_stride(0, 0, MIRROR_DISABLED, sprite, j*sprite->hslices + i);
rdp_draw_sprite(0, x, y);
x += 32;
}
y += 16;
}
rdp_detach_display();
}