diff options
Diffstat (limited to 'example/tga.c')
-rw-r--r-- | example/tga.c | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/example/tga.c b/example/tga.c new file mode 100644 index 0000000..6e8eb34 --- /dev/null +++ b/example/tga.c @@ -0,0 +1,145 @@ +/* + * Copyright (C) 2024 dwlr <dweller@cabin.digital> + * + * BSD 3-Clause License (BSD-3-Clause) + * See LICENSE for details + */ + +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +#include <unistd.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <fcntl.h> + + +typedef struct packed tga_hdr +{ + u8 id_len; + u8 cmap_type; + u8 img_type; + + struct packed + { + u16 first_entry_idx; + u16 length; + u8 entry_size; + + } cmap_spec; + + struct packed + { + u16 xorig; + u16 yorig; + u16 width; + u16 height; + u8 depth; + u8 desc; + + } img_spec; + +} tga_hdr; + +typedef enum tga_img_type +{ + TGA_IMG_NONE, + TGA_IMG_RAW_CMAP, + TGA_IMG_RAW_TRUE, + TGA_IMG_RAW_BW, + TGA_IMG_RLE_CMAP, + TGA_IMG_RLE_TRUE, + TGA_IMG_RLE_BW, + + TGA_IMG_TYPE_SIZE + +} tga_img_type; + +typedef union rgba +{ + u32 rgba; + struct + { + u8 b; + u8 g; + u8 r; + u8 a; + } c; + +} rgba; + +#define A c.a +#define R c.r +#define G c.g +#define B c.b + +typedef struct texture +{ + ssize width; + ssize height; + + rgba* texels; + +} texture; + + +bool tga2tex_from_mem(texture* tex, const u8* data, ssize sz) +{ + tga_hdr* hdr = NULL; + rgba* img_dat = NULL; + + assert(tex); + assert(data); + assert(sz > 0); + + hdr = (tga_hdr*)data; + if(hdr->img_type != TGA_IMG_RAW_TRUE) return false; + if(hdr->cmap_type) return false; + + /* FIXME(dwlr): check pixel depth */ + /* FIXME(dwlr): check bit 5 and 4 of img_spec.desc (ordering) */ + + tex->width = hdr->img_spec.width; + tex->height = hdr->img_spec.height; + + sz = sizeof(*tex->texels) * tex->width * tex->height; + tex->texels = malloc(sz); + + img_dat = (rgba*)(((u8*)hdr) + sizeof(*hdr) + hdr->id_len); + + /* FIXME(dwlr): convert if needed */ + memcpy(tex->texels, img_dat, sz); + + return true; +} + + +bool tga2tex_from_file(texture* tex, const char* path) +{ + struct stat stat = {0}; + + bool ret = false; + s32 fd = -1; + ssize sz = 0; + u8* file = NULL; + + assert(tex); + assert(path); + + fd = open(path, O_RDONLY); + if(fd < 0) goto clean_close; + + if(fstat(fd, &stat) != 0) goto clean_close; + + file = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if(file == MAP_FAILED) goto clean_close; + + ret = tga2tex_from_mem(tex, file, sz); + + munmap(file, stat.st_size); +clean_close: + close(fd); + + return ret; +} |