summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTazyFoundSoup <gardendistrict0x0@outlook.com>2026-04-14 10:12:56 +1000
committerTazyFoundSoup <gardendistrict0x0@outlook.com>2026-04-14 10:12:56 +1000
commit04fb8400143a37947baa0ec70b6c1768bff6944c (patch)
treea333a935932a946b825475ba3a48f9cd6c83605b /src
parenta01254912693cd1e9f7f4dab8b475c1b8287a9fb (diff)
feat(png): Add png dispatcher
Diffstat (limited to 'src')
-rw-r--r--src/format/image/png.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/src/format/image/png.c b/src/format/image/png.c
index fa803bc..d1e159d 100644
--- a/src/format/image/png.c
+++ b/src/format/image/png.c
@@ -4,6 +4,8 @@
// External
#include <ext/tinf.h>
+static ff_result ff_png_dispatch(ff_ctx* ctx, ff_stream* stream, ff_png_ctx *png_ctx);
+
const ff_png_chunk_handler ff_png_chunk_handlers[] = {
{"IHDR", ff_png_header_handler},
{"IDAT", ff_png_data_handler},
@@ -16,6 +18,57 @@ const ff_png_chunk_handler ff_png_chunk_handlers[] = {
{NULL, NULL} // Terminator
};
+static ff_result ff_png_dispatch(ff_ctx* ctx, ff_stream* stream, ff_png_ctx *png_ctx)
+{
+ while (1)
+ {
+ // 1. Read the length
+ uint8_t chunk_length[4];
+ if (!stream->read(chunk_length, 4, stream->user)) {
+ png_ctx->last_error = FF_RESULT_ERROR_READ_FILE_FAILURE;
+ return FF_RESULT_ERROR_READ_FILE_FAILURE;
+ }
+ uint32_t length = ff_be32(chunk_length);
+
+ // 2. Read the chunk type
+ uint8_t chunk_type[4];
+ if (!stream->read(chunk_type, 4, stream->user)) {
+ png_ctx->last_error = FF_RESULT_ERROR_READ_FILE_FAILURE;
+ return FF_RESULT_ERROR_READ_FILE_FAILURE;
+ }
+
+ if (ff_memcmp(chunk_type, "IEND", 4) == 0) return FF_RESULT_OK;
+
+ // 3. Read the chunk data (always, even if no handler)
+ uint8_t* chunk_data = ctx->allocator.ff_alloc(length);
+ if (!chunk_data) return FF_RESULT_ERROR_MEMORY_ALLOCATION;
+ if (!stream->read(chunk_data, length, stream->user)) {
+ ctx->allocator.ff_free(chunk_data);
+ png_ctx->last_error = FF_RESULT_ERROR_READ_FILE_FAILURE;
+ return FF_RESULT_ERROR_READ_FILE_FAILURE;
+ }
+
+ // 4. Find and call the handler
+ for (int i = 0; ff_png_chunk_handlers[i].type != NULL; i++) {
+ if (ff_memcmp(chunk_type, ff_png_chunk_handlers[i].type, 4) == 0) {
+ if (ff_png_chunk_handlers[i].handler != NULL)
+ ff_png_chunk_handlers[i].handler(ctx, chunk_data, length, png_ctx);
+ break;
+ }
+ }
+
+ ctx->allocator.ff_free(chunk_data);
+
+ // 5. Skip the CRC (for now)
+ // TODO: Validate CRC
+ uint8_t crc[4];
+ if (!stream->read(crc, 4, stream->user)) {
+ png_ctx->last_error = FF_RESULT_ERROR_READ_FILE_FAILURE;
+ return FF_RESULT_ERROR_READ_FILE_FAILURE;
+ }
+ }
+}
+
ff_result ff_png_isvalid(ff_ctx* ctx, ff_stream *stream)
{
ff_dprintf(ctx, "png: validating signature\n");
@@ -77,6 +130,14 @@ ff_result ff_open_png(ff_ctx* ctx, ff_stream *stream, ff_png_ctx **out_ctx, ff_f
ff_dprintf(ctx, "png: validation passed\n");
png_ctx->valid = true;
+ ff_dprintf(ctx, "png: calling dispatcher\n");
+
+ ff_result res = ff_png_dispatch(ctx, stream, png_ctx);
+ if (res != FF_RESULT_OK) {
+ ctx->allocator.ff_free(png_ctx);
+ return res;
+ }
+
*out_ctx = png_ctx;
ff_dprintf(ctx, "png: open_png reached WIP end\n");