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}