From 134b86727aba271174f9ea2599fcc927d282880e Mon Sep 17 00:00:00 2001 From: briandilley Date: Sat, 29 Mar 2025 23:02:00 -0700 Subject: [PATCH 1/2] Added support for memory based images, restructured the project for PlatformIO and other similar platforms (like Arduino) --- .gitignore | 6 - example.c => examples/example.c | 58 +++++- library.json | 20 ++ library.properties | 8 + gifdec.c => src/gifdec.c | 327 ++++++++++++++++++++------------ gifdec.h => src/gifdec.h | 27 +++ 6 files changed, 314 insertions(+), 132 deletions(-) delete mode 100644 .gitignore rename example.c => examples/example.c (76%) create mode 100644 library.json create mode 100644 library.properties rename gifdec.c => src/gifdec.c (61%) rename gifdec.h => src/gifdec.h (67%) diff --git a/.gitignore b/.gitignore deleted file mode 100644 index bf32229..0000000 --- a/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -* -!.gitignore -!README -!example.c -!gifdec.c -!gifdec.h diff --git a/example.c b/examples/example.c similarity index 76% rename from example.c rename to examples/example.c index f0b427e..81360e5 100644 --- a/example.c +++ b/examples/example.c @@ -27,16 +27,72 @@ main(int argc, char *argv[]) Uint32 pixel; int ret, paused, quit; Uint32 t0, t1, delay, delta; + FILE *file; + long file_size; + char *buffer; if (argc != 2) { fprintf(stderr, "usage:\n %s gif-file\n", argv[0]); return 1; } - gif = gd_open_gif(argv[1]); + + + // Open the file + file = fopen(argv[1], "rb"); + if (!file) { + perror("Failed to open file"); + return 1; + } + + // Get file size + fseek(file, 0, SEEK_END); + file_size = ftell(file); + fseek(file, 0, SEEK_SET); + + // Allocate memory for the file contents + buffer = (char *)malloc(file_size); + if (!buffer) { + fprintf(stderr, "Failed to allocate memory\n"); + fclose(file); + return 1; + } + + // Read file into memory + if (fread(buffer, 1, file_size, file) != file_size) { + fprintf(stderr, "Failed to read the entire file\n"); + free(buffer); + fclose(file); + return 1; + } + + fclose(file); + + fprintf(stderr, "File size: %ld\n", file_size); + gif = gd_open_gif_memory(buffer, file_size); if (!gif) { fprintf(stderr, "Could not open %s\n", argv[1]); return 1; } + + + gd_rewind(gif); + int frameCount = 0; + while (1) { + fprintf(stderr, "Loading frame %d\n", frameCount); + int f = gd_get_frame(gif); + if (f < 0) { + fprintf(stderr, "Unable to get frame: %d\n", frameCount); + return 1; + } else if (f == 0) { + fprintf(stderr, "End of file reached: %d\n", frameCount); + break; + } + frameCount++; + } + gd_rewind(gif); + + + frame = malloc(gif->width * gif->height * 3); if (!frame) { fprintf(stderr, "Could not allocate frame\n"); diff --git a/library.json b/library.json new file mode 100644 index 0000000..75291f8 --- /dev/null +++ b/library.json @@ -0,0 +1,20 @@ +{ + "name": "gifdec", + "version": "0.0.1", + "description": "This is a small C library that can be used to read GIF files.", + "homepage": "https://github.com/lecram/gifdec", + "frameworks": [ + "*" + ], + "platforms": "*", + "scripts": { + }, + "build": { + }, + "export": { + "include": + [ + ".h" + ] + } +} diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..4d41eb2 --- /dev/null +++ b/library.properties @@ -0,0 +1,8 @@ + +name=gifdec +version=0.0.1 +author=lecram +maintainer=lecram +sentence=This is a small C library that can be used to read GIF files. +category=Library +url=https://github.com/lecram/gifdec.git diff --git a/gifdec.c b/src/gifdec.c similarity index 61% rename from gifdec.c rename to src/gifdec.c index 83c2d0f..42396f5 100644 --- a/gifdec.c +++ b/src/gifdec.c @@ -16,6 +16,41 @@ #define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MAX(A, B) ((A) > (B) ? (A) : (B)) +// File based +static off_t gd_lseek_file(gd_GIF *gif, off_t offset, int whence) { + return lseek(gif->fd, offset, whence); +} + +static int gd_read_file(gd_GIF *gif, void *buf, size_t count) { + return read(gif->fd, buf, count); +} + +// Memory based +static off_t gd_lseek_memory(gd_GIF *gif, off_t offset, int whence) { + switch (whence) { + case SEEK_SET: + gif->gif_data_pos = MIN(MAX(0, offset), gif->gif_data_size); + break; + case SEEK_CUR: + gif->gif_data_pos = MIN(MAX(0, gif->gif_data_pos + offset), gif->gif_data_size); + break; + case SEEK_END: + gif->gif_data_pos = gif->gif_data_size; + break; + } + return gif->gif_data_pos; +} + +static int gd_read_memory(gd_GIF *gif, void *buf, size_t count) { + count = MIN(count, gif->gif_data_size - gif->gif_data_pos); + if (count == 0) { + return -1; + } + memcpy(buf, gif->gif_data + gif->gif_data_pos, count); + gif->gif_data_pos += count; + return count; +} + typedef struct Entry { uint16_t length; uint16_t prefix; @@ -29,92 +64,128 @@ typedef struct Table { } Table; static uint16_t -read_num(int fd) +read_num(gd_GIF *gif) { uint8_t bytes[2]; - read(fd, bytes, 2); + gif->gd_read(gif, bytes, 2); return bytes[0] + (((uint16_t) bytes[1]) << 8); } +static int gd_open_gif_impl(gd_GIF *gif) { + + uint8_t sigver[3]; + uint16_t width, height, depth; + uint8_t fdsz, bgidx, aspect; + int i; + uint8_t *bgcolor; + int gct_sz; + + /* Header */ + gif->gd_read(gif, sigver, 3); + if (memcmp(sigver, "GIF", 3) != 0) { + GD_LOG_ERROR("invalid signature"); + return -1; + } + /* Version */ + gif->gd_read(gif, sigver, 3); + if (memcmp(sigver, "89a", 3) != 0) { + GD_LOG_ERROR("invalid version"); + return -1; + } + /* Width x Height */ + width = read_num(gif); + height = read_num(gif); + /* FDSZ */ + gif->gd_read(gif, &fdsz, 1); + /* Presence of GCT */ + if (!(fdsz & 0x80)) { + GD_LOG_ERROR("no global color table"); + return -1; + } + /* Color Space's Depth */ + depth = ((fdsz >> 4) & 7) + 1; + /* Ignore Sort Flag. */ + /* GCT Size */ + gct_sz = 1 << ((fdsz & 0x07) + 1); + /* Background Color Index */ + gif->gd_read(gif, &bgidx, 1); + /* Aspect Ratio */ + gif->gd_read(gif, &aspect, 1); + /* Create gd_GIF Structure. */ + + gif->width = width; + gif->height = height; + gif->depth = depth; + /* Read GCT */ + gif->gct.size = gct_sz; + gif->gd_read(gif, gif->gct.colors, 3 * gif->gct.size); + gif->palette = &gif->gct; + gif->bgindex = bgidx; + gif->frame = (unsigned char*)GD_CALLOC(width * height, 4); + if (!gif->frame) { + GD_LOG_ERROR("Unable to allocate memory for frame buffer"); + return -1; + } + gif->canvas = &gif->frame[width * height]; + if (gif->bgindex) + memset(gif->frame, gif->bgindex, gif->width * gif->height); + bgcolor = &gif->palette->colors[gif->bgindex*3]; + if (bgcolor[0] || bgcolor[1] || bgcolor [2]) + for (i = 0; i < gif->width * gif->height; i++) + memcpy(&gif->canvas[i*3], bgcolor, 3); + gif->anim_start = gif->gd_lseek(gif, 0, SEEK_CUR); + return 0; +} + +gd_GIF *gd_open_gif_memory(const char *data, size_t size) { + gd_GIF *gif; + + gif = (gd_GIF*)GD_CALLOC(1, sizeof(*gif)); + if (!gif) { + GD_LOG_ERROR("Unable to allocate memory for gd_GIF"); + return 0; + } + + gif->gif_data = data; + gif->gif_data_size = size; + gif->gif_data_pos = 0; + gif->gd_lseek = gd_lseek_memory; + gif->gd_read = gd_read_memory; + + if (gd_open_gif_impl(gif) != 0) { + GD_FREE(gif); + return 0; + } + return gif; +} + gd_GIF * gd_open_gif(const char *fname) { - int fd; - uint8_t sigver[3]; - uint16_t width, height, depth; - uint8_t fdsz, bgidx, aspect; - int i; - uint8_t *bgcolor; - int gct_sz; gd_GIF *gif; + int fd; fd = open(fname, O_RDONLY); if (fd == -1) return NULL; #ifdef _WIN32 setmode(fd, O_BINARY); #endif - /* Header */ - read(fd, sigver, 3); - if (memcmp(sigver, "GIF", 3) != 0) { - fprintf(stderr, "invalid signature\n"); - goto fail; - } - /* Version */ - read(fd, sigver, 3); - if (memcmp(sigver, "89a", 3) != 0) { - fprintf(stderr, "invalid version\n"); - goto fail; + gif = (gd_GIF*)GD_CALLOC(1, sizeof(*gif)); + if (!gif) { + GD_LOG_ERROR("Unable to allocate memory for gd_GIF"); + return 0; } - /* Width x Height */ - width = read_num(fd); - height = read_num(fd); - /* FDSZ */ - read(fd, &fdsz, 1); - /* Presence of GCT */ - if (!(fdsz & 0x80)) { - fprintf(stderr, "no global color table\n"); - goto fail; - } - /* Color Space's Depth */ - depth = ((fdsz >> 4) & 7) + 1; - /* Ignore Sort Flag. */ - /* GCT Size */ - gct_sz = 1 << ((fdsz & 0x07) + 1); - /* Background Color Index */ - read(fd, &bgidx, 1); - /* Aspect Ratio */ - read(fd, &aspect, 1); - /* Create gd_GIF Structure. */ - gif = calloc(1, sizeof(*gif)); - if (!gif) goto fail; + gif->fd = fd; - gif->width = width; - gif->height = height; - gif->depth = depth; - /* Read GCT */ - gif->gct.size = gct_sz; - read(fd, gif->gct.colors, 3 * gif->gct.size); - gif->palette = &gif->gct; - gif->bgindex = bgidx; - gif->frame = calloc(4, width * height); - if (!gif->frame) { - free(gif); - goto fail; + gif->gd_lseek = gd_lseek_file; + gif->gd_read = gd_read_file; + + if (gd_open_gif_impl(gif) != 0) { + GD_FREE(gif); + close(fd); + return 0; } - gif->canvas = &gif->frame[width * height]; - if (gif->bgindex) - memset(gif->frame, gif->bgindex, gif->width * gif->height); - bgcolor = &gif->palette->colors[gif->bgindex*3]; - if (bgcolor[0] || bgcolor[1] || bgcolor [2]) - for (i = 0; i < gif->width * gif->height; i++) - memcpy(&gif->canvas[i*3], bgcolor, 3); - gif->anim_start = lseek(fd, 0, SEEK_CUR); - goto ok; -fail: - close(fd); - return 0; -ok: return gif; } @@ -124,8 +195,8 @@ discard_sub_blocks(gd_GIF *gif) uint8_t size; do { - read(gif->fd, &size, 1); - lseek(gif->fd, size, SEEK_CUR); + gif->gd_read(gif, &size, 1); + gif->gd_lseek(gif, size, SEEK_CUR); } while (size); } @@ -136,21 +207,21 @@ read_plain_text_ext(gd_GIF *gif) uint16_t tx, ty, tw, th; uint8_t cw, ch, fg, bg; off_t sub_block; - lseek(gif->fd, 1, SEEK_CUR); /* block size = 12 */ - tx = read_num(gif->fd); - ty = read_num(gif->fd); - tw = read_num(gif->fd); - th = read_num(gif->fd); - read(gif->fd, &cw, 1); - read(gif->fd, &ch, 1); - read(gif->fd, &fg, 1); - read(gif->fd, &bg, 1); - sub_block = lseek(gif->fd, 0, SEEK_CUR); + gif->gd_lseek(gif, 1, SEEK_CUR); /* block size = 12 */ + tx = read_num(gif); + ty = read_num(gif); + tw = read_num(gif); + th = read_num(gif); + gif->gd_read(gif, &cw, 1); + gif->gd_read(gif, &ch, 1); + gif->gd_read(gif, &fg, 1); + gif->gd_read(gif, &bg, 1); + sub_block = gif->gd_lseek(gif, 0, SEEK_CUR); gif->plain_text(gif, tx, ty, tw, th, cw, ch, fg, bg); - lseek(gif->fd, sub_block, SEEK_SET); + gif->gd_lseek(gif, sub_block, SEEK_SET); } else { /* Discard plain text metadata. */ - lseek(gif->fd, 13, SEEK_CUR); + gif->gd_lseek(gif, 13, SEEK_CUR); } /* Discard plain text sub-blocks. */ discard_sub_blocks(gif); @@ -162,24 +233,24 @@ read_graphic_control_ext(gd_GIF *gif) uint8_t rdit; /* Discard block size (always 0x04). */ - lseek(gif->fd, 1, SEEK_CUR); - read(gif->fd, &rdit, 1); + gif->gd_lseek(gif, 1, SEEK_CUR); + gif->gd_read(gif, &rdit, 1); gif->gce.disposal = (rdit >> 2) & 3; gif->gce.input = rdit & 2; gif->gce.transparency = rdit & 1; - gif->gce.delay = read_num(gif->fd); - read(gif->fd, &gif->gce.tindex, 1); + gif->gce.delay = read_num(gif); + gif->gd_read(gif, &gif->gce.tindex, 1); /* Skip block terminator. */ - lseek(gif->fd, 1, SEEK_CUR); + gif->gd_lseek(gif, 1, SEEK_CUR); } static void read_comment_ext(gd_GIF *gif) { if (gif->comment) { - off_t sub_block = lseek(gif->fd, 0, SEEK_CUR); + off_t sub_block = gif->gd_lseek(gif, 0, SEEK_CUR); gif->comment(gif); - lseek(gif->fd, sub_block, SEEK_SET); + gif->gd_lseek(gif, sub_block, SEEK_SET); } /* Discard comment sub-blocks. */ discard_sub_blocks(gif); @@ -192,21 +263,21 @@ read_application_ext(gd_GIF *gif) char app_auth_code[3]; /* Discard block size (always 0x0B). */ - lseek(gif->fd, 1, SEEK_CUR); + gif->gd_lseek(gif, 1, SEEK_CUR); /* Application Identifier. */ - read(gif->fd, app_id, 8); + gif->gd_read(gif, app_id, 8); /* Application Authentication Code. */ - read(gif->fd, app_auth_code, 3); + gif->gd_read(gif, app_auth_code, 3); if (!strncmp(app_id, "NETSCAPE", sizeof(app_id))) { /* Discard block size (0x03) and constant byte (0x01). */ - lseek(gif->fd, 2, SEEK_CUR); - gif->loop_count = read_num(gif->fd); + gif->gd_lseek(gif, 2, SEEK_CUR); + gif->loop_count = read_num(gif); /* Skip block terminator. */ - lseek(gif->fd, 1, SEEK_CUR); + gif->gd_lseek(gif, 1, SEEK_CUR); } else if (gif->application) { - off_t sub_block = lseek(gif->fd, 0, SEEK_CUR); + off_t sub_block = gif->gd_lseek(gif, 0, SEEK_CUR); gif->application(gif, app_id, app_auth_code); - lseek(gif->fd, sub_block, SEEK_SET); + gif->gd_lseek(gif, sub_block, SEEK_SET); discard_sub_blocks(gif); } else { discard_sub_blocks(gif); @@ -218,7 +289,7 @@ read_ext(gd_GIF *gif) { uint8_t label; - read(gif->fd, &label, 1); + gif->gd_read(gif, &label, 1); switch (label) { case 0x01: read_plain_text_ext(gif); @@ -233,7 +304,7 @@ read_ext(gd_GIF *gif) read_application_ext(gif); break; default: - fprintf(stderr, "unknown extension: %02X\n", label); + GD_LOG_ERROR("unknown extension: %02X", label); } } @@ -242,13 +313,15 @@ new_table(int key_size) { int key; int init_bulk = MAX(1 << (key_size + 1), 0x100); - Table *table = malloc(sizeof(*table) + sizeof(Entry) * init_bulk); + Table *table = (Table*)GD_MALLOC(sizeof(*table) + sizeof(Entry) * init_bulk); if (table) { table->bulk = init_bulk; table->nentries = (1 << key_size) + 2; table->entries = (Entry *) &table[1]; for (key = 0; key < (1 << key_size); key++) - table->entries[key] = (Entry) {1, 0xFFF, key}; + table->entries[key] = (Entry) {1, 0xFFF, (uint8_t)key}; + } else { + GD_LOG_ERROR("Unable to allocate memory for LZW code table"); } return table; } @@ -263,7 +336,7 @@ add_entry(Table **tablep, uint16_t length, uint16_t prefix, uint8_t suffix) Table *table = *tablep; if (table->nentries == table->bulk) { table->bulk *= 2; - table = realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk); + table = (Table*)realloc(table, sizeof(*table) + sizeof(Entry) * table->bulk); if (!table) return -1; table->entries = (Entry *) &table[1]; *tablep = table; @@ -289,11 +362,11 @@ get_key(gd_GIF *gif, int key_size, uint8_t *sub_len, uint8_t *shift, uint8_t *by if (rpad == 0) { /* Update byte. */ if (*sub_len == 0) { - read(gif->fd, sub_len, 1); /* Must be nonzero! */ + gif->gd_read(gif, sub_len, 1); /* Must be nonzero! */ if (*sub_len == 0) return 0x1000; } - read(gif->fd, byte, 1); + gif->gd_read(gif, byte, 1); (*sub_len)--; } frag_size = MIN(key_size - bits_read, 8 - rpad); @@ -333,23 +406,23 @@ static int read_image_data(gd_GIF *gif, int interlace) { uint8_t sub_len, shift, byte; - int init_key_size, key_size, table_is_full; - int frm_off, frm_size, str_len, i, p, x, y; + int init_key_size, key_size, table_is_full = 0; + int frm_off, frm_size, str_len = 0, i, p, x, y; uint16_t key, clear, stop; int ret; Table *table; - Entry entry; + Entry entry = {0, 0xFFF, 0}; off_t start, end; - read(gif->fd, &byte, 1); + gif->gd_read(gif, &byte, 1); key_size = (int) byte; if (key_size < 2 || key_size > 8) return -1; - start = lseek(gif->fd, 0, SEEK_CUR); + start = gif->gd_lseek(gif, 0, SEEK_CUR); discard_sub_blocks(gif); - end = lseek(gif->fd, 0, SEEK_CUR); - lseek(gif->fd, start, SEEK_SET); + end = gif->gd_lseek(gif, 0, SEEK_CUR); + gif->gd_lseek(gif, start, SEEK_SET); clear = 1 << key_size; stop = clear + 1; table = new_table(key_size); @@ -368,7 +441,7 @@ read_image_data(gd_GIF *gif, int interlace) } else if (!table_is_full) { ret = add_entry(&table, str_len + 1, key, entry.suffix); if (ret == -1) { - free(table); + GD_FREE(table); return -1; } if (table->nentries == 0x1000) { @@ -398,10 +471,10 @@ read_image_data(gd_GIF *gif, int interlace) if (key < table->nentries - 1 && !table_is_full) table->entries[table->nentries - 1].suffix = entry.suffix; } - free(table); + GD_FREE(table); if (key == stop) - read(gif->fd, &sub_len, 1); /* Must be zero! */ - lseek(gif->fd, end, SEEK_SET); + gif->gd_read(gif, &sub_len, 1); /* Must be zero! */ + gif->gd_lseek(gif, end, SEEK_SET); return 0; } @@ -414,26 +487,26 @@ read_image(gd_GIF *gif) int interlace; /* Image Descriptor. */ - gif->fx = read_num(gif->fd); - gif->fy = read_num(gif->fd); + gif->fx = read_num(gif); + gif->fy = read_num(gif); if (gif->fx >= gif->width || gif->fy >= gif->height) return -1; - gif->fw = read_num(gif->fd); - gif->fh = read_num(gif->fd); + gif->fw = read_num(gif); + gif->fh = read_num(gif); gif->fw = MIN(gif->fw, gif->width - gif->fx); gif->fh = MIN(gif->fh, gif->height - gif->fy); - read(gif->fd, &fisrz, 1); + gif->gd_read(gif, &fisrz, 1); interlace = fisrz & 0x40; /* Ignore Sort Flag. */ /* Local Color Table? */ if (fisrz & 0x80) { /* Read LCT */ gif->lct.size = 1 << ((fisrz & 0x07) + 1); - read(gif->fd, gif->lct.colors, 3 * gif->lct.size); + gif->gd_read(gif, gif->lct.colors, 3 * gif->lct.size); gif->palette = &gif->lct; } else gif->palette = &gif->gct; @@ -488,14 +561,14 @@ gd_get_frame(gd_GIF *gif) char sep; dispose(gif); - read(gif->fd, &sep, 1); + gif->gd_read(gif, &sep, 1); while (sep != ',') { if (sep == ';') return 0; if (sep == '!') read_ext(gif); else return -1; - read(gif->fd, &sep, 1); + gif->gd_read(gif, &sep, 1); } if (read_image(gif) == -1) return -1; @@ -518,13 +591,17 @@ gd_is_bgcolor(gd_GIF *gif, uint8_t color[3]) void gd_rewind(gd_GIF *gif) { - lseek(gif->fd, gif->anim_start, SEEK_SET); + gif->gd_lseek(gif, gif->anim_start, SEEK_SET); } void gd_close_gif(gd_GIF *gif) { + if (gif->fd != -1) { close(gif->fd); - free(gif->frame); - free(gif); + } + if (gif->frame) { + GD_FREE(gif->frame); + } + GD_FREE(gif); } diff --git a/gifdec.h b/src/gifdec.h similarity index 67% rename from gifdec.h rename to src/gifdec.h index 2bbc9f5..f32db8d 100644 --- a/gifdec.h +++ b/src/gifdec.h @@ -4,6 +4,22 @@ #include #include +#ifndef GD_CALLOC +#define GD_CALLOC(n, s) calloc(n, s) +#endif + +#ifndef GD_FREE +#define GD_FREE(p) free(p) +#endif + +#ifndef GD_MALLOC +#define GD_MALLOC(s) malloc(s) +#endif + +#ifndef GD_LOG_ERROR +#define GD_LOG_ERROR(f, ...) fprintf(stderr, f "\n", ##__VA_ARGS__) +#endif + #ifdef __cplusplus extern "C" { #endif @@ -22,7 +38,14 @@ typedef struct gd_GCE { } gd_GCE; typedef struct gd_GIF { + // file based int fd; + + // memory based + const char* gif_data; + size_t gif_data_size; + off_t gif_data_pos; + off_t anim_start; uint16_t width, height; uint16_t depth; @@ -40,9 +63,13 @@ typedef struct gd_GIF { uint16_t fx, fy, fw, fh; uint8_t bgindex; uint8_t *canvas, *frame; + + off_t (*gd_lseek)(struct gd_GIF *gif, off_t offset, int whence); + int (*gd_read)(struct gd_GIF *gif, void *__buf, size_t __nbyte); } gd_GIF; gd_GIF *gd_open_gif(const char *fname); +gd_GIF *gd_open_gif_memory(const char *data, size_t size); int gd_get_frame(gd_GIF *gif); void gd_render_frame(gd_GIF *gif, uint8_t *buffer); int gd_is_bgcolor(gd_GIF *gif, uint8_t color[3]); From 00434c18d457b6098ec27763cd3aa40f3cb0633e Mon Sep 17 00:00:00 2001 From: briandilley Date: Tue, 15 Apr 2025 10:14:13 -0700 Subject: [PATCH 2/2] better error reporting --- src/gifdec.c | 15 ++++++++------- src/gifdec.h | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/gifdec.c b/src/gifdec.c index 42396f5..95c69ed 100644 --- a/src/gifdec.c +++ b/src/gifdec.c @@ -321,7 +321,7 @@ new_table(int key_size) for (key = 0; key < (1 << key_size); key++) table->entries[key] = (Entry) {1, 0xFFF, (uint8_t)key}; } else { - GD_LOG_ERROR("Unable to allocate memory for LZW code table"); + GD_LOG_ERROR("Unable to allocate memory for LZW code table: %d %p", (sizeof(*table) + sizeof(Entry) * init_bulk), table); } return table; } @@ -426,6 +426,9 @@ read_image_data(gd_GIF *gif, int interlace) clear = 1 << key_size; stop = clear + 1; table = new_table(key_size); + if (!table) { + return -1; + } key_size++; init_key_size = key_size; sub_len = shift = 0; @@ -582,16 +585,14 @@ gd_render_frame(gd_GIF *gif, uint8_t *buffer) render_frame_rect(gif, buffer); } -int -gd_is_bgcolor(gd_GIF *gif, uint8_t color[3]) -{ - return !memcmp(&gif->palette->colors[gif->bgindex*3], color, 3); +int gd_is_bgcolor(gd_GIF *gif, uint8_t color[3]) { + return !memcmp(&gif->palette->colors[gif->bgindex * 3], color, 3); } -void +off_t gd_rewind(gd_GIF *gif) { - gif->gd_lseek(gif, gif->anim_start, SEEK_SET); + return gif->gd_lseek(gif, gif->anim_start, SEEK_SET); } void diff --git a/src/gifdec.h b/src/gifdec.h index f32db8d..bede778 100644 --- a/src/gifdec.h +++ b/src/gifdec.h @@ -73,7 +73,7 @@ gd_GIF *gd_open_gif_memory(const char *data, size_t size); int gd_get_frame(gd_GIF *gif); void gd_render_frame(gd_GIF *gif, uint8_t *buffer); int gd_is_bgcolor(gd_GIF *gif, uint8_t color[3]); -void gd_rewind(gd_GIF *gif); +off_t gd_rewind(gd_GIF *gif); void gd_close_gif(gd_GIF *gif); #ifdef __cplusplus