kitchen: README + MISSIONS/engine-c keep-drop notes
This commit is contained in:
parent
1d351918da
commit
575d7d29b8
130 changed files with 9817 additions and 1 deletions
83
engine-c/src/png.c
Normal file
83
engine-c/src/png.c
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Minimal dependency-free PNG encoder (RGBA) using zlib.
|
||||
* Avoids linking SDL2_image (which drags in an incompatible SDL3 at runtime).
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "kknd.h"
|
||||
#include <zlib.h>
|
||||
|
||||
static uint32_t crc_table[256];
|
||||
static int crc_done = 0;
|
||||
|
||||
static void crc_init(void) {
|
||||
for (uint32_t n = 0; n < 256; n++) {
|
||||
uint32_t c = n;
|
||||
for (int k = 0; k < 8; k++)
|
||||
c = (c & 1) ? (0xedb88320U ^ (c >> 1)) : (c >> 1);
|
||||
crc_table[n] = c;
|
||||
}
|
||||
crc_done = 1;
|
||||
}
|
||||
|
||||
static uint32_t crc_update(uint32_t c, const uint8_t *buf, size_t len) {
|
||||
c = ~c;
|
||||
for (size_t i = 0; i < len; i++)
|
||||
c = crc_table[(c ^ buf[i]) & 0xff] ^ (c >> 8);
|
||||
return ~c;
|
||||
}
|
||||
|
||||
static void chunk(FILE *f, const char *type, const uint8_t *data, uint32_t len) {
|
||||
uint8_t hdr[4];
|
||||
hdr[0] = (len >> 24) & 0xff; hdr[1] = (len >> 16) & 0xff;
|
||||
hdr[2] = (len >> 8) & 0xff; hdr[3] = len & 0xff;
|
||||
fwrite(hdr, 1, 4, f);
|
||||
fwrite(type, 1, 4, f);
|
||||
if (len) fwrite(data, 1, len, f);
|
||||
uint32_t crc = crc_update(0, (const uint8_t *)type, 4);
|
||||
crc = crc_update(crc, data, len);
|
||||
uint8_t cr[4];
|
||||
cr[0] = (crc >> 24) & 0xff; cr[1] = (crc >> 16) & 0xff;
|
||||
cr[2] = (crc >> 8) & 0xff; cr[3] = crc & 0xff;
|
||||
fwrite(cr, 1, 4, f);
|
||||
}
|
||||
|
||||
int png_save(const char *path, int w, int h, const uint8_t *rgba) {
|
||||
if (!crc_done) crc_init();
|
||||
FILE *f = fopen(path, "wb");
|
||||
if (!f) return -1;
|
||||
|
||||
static const uint8_t sig[8] = {137,80,78,71,13,10,26,10};
|
||||
fwrite(sig, 1, 8, f);
|
||||
|
||||
uint8_t ihdr[13];
|
||||
ihdr[0] = (w >> 24) & 0xff; ihdr[1] = (w >> 16) & 0xff;
|
||||
ihdr[2] = (w >> 8) & 0xff; ihdr[3] = w & 0xff;
|
||||
ihdr[4] = (h >> 24) & 0xff; ihdr[5] = (h >> 16) & 0xff;
|
||||
ihdr[6] = (h >> 8) & 0xff; ihdr[7] = h & 0xff;
|
||||
ihdr[8] = 8; /* bit depth */
|
||||
ihdr[9] = 6; /* colour type RGBA */
|
||||
ihdr[10] = 0; ihdr[11] = 0; ihdr[12] = 0;
|
||||
chunk(f, "IHDR", ihdr, 13);
|
||||
|
||||
/* raw scanlines with filter byte 0 */
|
||||
uint8_t *raw = (uint8_t *)malloc((size_t)(w * 4 + 1) * h);
|
||||
if (!raw) { fclose(f); return -1; }
|
||||
for (int y = 0; y < h; y++) {
|
||||
raw[(size_t)y * (w * 4 + 1)] = 0;
|
||||
memcpy(raw + (size_t)y * (w * 4 + 1) + 1, rgba + (size_t)y * w * 4, (size_t)w * 4);
|
||||
}
|
||||
uLongf cmp_cap = compressBound((uLong)(w * 4 + 1) * h);
|
||||
uint8_t *cmp = (uint8_t *)malloc(cmp_cap);
|
||||
if (!cmp) { free(raw); fclose(f); return -1; }
|
||||
uLongf cmp_len = cmp_cap;
|
||||
compress2((Bytef *)cmp, &cmp_len, (const Bytef *)raw,
|
||||
(uLong)(w * 4 + 1) * h, Z_BEST_COMPRESSION);
|
||||
chunk(f, "IDAT", cmp, (uint32_t)cmp_len);
|
||||
chunk(f, "IEND", NULL, 0);
|
||||
|
||||
free(cmp); free(raw);
|
||||
fclose(f);
|
||||
return 0;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue