From ff11942fb7abfc68e2f04350f7d0a2dde51b1d9e Mon Sep 17 00:00:00 2001 From: Clement Sibille Date: Sun, 9 Jun 2024 18:08:51 +0900 Subject: Make LisPng_decode use a u8* instead of a FILE* --- cross/playdate.txt | 3 +++ lisiblepng-bin/src/main.c | 24 ++++++++++++++---------- lisiblepng/src/lisiblepng.c | 45 ++++++++++++++++++++++++++++----------------- lisiblepng/src/lisiblepng.h | 8 ++++---- 4 files changed, 49 insertions(+), 31 deletions(-) diff --git a/cross/playdate.txt b/cross/playdate.txt index c54b4ba..c843775 100644 --- a/cross/playdate.txt +++ b/cross/playdate.txt @@ -9,3 +9,6 @@ system = 'none' cpu_family = 'arm' cpu = 'cortex-m7' endian = 'little' + +[properties] +is_playdate_build = true diff --git a/lisiblepng-bin/src/main.c b/lisiblepng-bin/src/main.c index 47e1722..116125a 100644 --- a/lisiblepng-bin/src/main.c +++ b/lisiblepng-bin/src/main.c @@ -1,8 +1,12 @@ #include +#include #include #include #include +#include #include +#include +#include #define LOG0(msg) fprintf(stderr, msg "\n") #define LOGN(fmt, ...) fprintf(stderr, fmt "\n", __VA_ARGS__) @@ -15,19 +19,19 @@ int main(int argc, char **argv) { } const char *png_filepath = argv[1]; - FILE *png_file = fopen(png_filepath, "r"); - fseek(png_file, 0, SEEK_END); - long file_size = ftell(png_file); - LOGN("File size: %ld bytes", file_size); - fseek(png_file, 0, SEEK_SET); + int fd = open(png_filepath, O_RDONLY); + struct stat st; + fstat(fd, &st); + u8 *png_file_data = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + LOGN("File size: %ld bytes", st.st_size); - if (!png_file) { + if (!png_file_data) { const char *error_message = strerror(errno); - LOGN("Couldn't open PNG file: %s", error_message); + LOGN("Couldn't map PNG file: %s", error_message); return 1; } - LisPng *png = LisPng_decode(png_file); + LisPng *png = LisPng_decode(png_file_data, st.st_size); if (!png) { LOG0("Couldn't decode PNG"); return 1; @@ -36,9 +40,9 @@ int main(int argc, char **argv) { LisPng_dump_ppm(png); LisPng_destroy(png); - if (fclose(png_file) != 0) { + if (munmap(png_file_data, st.st_size) != 0) { const char *error_message = strerror(errno); - LOGN("Couldn't close PNG file: %s", error_message); + LOGN("Couldn't unmap PNG file: %s", error_message); return 1; } diff --git a/lisiblepng/src/lisiblepng.c b/lisiblepng/src/lisiblepng.c index de6f06e..ead4107 100644 --- a/lisiblepng/src/lisiblepng.c +++ b/lisiblepng/src/lisiblepng.c @@ -1,12 +1,8 @@ #include "lisiblepng.h" #include "lisiblepng/deflate.h" -#include #include #include -#include -#include -#include -#include +#include #include #define PNG_SIGNATURE_LENGTH 8 @@ -120,16 +116,21 @@ uint8_t LisPngColourType_sample_count(const LisPngColourType colour_type) { } } typedef struct { - FILE *stream; + const u8 *image_data; + size_t image_data_size; + size_t current_offset; #ifdef LPNG_COMPUTE_CRC uint32_t computed_crc; #endif // LPNG_COMPUTE_CRC } DeflateDecompressor; -void DeflateDecompressor_init(DeflateDecompressor *ctx, FILE *stream) { +void DeflateDecompressor_init(DeflateDecompressor *ctx, const u8 *image_data, + usize image_data_size) { LSTD_ASSERT(ctx != NULL); - LSTD_ASSERT(stream != NULL); - ctx->stream = stream; + LSTD_ASSERT(image_data != NULL); + ctx->current_offset = 0; + ctx->image_data = image_data; + ctx->image_data_size = image_data_size; #ifdef LPNG_COMPUTE_CRC ctx->computed_crc = 0xFFFFFFFFu; #endif // LPNG_COMPUTE_CRC @@ -151,13 +152,19 @@ uint32_t ParsingContext_computed_crc(DeflateDecompressor *ctx) { long ParsingContext_cursor_position(DeflateDecompressor *ctx) { LSTD_ASSERT(ctx != NULL); - return ftell(ctx->stream); + return ctx->current_offset; } bool ParsingContext_skip_bytes(DeflateDecompressor *ctx, size_t byte_count) { LSTD_ASSERT(ctx != NULL); - if (fseek(ctx->stream, byte_count, SEEK_CUR) != 0) { - LOG_ERROR("Couldn't skip bytes: %s", strerror(errno)); + const size_t previous_offset = ctx->current_offset; + ctx->current_offset += byte_count; + if (ctx->current_offset > ctx->image_data_size) { + LOG_ERROR("current offset > image data size"); + return false; + } + if (ctx->current_offset < previous_offset) { + LOG_ERROR("current offset overflowed"); return false; } @@ -168,9 +175,13 @@ bool ParsingContext_parse_bytes(DeflateDecompressor *ctx, size_t byte_count, uint8_t *output_buffer) { LSTD_ASSERT(ctx != NULL); LSTD_ASSERT(output_buffer != NULL); - if (fread(output_buffer, 1, byte_count, ctx->stream) < byte_count) { - LOG_ERROR("Couldn't parse bytes, EOF reached"); - return false; + + for (size_t i = 0; i < byte_count; i++) { + output_buffer[i] = ctx->image_data[ctx->current_offset++]; + if (ctx->current_offset > ctx->image_data_size) { + LOG_ERROR("Couldn't parse bytes, EOF reached"); + return false; + } } #ifdef LPNG_COMPUTE_CRC @@ -477,11 +488,11 @@ void apply_reconstruction_functions(LisPng *image, } } -LisPng *LisPng_decode(FILE *stream) { +LisPng *LisPng_decode(const u8 *image_bytes, usize image_bytes_length) { LisPng *png = malloc(sizeof(LisPng)); DeflateDecompressor ctx; - DeflateDecompressor_init(&ctx, stream); + DeflateDecompressor_init(&ctx, image_bytes, image_bytes_length); uint8_t parsed_png_signature[PNG_SIGNATURE_LENGTH]; if (!ParsingContext_parse_bytes(&ctx, PNG_SIGNATURE_LENGTH, parsed_png_signature)) { diff --git a/lisiblepng/src/lisiblepng.h b/lisiblepng/src/lisiblepng.h index e7f94ec..5d4bb44 100644 --- a/lisiblepng/src/lisiblepng.h +++ b/lisiblepng/src/lisiblepng.h @@ -1,8 +1,7 @@ #ifndef LISIBLE_PNG_H #define LISIBLE_PNG_H -#include -#include +#include typedef enum { LisPngColourType_Greyscale = 0, @@ -19,11 +18,12 @@ typedef struct LisPng LisPng; /// Parses the provided PNG stream /// -/// @param stream The PNG stream +/// @param image_bytes The image data +/// @param image_bytes_length The size of the image data /// @returns The parsed PNG as a Png struct pointer or NULL if an error occured. /// The returned PNG is owned by the caller and must be destroyed with /// Png_destroy. -LisPng *LisPng_decode(FILE *stream); +LisPng *LisPng_decode(const u8 *image_bytes, usize image_bytes_length); /// Writes the PNG image data as RGBA8 data to a buffer /// -- cgit v1.2.3