From 21e7d15a1b6fae60747b42165e67fcfb9e74cd25 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Fri, 6 Oct 2023 10:40:44 +0700 Subject: [PATCH] texturepacker: Check if files provided can be loaded as images --- .gitignore | 1 + game/Makefile | 4 ++ game/tools/texturepacker.c | 101 ++++++++++++++++++++++++++++++++++++- 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 23bbbb8..3ccef61 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /libs/glad/glad.o /opengl /game/main +/game/texturepacker diff --git a/game/Makefile b/game/Makefile index 84dd10d..7ea0542 100644 --- a/game/Makefile +++ b/game/Makefile @@ -10,6 +10,10 @@ RM=rm -vf build: clean $(CC) $(CFLAGS) $(LDLIBS) $(INCLUDES) $(OBJECTS) $(P).c -o $(P) +.PHONY: texturepacker +texturepacker: + $(CC) $(CFLAGS) $(LDLIBS) $(INCLUDES) $(OBJECTS) tools/texturepacker.c -o texturepacker + .PHONY: run run: build ./$(P) diff --git a/game/tools/texturepacker.c b/game/tools/texturepacker.c index da03a5e..9750cfe 100644 --- a/game/tools/texturepacker.c +++ b/game/tools/texturepacker.c @@ -1,13 +1,112 @@ #include #include +#include #include #define STB_IMAGE_IMPLEMENTATION +#define STBI_FAILURE_USERMSG #include "stb_image.h" -int main(void) { +struct image { + char* filename; + unsigned char* image_data; + int width; + int height; + int channels; +}; +int main(int argc, char* argv[]) { + if (argc == 1) { + fprintf(stderr, "Must provide image files to pack"); + exit(-1); + } + if (argc == 2) { + fprintf(stderr, "Please provide at least 2 images to pack"); + exit(-1); + } + struct image* images = calloc(argc - 1, sizeof(struct image)); + if (images == NULL) { + fprintf(stderr, "Failed to alloc image data array"); + exit(-1); + } + //------------------------------------- + // First get the image info, make sure the file is an image and it exists + //------------------------------------- + int image_count = argc - 1; + for (int i = 0; i < argc - 1; i++) { + struct image* img = &images[i]; + img->filename = argv[i+1]; + int result = stbi_info(img->filename, &img->width, &img->height, &img->channels); + if (result != 1) { + char *errorMsg = "Cannot load image '%s': %s\n"; + fprintf(stderr, errorMsg, img->filename, stbi_failure_reason()); + exit(-1); + } + } + //------------------------------------- + // Now run the packing algorithm + // Note: How to get the minimum power of 2 texture size. Note that this is still + // very inefficient because we're just naively putting them all at 0 + // x = log2(max(width, height)) + // width or height = 2 ** (x + 1) + // This is super inefficient texture packing but I just want to get it working first + //------------------------------------- + int totalh = 0, maxw = 0; + for (int i = 0; i < image_count; i++) { + totalh += images[i].height; + if (images[i].width > maxw) { + maxw = images[i].width; + } + } + int max = totalh > maxw ? totalh : maxw; + int exp = (int)log2(max) + 1; + int size = (int)pow(2, exp); + unsigned char* buf = calloc(size*size, sizeof(char)); + (void)buf; + + //------------------------------------- + // Now load each texture one by one, write to the new image buffer, and free, before + // loading the next one + //------------------------------------- + for (int i = 0; i < argc - 1; i++) { + images[i].filename = argv[i+1]; + + // int width, height, channels; + // images[i].image_data = (unsigned char*)stbi_load(images[i].filename, + // &width, + // &height, + // &channels, + // 4); + + // images[i].width = (short)width; + // images[i].height = (short)height; + // images[i].channels = (char)channels; + images[i].image_data = (unsigned char*)stbi_load(images[i].filename, + &images[i].width, + &images[i].height, + &images[i].channels, + 4); + if (images[i].image_data == NULL) { + char *errorMsg = "Could not load data for image '%s': %s"; + fprintf(stderr, errorMsg, images[i].filename, stbi_failure_reason()); + // QUESTION: Should we clean up here? + exit(-1); + } + } + // unsigned char* image_bytes = images[0].image_data; + // int b = 0; + // while (image_bytes) { + // if (image_bytes[b]) { + // printf("R:%u G:%u B:%u A:%u\n", image_bytes[b], image_bytes[b+1], image_bytes[b+2], image_bytes[b+3]); + // } + // b += 4; + // image_bytes += 4; + // } + for (int i = 0; i < image_count; i++) { + stbi_image_free(images[i].image_data); + } + // for (int i = ) return 0; }