/* * Copyright (C) 2024 dwlr * * BSD 3-Clause License (BSD-3-Clause) * See LICENSE for details */ #include #include #include #include #include #include #include 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; }