imgconv.c

 1#define STB_IMAGE_IMPLEMENTATION
 2#include "stb_image.h"
 3
 4#define STB_IMAGE_WRITE_IMPLEMENTATION
 5#include "stb_image_write.h"
 6
 7#include "imgconv.h"
 8#include <stdlib.h>
 9#include <string.h>
10
11// write callback for stb_image_write_to_func — appends to a dynamic buffer.
12typedef struct {
13    unsigned char* buf;
14    size_t len;
15    size_t cap;
16} PngBuffer;
17
18static void png_write_cb(void* context, void* data, int size) {
19    PngBuffer* pb = (PngBuffer*)context;
20    if (size <= 0) return;
21
22    size_t needed = pb->len + (size_t)size;
23    if (needed > pb->cap) {
24        size_t new_cap = pb->cap * 2;
25        if (new_cap < needed) new_cap = needed;
26        unsigned char* new_buf = (unsigned char*)realloc(pb->buf, new_cap);
27        if (!new_buf) return; // allocation failure, partial write
28        pb->buf = new_buf;
29        pb->cap = new_cap;
30    }
31    memcpy(pb->buf + pb->len, data, (size_t)size);
32    pb->len += (size_t)size;
33}
34
35ImageResult decode_to_png(const unsigned char* data, size_t len) {
36    ImageResult result = {0};
37
38    int w, h, channels;
39    // Force 4 channels (RGBA) for consistent PNG output
40    unsigned char* pixels = stbi_load_from_memory(data, (int)len, &w, &h, &channels, 4);
41    if (!pixels) {
42        return result;
43    }
44
45    PngBuffer pb = {0};
46    pb.cap = 4096;
47    pb.buf = (unsigned char*)malloc(pb.cap);
48    if (!pb.buf) {
49        stbi_image_free(pixels);
50        return result;
51    }
52
53    int ok = stbi_write_png_to_func(png_write_cb, &pb, w, h, 4, pixels, w * 4);
54    stbi_image_free(pixels);
55
56    if (!ok || pb.len == 0) {
57        free(pb.buf);
58        return result;
59    }
60
61    result.png_data = pb.buf;
62    result.png_len = pb.len;
63    result.width = w;
64    result.height = h;
65    result.ok = 1;
66    return result;
67}
68
69void free_image_result(ImageResult* r) {
70    if (r && r->png_data) {
71        free(r->png_data);
72        r->png_data = NULL;
73        r->png_len = 0;
74    }
75}
76
77int image_dimensions(const unsigned char* data, size_t len, int* width, int* height) {
78    int w, h, channels;
79    int ok = stbi_info_from_memory(data, (int)len, &w, &h, &channels);
80    if (!ok) return 0;
81    *width = w;
82    *height = h;
83    return 1;
84}