summaryrefslogtreecommitdiff
path: root/example/tga.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--example/tga.c145
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;
+}