summaryrefslogtreecommitdiff
path: root/src/format/image/png.c
blob: 266f4f64ed50de9d87a0e089fead65582744d9a0 (plain)
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
#include "tinyff/image/png.h"
#include "png.h"

ff_result ff_png_isvalid(FILE *file)
{
    char raw_sig[8];
    if (fread(raw_sig, sizeof(char), 8, file) != 8) {
        // Unable to read first 8 bytes
        fclose(file);
        return FF_RESULT_ERROR_INVALID_FILE;
    }

    if (memcmp(raw_sig, PNG_SIGNATURE, 8) != 0) {
        // Signature did not match
        fclose(file);
        return FF_RESULT_ERROR_INVALID_FILE_SIGNITURE;
    }

    return FF_RESULT_OK;
}

ff_result ff_open_png(const char *filepath, ff_png_ctx **out_ctx) {
    // Validate
    
    ff_png_ctx ctx;
    ctx.raw = fopen(filepath, "rb");

    if (!ctx.raw) {
        return FF_RESULT_ERROR_READ_FILE_FAILURE;
    }

    if (ff_png_isvalid(ctx.raw) != FF_RESULT_OK) {
        return ff_png_isvalid(ctx.raw);
    }

    // TODO: Parse
}

ff_result ff_next_chunk(FILE *file, ff_png_chunk **out_chunk) {
    // 1. Read length (4 bytes): We have to read the first 4 bytes to know how many bytes to read for data
    uint32_t length_buffer;

    if (fread(&length_buffer, sizeof(sizeof(ff_byte) * 4), 1, file) != 1) {
        return FF_RESULT_ERROR_READ_FILE_FAILURE;
    }

    // Get the big endian value of the length buffer
    uint32_t data_chunk_length = get_big_endian(length_buffer);

    // 2. Read type (ditto)
    // (we are really just doing the same as before and we don't have to move any positions cause
    //  thank god, FILE can already do that, *ascends*)
    uint32_t type_buffer;

    if (fread(&type_buffer, sizeof(sizeof(ff_byte) * 4), 1, file) != 1) {
        return FF_RESULT_ERROR_READ_FILE_FAILURE;
    }

    // Get the big endian value of the type buffer
    // It needs to be mapped to the enum though
    uint32_t chunk_type = get_big_endian(type_buffer);

    // 3. Read data (data_chunk_length bytes)
    uint32_t *data_buffer = (uint32_t)malloc(data_chunk_length * sizeof(ff_byte));

    if (fread(data_buffer, sizeof(ff_byte), data_chunk_length, file) != data_chunk_length) {
        free(data_buffer);
        return FF_RESULT_ERROR_READ_FILE_FAILURE;
    }

    // 4. Read CRC (4 bytes)
    // However, I don't think we need to use the data right now
    // so we can just read and store it
    uint32_t crc_buffer;

    if (fread(&crc_buffer, sizeof(sizeof(ff_byte) * 4), 1, file) != 1) {
        free(data_buffer);
        return FF_RESULT_ERROR_READ_FILE_FAILURE;
    }

    uint16_t crc = get_big_endian(crc_buffer);

    // 5. Create a chunk struct and return it
    ff_png_chunk *out = (ff_png_chunk *)malloc(sizeof(ff_png_chunk));
    out->length = data_chunk_length;
    out->type = chunk_type;
    out->data = data_buffer;
    out->crc = crc;
    *out_chunk = out;

    return FF_RESULT_OK;
}