1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
#include "tinyff/image/png.h"
#include "tinyff/dbg.h"
#include "png.h"
ff_result ff_png_isvalid(FILE *file)
{
ff_dprintf("png: validating signature\n");
char raw_sig[8];
if (fread(raw_sig, 1, 8, file) != 8) {
ff_dprintf("png: failed to read signature bytes\n");
return FF_RESULT_ERROR_INVALID_FILE;
}
ff_dprintf(
"png: signature read: %02X %02X %02X %02X %02X %02X %02X %02X\n",
raw_sig[0], raw_sig[1], raw_sig[2], raw_sig[3],
raw_sig[4], raw_sig[5], raw_sig[6], raw_sig[7]
);
if (memcmp(raw_sig, PNG_SIGNATURE, 8) != 0) {
ff_dprintf("png: signature mismatch\n");
return FF_RESULT_ERROR_INVALID_FILE_SIGNITURE;
}
ff_dprintf("png: signature valid\n");
return FF_RESULT_OK;
}
ff_result ff_open_png(const char *filepath, ff_png_ctx **out_ctx)
{
ff_dprintf("png: opening file '%s'\n", filepath);
ff_png_ctx ctx;
ctx.raw = fopen(filepath, "rb");
if (!ctx.raw) {
ff_dprintf("png: fopen failed\n");
return FF_RESULT_ERROR_READ_FILE_FAILURE;
}
ff_dprintf("png: file opened successfully\n");
ff_result res = ff_png_isvalid(ctx.raw);
if (res != FF_RESULT_OK) {
ff_dprintf("png: validation failed (%d)\n", res);
fclose(ctx.raw);
return res;
}
ff_dprintf("png: validation passed\n");
*out_ctx = NULL;
ff_dprintf("png: open_png reached WIP end\n");
return FF_RESULT_OK;
}
// Handlers
ff_result ff_png_header_handler(uint8_t *buf, size_t len, ff_png_ctx *ctx)
{
ff_dprintf("png: IHDR chunk received (len=%zu)\n", len);
if (len != 13) {
ff_dprintf("png: invalid IHDR length\n");
return FF_RESULT_ERROR_INVALID_FILE;
}
uint32_t w = get_big_endian(buf);
uint32_t h = get_big_endian(buf + 4);
ff_dprintf("Width: %u\n", w);
ff_dprintf("Height: %u\n", h);
ff_dprintf("Bit depth: %u\n", buf[8]);
ff_dprintf("Color type: %u\n", buf[9]);
ff_dprintf("Compression method: %u\n", buf[10]);
ff_dprintf("Filter method: %u\n", buf[11]);
ff_dprintf("Interlace method: %u\n", buf[12]);
ctx->width = w;
ctx->height = h;
ctx->bit_depth = buf[8];
ctx->color_type = buf[9];
ff_dprintf("png: IHDR stored in context\n");
return FF_RESULT_OK;
}
ff_result ff_png_chunk_palette_handler(uint8_t *buf, size_t len, ff_png_ctx *ctx)
{
ff_dprintf("png: PLTE chunk received (len=%zu)\n", len);
uint16_t num_entries = len / 3;
ff_dprintf("png: PLTE contains %u palette entries\n", num_entries);
return FF_RESULT_WARN_NO_IMPL;
}
ff_result ff_png_data_handler(uint8_t *buf, size_t len, ff_png_ctx *ctx)
{
ff_dprintf("png: IDAT chunk received (len=%zu)\n", len);
// For now, compression handling is not implemented
// and instead will assume data is uncompressed
ff_dprintf("png: IDAT handler WIP - data is assumed uncompressed\n");
ff_dprintf("png: IDAT handler WIP - expect undefined behavior\n");
// We will need to loop over all the scanlines and apply filters
// But im too lazy to do that right now
// TODO implement
return FF_RESULT_WARN_NO_IMPL;
}
ff_result ff_png_end_handler(uint8_t *buf, size_t len, ff_png_ctx *ctx)
{
ff_dprintf("png: IEND chunk received (len=%zu)\n", len);
ff_dprintf("png: all chunks received\n");
return FF_RESULT_OK;
}
|