diff --git a/common/image.c b/common/image.c new file mode 100644 index 0000000..bf2de09 --- /dev/null +++ b/common/image.c @@ -0,0 +1,9 @@ +#include "image.h" +#include + +void free_image(Image* img) { + if (img && img->data) { + free(img->data); + img->data = NULL; + } +} diff --git a/common/image.h b/common/image.h new file mode 100644 index 0000000..26d623d --- /dev/null +++ b/common/image.h @@ -0,0 +1,10 @@ +#include + +typedef struct { + int width; + int height; + int channels; + uint8_t* data; +} image_t; + +void free_image(image_t* img); diff --git a/common/utils.c b/common/utils.c new file mode 100644 index 0000000..2b97488 --- /dev/null +++ b/common/utils.c @@ -0,0 +1,7 @@ +#include "common.h" + +uint32_t char_to_uint32 (unsigned char* input) { + uint32_t val = (input[0] << 24) + (input[1] << 16) + (input[2] << 8) + input[3]; + + return val; +} diff --git a/common/utils.h b/common/utils.h new file mode 100644 index 0000000..42ccbd8 --- /dev/null +++ b/common/utils.h @@ -0,0 +1,3 @@ +#include + +uint32_t char_to_uint32(unsigned char *input); diff --git a/formats/img_png.c b/formats/img_png.c new file mode 100644 index 0000000..5b616fc --- /dev/null +++ b/formats/img_png.c @@ -0,0 +1,85 @@ +#include +#include +#include +#include +#include "img_png.h" +#include "common.h" + +#define BUFSIZE 1024 + +const unsigned char img_png_signature[] = {0x89, 'P', 'N', 'G', '\r', '\n', 0x1a, '\n'}; + + +int read_chunk(FILE *fp) { + struct img_png_chunk cur_chunk; + + // Read chunk length + unsigned char len[4]; + if(fread(len, sizeof(*len), 4, fp) < 4) { + fprintf(stderr, "Couldn\'t read chunk length.\n"); + exit(EXIT_FAILURE); + } + + cur_chunk.length = char_to_uint32(len); + printf("Chunk length: %lu\n", (unsigned long) cur_chunk.length); + + // Read chunk type + if(fread(cur_chunk.chunk_type, sizeof(*cur_chunk.chunk_type), 4, fp) < 4) { + fprintf(stderr, "Couldn\'t read chunk type.\n"); + exit(EXIT_FAILURE); + } + printf("Chunk type: %.*s\n", 4, cur_chunk.chunk_type); + + // Read chunk data + size_t chunk_size = cur_chunk.length / sizeof(unsigned char); + printf("Chunk size: %zu\n", chunk_size); + cur_chunk.chunk_data = malloc(chunk_size); + + if(!cur_chunk.chunk_data) { + perror("Failed to allocate chunk data!"); + exit(EXIT_FAILURE); + } + + if(fread(cur_chunk.chunk_data, 1, cur_chunk.length, fp) != cur_chunk.length) { + if(feof(fp)) { + fprintf(stderr, "File ended prematurely.\n"); + exit(EXIT_FAILURE); + } + fprintf(stderr, "Failed to read chunk data!\n"); + exit(EXIT_FAILURE); + } + + return feof(fp); +} + +uint8_t* img_png_decode(FILE *fp) { + unsigned char magic[8]; + + // Check PNG Magic + if(fread(magic, sizeof(*magic), 8, fp) < 8) { + fprintf(stderr, "Couldn\'t read PNG magic."); + exit(EXIT_FAILURE); + } + + if(memcmp(magic, img_png_signature, 8) != 0) { + fprintf(stderr, "Invalid PNG magic\n"); + exit(EXIT_FAILURE); + } + + printf("PNG Magic: %#04x%02x%02x%02x%02x%02x%02x%02x\n", magic[0], magic[1], magic[2], + magic[3], magic[4], magic[5], magic[6], magic[7]); + + struct img_png_chunk cur_chunk; + + // Read chunk + + while (read_chunk(fp) == 0); + + if(!feof(fp)) { + perror("fread() failed!"); + exit(EXIT_FAILURE); + } + + + return NULL; +} diff --git a/formats/img_png.h b/formats/img_png.h new file mode 100644 index 0000000..20fbb03 --- /dev/null +++ b/formats/img_png.h @@ -0,0 +1,12 @@ +#include +#include + + +struct img_png_chunk { + unsigned char* chunk_data; + uint32_t length; + uint32_t crc; + char chunk_type[4]; +}; + +uint8_t* img_png_decode (FILE* fp);