/* * image.c -- PNG decoding for ez3d, wrapped around the vendored * stb_image.h (public domain, v2.30). * * We always ask stb for 4 channels (RGBA): it replicates gray into RGB * and fills alpha with 255 when the source has none, which gives us one * uniform code path regardless of the PNG's actual color type. * 16-bit PNGs are converted down to 8 bits by stb (documented limitation). */ #define STB_IMAGE_IMPLEMENTATION #include "vendor/stb_image.h" #include #include #include "image.h" void ez3d_free_image(ez3d_image_t *img) { if (!img) return; free(img->gray); free(img->alpha); img->gray = img->alpha = NULL; } int ez3d_load_image(const char *path, ez3d_image_t *img) { int w, h, n; unsigned char *rgba = stbi_load(path, &w, &h, &n, 4); if (!rgba) { fprintf(stderr, "ez3d: cannot load '%s': %s\n", path, stbi_failure_reason()); return -1; } if (w < 1 || h < 1) { fprintf(stderr, "ez3d: '%s' has degenerate size %dx%d\n", path, w, h); stbi_image_free(rgba); return -1; } img->w = w; img->h = h; img->has_alpha = (n == 2 || n == 4); /* original had an alpha channel */ img->gray = malloc((size_t)w * h); img->alpha = malloc((size_t)w * h); if (!img->gray || !img->alpha) { fprintf(stderr, "ez3d: out of memory for %dx%d image\n", w, h); stbi_image_free(rgba); ez3d_free_image(img); return -1; } for (size_t i = 0; i < (size_t)w * h; i++) { img->gray[i] = rgba[4 * i]; img->alpha[i] = rgba[4 * i + 3]; } stbi_image_free(rgba); return 0; }