Skip to content

Instantly share code, notes, and snippets.

@samthor
Created July 2, 2018 09:34
Show Gist options
  • Save samthor/fbcb82a28e5edda4709e7dece54f1cb9 to your computer and use it in GitHub Desktop.
Save samthor/fbcb82a28e5edda4709e7dece54f1cb9 to your computer and use it in GitHub Desktop.
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
int chunks, w, h;
} info_t;
const char expected_header[8] = {0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a};
extern int chunk_callback(uint32_t type, uint32_t len, void *p);
uint32_t flip_endian(uint32_t val) {
val = ((val << 8) & 0xff00ff00) | ((val >> 8) & 0xff00ff );
return (val << 16) | ((val >> 16) & 0xffff);
}
char *parse_png(void *p, uint32_t plen, info_t *out) {
if (plen < 8 || memcmp(p, expected_header, 8)) {
return "invalid header";
}
int found_header = 0;
out->chunks = 0;
void *curr = p + 8;
while (curr - p < plen) {
uint32_t *lp = (uint32_t *) curr;
uint32_t len = flip_endian(lp[0]);
if ((curr - p) + (len + 12) > plen) {
return "chunk too large";
}
if (!memcmp(curr + 4, "IHDR", 4)) {
if (len != 13) {
return "IHDR has wrong size";
}
found_header = 1;
out->w = lp[2];
out->h = lp[3];
}
// demonstrate malloc/free: copy chunk so caller can change it
void *copy = malloc(len);
if (!copy) {
return "couldn't malloc for copy";
}
memcpy(copy, curr + 8, len);
chunk_callback(lp[1], len, copy);
free(copy);
curr += (len + 12); // chunk length plus 3 x 32-bit ints
++out->chunks;
}
if (!found_header) {
return "header not found";
}
return NULL;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment