Gitweb links:

...log 
http://git.netsurf-browser.org/libnsgif.git/shortlog/a1c436270011cb3770f3d74bf08347289feb1273
...commit 
http://git.netsurf-browser.org/libnsgif.git/commit/a1c436270011cb3770f3d74bf08347289feb1273
...tree 
http://git.netsurf-browser.org/libnsgif.git/tree/a1c436270011cb3770f3d74bf08347289feb1273

The branch, master has been updated
       via  a1c436270011cb3770f3d74bf08347289feb1273 (commit)
       via  03a6a3a8a7b2481e7357a2563be30a98c174f5bb (commit)
       via  c52794486f394b52a5216ccbcca3fd0604cdca9d (commit)
       via  0e1ce8d71d6606640199e914b2c63482f044639c (commit)
       via  8966288ad6f9fecf92fb77e794d5c2cb6abddc18 (commit)
       via  7a200a82b014c404b3b205bfd62155655e4c4c90 (commit)
       via  4f588e9400eb82efac9c8c9fa6844419c2caa101 (commit)
       via  5a1c0ed3ba4534957965839fda659482603117e2 (commit)
       via  50b3f3b46903281c5507786b5f65118dca5139a5 (commit)
       via  76cc3a8ae804d398816ab9454731948f0ecb4c70 (commit)
       via  2b93687087490cb5e760405709961a9abf8e205b (commit)
       via  bdb312737d57497db67dda2543c7ea8b62315d0a (commit)
      from  c40d6f536473c4ee5fd310b50697ac7d0816d6e5 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=a1c436270011cb3770f3d74bf08347289feb1273
commit a1c436270011cb3770f3d74bf08347289feb1273
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Test: Ensure we can still loop GIFs with a loop count limit.

diff --git a/test/nsgif.c b/test/nsgif.c
index 6abd985..4a9e31c 100644
--- a/test/nsgif.c
+++ b/test/nsgif.c
@@ -391,6 +391,9 @@ int main(int argc, char *argv[])
 
        for (uint64_t i = 0; i < nsgif_options.loops; i++) {
                decode(ppm, nsgif_options.file, gif, i == 0);
+
+               /* We want to ignore any loop limit in the GIF. */
+               nsgif_reset(gif);
        }
 
        if (ppm != NULL) {


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=03a6a3a8a7b2481e7357a2563be30a98c174f5bb
commit 03a6a3a8a7b2481e7357a2563be30a98c174f5bb
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Test: Only generate output on first loop.
    
    The multiple loops feature is for decode performance testing and
    it makes no sense to generate output more than once.

diff --git a/test/nsgif.c b/test/nsgif.c
index aa66706..6abd985 100644
--- a/test/nsgif.c
+++ b/test/nsgif.c
@@ -250,7 +250,7 @@ static bool save_local_palette(const nsgif_t *gif, uint32_t 
frame)
        return save_palette(nsgif_options.file, filename, table, entries);
 }
 
-static void decode(FILE* ppm, const char *name, nsgif_t *gif)
+static void decode(FILE* ppm, const char *name, nsgif_t *gif, bool first)
 {
        nsgif_error err;
        uint32_t frame_prev = 0;
@@ -258,7 +258,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
 
        info = nsgif_get_info(gif);
 
-       if (ppm != NULL) {
+       if (first && ppm != NULL) {
                fprintf(ppm, "P3\n");
                fprintf(ppm, "# %s\n", name);
                fprintf(ppm, "# width                %u \n", info->width);
@@ -269,10 +269,10 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                                info->height * info->frame_count);
        }
 
-       if (nsgif_options.info == true) {
+       if (first && nsgif_options.info) {
                print_gif_info(info);
        }
-       if (nsgif_options.palette == true && info->global_palette == true) {
+       if (first && nsgif_options.palette && info->global_palette) {
                save_global_palette(gif);
        }
 
@@ -298,7 +298,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                }
                frame_prev = frame_new;
 
-               if (nsgif_options.info == true) {
+               if (first && nsgif_options.info) {
                        const nsgif_frame_info_t *f_info;
 
                        f_info = nsgif_get_frame_info(gif, frame_new);
@@ -306,7 +306,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                                print_gif_frame_info(f_info, frame_new);
                        }
                }
-               if (nsgif_options.palette == true) {
+               if (first && nsgif_options.palette) {
                        save_local_palette(gif, frame_new);
                }
 
@@ -317,7 +317,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                                        frame_new, nsgif_strerror(err));
                        /* Continue decoding the rest of the frames. */
 
-               } else if (ppm != NULL) {
+               } else if (first && ppm != NULL) {
                        fprintf(ppm, "# frame %u:\n", frame_new);
                        image = (const uint8_t *) bitmap;
                        for (uint32_t y = 0; y != info->height; y++) {
@@ -390,7 +390,7 @@ int main(int argc, char *argv[])
        }
 
        for (uint64_t i = 0; i < nsgif_options.loops; i++) {
-               decode((i == 0) ? ppm : NULL, nsgif_options.file, gif);
+               decode(ppm, nsgif_options.file, gif, i == 0);
        }
 
        if (ppm != NULL) {


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=c52794486f394b52a5216ccbcca3fd0604cdca9d
commit c52794486f394b52a5216ccbcca3fd0604cdca9d
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    API: Replace colour_table with {global|local}_palette.
    
    Avoiding use of "colour" because of different spelling in US.

diff --git a/include/nsgif.h b/include/nsgif.h
index 2251060..208bc27 100644
--- a/include/nsgif.h
+++ b/include/nsgif.h
@@ -364,7 +364,7 @@ typedef struct nsgif_info {
        /** background colour in same pixel format as \ref nsgif_bitmap_t. */
        uint32_t background;
        /** whether the GIF has a global colour table */
-       bool colour_table;
+       bool global_palette;
 } nsgif_info_t;
 
 /**
@@ -398,7 +398,7 @@ typedef struct nsgif_frame_info {
        /** whether the frame may have transparency */
        bool transparency;
        /** whether the frame has a local colour table */
-       bool colour_table;
+       bool local_palette;
 
        /** Disposal method for previous frame; affects plotting */
        uint8_t disposal;
diff --git a/src/gif.c b/src/gif.c
index 7f1d4c8..d2b6054 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -1149,7 +1149,7 @@ static nsgif_error nsgif__parse_colour_table(
        if (decode) {
                gif->colour_table = gif->local_colour_table;
        } else {
-               frame->info.colour_table = true;
+               frame->info.local_palette = true;
        }
 
        return NSGIF_OK;
@@ -1260,7 +1260,7 @@ static struct nsgif_frame *nsgif__get_frame(
 
                frame->transparency_index = NSGIF_NO_TRANSPARENCY;
                frame->frame_offset = gif->buf_pos;
-               frame->info.colour_table = false;
+               frame->info.local_palette = false;
                frame->info.transparency = false;
                frame->redraw_required = false;
                frame->info.display = false;
@@ -1573,7 +1573,7 @@ static nsgif_error nsgif__parse_logical_screen_descriptor(
 
        gif->info.width = data[0] | (data[1] << 8);
        gif->info.height = data[2] | (data[3] << 8);
-       gif->info.colour_table = data[4] & NSGIF_COLOUR_TABLE_MASK;
+       gif->info.global_palette = data[4] & NSGIF_COLOUR_TABLE_MASK;
        gif->colour_table_size = 2 << (data[4] & NSGIF_COLOUR_TABLE_SIZE_MASK);
        gif->bg_index = data[5];
        gif->aspect_ratio = data[6];
@@ -1667,7 +1667,7 @@ nsgif_error nsgif_data_scan(
         */
        if (gif->global_colour_table[0] == NSGIF_PROCESS_COLOURS) {
                /* Check for a global colour map signified by bit 7 */
-               if (gif->info.colour_table) {
+               if (gif->info.global_palette) {
                        size_t remaining = gif->buf + gif->buf_len - nsgif_data;
                        size_t used;
 
@@ -1704,7 +1704,7 @@ nsgif_error nsgif_data_scan(
                        gif->colour_table_size = 2;
                }
 
-               if (gif->info.colour_table &&
+               if (gif->info.global_palette &&
                    gif->bg_index < gif->colour_table_size) {
                        size_t bg_idx = gif->bg_index;
                        gif->info.background = gif->global_colour_table[bg_idx];
@@ -1964,7 +1964,7 @@ bool nsgif_local_palette(
        }
 
        f = &gif->frames[frame];
-       if (f->info.colour_table == false) {
+       if (f->info.local_palette == false) {
                return false;
        }
 
diff --git a/test/nsgif.c b/test/nsgif.c
index 7f1cc55..aa66706 100644
--- a/test/nsgif.c
+++ b/test/nsgif.c
@@ -150,8 +150,7 @@ static void print_gif_info(const nsgif_info_t *info)
        fprintf(stdout, "  height: %"PRIu32"\n", info->height);
        fprintf(stdout, "  max-loops: %"PRIu32"\n", info->loop_max);
        fprintf(stdout, "  frame-count: %"PRIu32"\n", info->frame_count);
-       fprintf(stdout, "  global colour table: %s\n",
-                       info->colour_table ? "yes" : "no");
+       fprintf(stdout, "  global palette: %s\n", info->global_palette ? "yes" 
: "no");
        fprintf(stdout, "  background:\n");
        fprintf(stdout, "    red: 0x%"PRIx8"\n", bg[0]);
        fprintf(stdout, "    green: 0x%"PRIx8"\n", bg[1]);
@@ -164,7 +163,7 @@ static void print_gif_frame_info(const nsgif_frame_info_t 
*info, uint32_t i)
        const char *disposal = nsgif_str_disposal(info->disposal);
 
        fprintf(stdout, "  - frame: %"PRIu32"\n", i);
-       fprintf(stdout, "    local colour table: %s\n", info->colour_table ? 
"yes" : "no");
+       fprintf(stdout, "    local palette: %s\n", info->local_palette ? "yes" 
: "no");
        fprintf(stdout, "    disposal-method: %s\n", disposal);
        fprintf(stdout, "    transparency: %s\n", info->transparency ? "yes" : 
"no");
        fprintf(stdout, "    display: %s\n", info->display ? "yes" : "no");
@@ -273,7 +272,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
        if (nsgif_options.info == true) {
                print_gif_info(info);
        }
-       if (nsgif_options.palette == true && info->colour_table == true) {
+       if (nsgif_options.palette == true && info->global_palette == true) {
                save_global_palette(gif);
        }
 


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=0e1ce8d71d6606640199e914b2c63482f044639c
commit 0e1ce8d71d6606640199e914b2c63482f044639c
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    GIF: Rename frame_pointer to frame_offset.

diff --git a/src/gif.c b/src/gif.c
index 09bacdc..7f1d4c8 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -32,7 +32,7 @@ typedef struct nsgif_frame {
        struct nsgif_frame_info info;
 
        /** offset (in bytes) to the GIF frame data */
-       uint32_t frame_pointer;
+       uint32_t frame_offset;
        /** whether the frame has previously been decoded. */
        bool decoded;
        /** whether the frame is totally opaque */
@@ -1259,7 +1259,7 @@ static struct nsgif_frame *nsgif__get_frame(
                frame = &gif->frames[frame_idx];
 
                frame->transparency_index = NSGIF_NO_TRANSPARENCY;
-               frame->frame_pointer = gif->buf_pos;
+               frame->frame_offset = gif->buf_pos;
                frame->info.colour_table = false;
                frame->info.transparency = false;
                frame->redraw_required = false;
@@ -1298,7 +1298,7 @@ static nsgif_error nsgif__process_frame(
        end = gif->buf + gif->buf_len;
 
        if (decode) {
-               pos = gif->buf + frame->frame_pointer;
+               pos = gif->buf + frame->frame_offset;
 
                /* Ensure this frame is supposed to be decoded */
                if (frame->info.display == false) {


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=8966288ad6f9fecf92fb77e794d5c2cb6abddc18
commit 8966288ad6f9fecf92fb77e794d5c2cb6abddc18
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Test: Allow local palettes to be saved as an image.

diff --git a/test/nsgif.c b/test/nsgif.c
index 17fb596..7f1cc55 100644
--- a/test/nsgif.c
+++ b/test/nsgif.c
@@ -235,6 +235,22 @@ static bool save_global_palette(const nsgif_t *gif)
                        table, entries);
 }
 
+static bool save_local_palette(const nsgif_t *gif, uint32_t frame)
+{
+       static uint32_t table[NSGIF_MAX_COLOURS];
+       char filename[64];
+       size_t entries;
+
+       snprintf(filename, sizeof(filename), "local-palette-%"PRIu32".ppm",
+                       frame);
+
+       if (!nsgif_local_palette(gif, frame, table, &entries)) {
+               return false;
+       }
+
+       return save_palette(nsgif_options.file, filename, table, entries);
+}
+
 static void decode(FILE* ppm, const char *name, nsgif_t *gif)
 {
        nsgif_error err;
@@ -291,6 +307,9 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                                print_gif_frame_info(f_info, frame_new);
                        }
                }
+               if (nsgif_options.palette == true) {
+                       save_local_palette(gif, frame_new);
+               }
 
                err = nsgif_frame_decode(gif, frame_new, &bitmap);
                if (err != NSGIF_OK) {


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=7a200a82b014c404b3b205bfd62155655e4c4c90
commit 7a200a82b014c404b3b205bfd62155655e4c4c90
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Test: Allow the global palette to be saved as an image.

diff --git a/test/nsgif.c b/test/nsgif.c
index a87ab69..17fb596 100644
--- a/test/nsgif.c
+++ b/test/nsgif.c
@@ -27,6 +27,7 @@ static struct nsgif_options {
        const char *file;
        const char *ppm;
        uint64_t loops;
+       bool palette;
        bool info;
 } nsgif_options;
 
@@ -54,6 +55,13 @@ static const struct cli_table_entry cli_entries[] = {
                     "The default is 1."
        },
        {
+               .s = 'p',
+               .l = "palette",
+               .t = CLI_BOOL,
+               .v.b = &nsgif_options.palette,
+               .d = "Save palette images."
+       },
+       {
                .p = true,
                .l = "FILE",
                .t = CLI_STRING,
@@ -168,6 +176,65 @@ static void print_gif_frame_info(const nsgif_frame_info_t 
*info, uint32_t i)
        fprintf(stdout, "      h: %"PRIu32"\n", info->rect.y1 - info->rect.y0);
 }
 
+static bool save_palette(
+               const char *img_filename,
+               const char *palette_filename,
+               const uint32_t palette[NSGIF_MAX_COLOURS],
+               size_t used_entries)
+{
+       enum {
+               SIZE = 32,
+               COUNT = 16,
+       };
+       FILE *f;
+       int size = COUNT * SIZE + 1;
+
+       f = fopen(palette_filename, "w+");
+       if (f == NULL) {
+               fprintf(stderr, "Unable to open %s for writing\n",
+                               palette_filename);
+               return false;
+       }
+
+       fprintf(f, "P3\n");
+       fprintf(f, "# %s: %s\n", img_filename, palette_filename);
+       fprintf(f, "# Colour count: %zu\n", used_entries);
+       fprintf(f, "%u %u 256\n", size, size);
+
+       for (int y = 0; y < size; y++) {
+               for (int x = 0; x < size; x++) {
+                       if (x % SIZE == 0 || y % SIZE == 0) {
+                               fprintf(f, "0 0 0 ");
+                       } else {
+                               size_t offset = y / SIZE * COUNT + x / SIZE;
+                               uint8_t *entry = (uint8_t *)&palette[offset];
+
+                               fprintf(f, "%u %u %u ",
+                                               entry[0],
+                                               entry[1],
+                                               entry[2]);
+                       }
+               }
+
+               fprintf(f, "\n");
+       }
+
+       fclose(f);
+
+       return true;
+}
+
+static bool save_global_palette(const nsgif_t *gif)
+{
+       uint32_t table[NSGIF_MAX_COLOURS];
+       size_t entries;
+
+       nsgif_global_palette(gif, table, &entries);
+
+       return save_palette(nsgif_options.file, "global-palette.ppm",
+                       table, entries);
+}
+
 static void decode(FILE* ppm, const char *name, nsgif_t *gif)
 {
        nsgif_error err;
@@ -190,6 +257,9 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
        if (nsgif_options.info == true) {
                print_gif_info(info);
        }
+       if (nsgif_options.palette == true && info->colour_table == true) {
+               save_global_palette(gif);
+       }
 
        /* decode the frames */
        while (true) {


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=4f588e9400eb82efac9c8c9fa6844419c2caa101
commit 4f588e9400eb82efac9c8c9fa6844419c2caa101
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    API: Add function to get a frame's local palette.

diff --git a/include/nsgif.h b/include/nsgif.h
index 9eec0f8..2251060 100644
--- a/include/nsgif.h
+++ b/include/nsgif.h
@@ -448,6 +448,26 @@ void nsgif_global_palette(
                size_t *entries);
 
 /**
+ * Get the local colour palette for a frame.
+ *
+ * Frames may have no local palette. In this case they use the global palette.
+ * This function returns false if the frame has no local palette.
+ *
+ * Colours in same pixel format as \ref nsgif_bitmap_t.
+ *
+ * \param[in]  gif      The \ref nsgif_t object.
+ * \param[in]  frame    The \ref frame to get the palette for.
+ * \param[out] table    Client buffer to hold the colour table.
+ * \param[out] entries  The number of used entries in the colour table.
+ * \return true if a palette is returned, false otherwise.
+ */
+bool nsgif_local_palette(
+               const nsgif_t *gif,
+               uint32_t frame,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries);
+
+/**
  * Configure handling of small frame delays.
  *
  * Historically people created GIFs with a tiny frame delay, however the slow
diff --git a/src/gif.c b/src/gif.c
index 7f960d1..09bacdc 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -1951,6 +1951,31 @@ void nsgif_global_palette(
 }
 
 /* exported function documented in nsgif.h */
+bool nsgif_local_palette(
+               const nsgif_t *gif,
+               uint32_t frame,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries)
+{
+       const nsgif_frame *f;
+
+       if (frame >= gif->frame_count_partial) {
+               return false;
+       }
+
+       f = &gif->frames[frame];
+       if (f->info.colour_table == false) {
+               return false;
+       }
+
+       *entries = 2 << (f->flags & NSGIF_COLOUR_TABLE_SIZE_MASK);
+       nsgif__colour_table_decode(table, &gif->colour_layout,
+                       *entries, gif->buf + f->colour_table_offset);
+
+       return true;
+}
+
+/* exported function documented in nsgif.h */
 const char *nsgif_strerror(nsgif_error err)
 {
        static const char *const str[] = {


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=5a1c0ed3ba4534957965839fda659482603117e2
commit 5a1c0ed3ba4534957965839fda659482603117e2
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    GIF: Store frame palette offset.

diff --git a/src/gif.c b/src/gif.c
index e9048f9..7f960d1 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -43,6 +43,9 @@ typedef struct nsgif_frame {
        /** the index designating a transparent pixel */
        uint32_t transparency_index;
 
+       /** offset to frame colour table */
+       uint32_t colour_table_offset;
+
        /* Frame flags */
        uint32_t flags;
 } nsgif_frame;
@@ -1130,6 +1133,10 @@ static nsgif_error nsgif__parse_colour_table(
                return NSGIF_OK;
        }
 
+       if (decode == false) {
+               frame->colour_table_offset = *pos - gif->buf;
+       }
+
        ret = nsgif__colour_table_extract(
                        gif->local_colour_table, &gif->colour_layout,
                        2 << (frame->flags & NSGIF_COLOUR_TABLE_SIZE_MASK),


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=50b3f3b46903281c5507786b5f65118dca5139a5
commit 50b3f3b46903281c5507786b5f65118dca5139a5
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    GIF: Restructure local palette decode.

diff --git a/src/gif.c b/src/gif.c
index 34b4e58..e9048f9 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -1039,6 +1039,38 @@ static nsgif_error nsgif__parse_image_descriptor(
 /**
  * Extract a GIF colour table into a LibNSGIF colour table buffer.
  *
+ * \param[in] colour_table          The colour table to populate.
+ * \param[in] layout                la.
+ * \param[in] colour_table_entries  The number of colour table entries.
+ * \param[in] Data                  Raw colour table data.
+ */
+static void nsgif__colour_table_decode(
+               uint32_t colour_table[NSGIF_MAX_COLOURS],
+               const struct nsgif_colour_layout *layout,
+               size_t colour_table_entries,
+               const uint8_t *data)
+{
+       uint8_t *entry = (uint8_t *)colour_table;
+
+       while (colour_table_entries--) {
+               /* Gif colour map contents are r,g,b.
+                *
+                * We want to pack them bytewise into the colour table,
+                * according to the client colour layout.
+                */
+
+               entry[layout->r] = *data++;
+               entry[layout->g] = *data++;
+               entry[layout->b] = *data++;
+               entry[layout->a] = 0xff;
+
+               entry += sizeof(uint32_t);
+       }
+}
+
+/**
+ * Extract a GIF colour table into a LibNSGIF colour table buffer.
+ *
  * \param[in] gif                   The gif object we're decoding.
  * \param[in] colour_table          The colour table to populate.
  * \param[in] colour_table_entries  The number of colour table entries.
@@ -1046,42 +1078,25 @@ static nsgif_error nsgif__parse_image_descriptor(
  * \param[in] decode                Whether to decode the colour table.
  * \return NSGIF_OK on success, appropriate error otherwise.
  */
-static nsgif_error nsgif__colour_table_extract(
-               struct nsgif *gif,
+static inline nsgif_error nsgif__colour_table_extract(
                uint32_t colour_table[NSGIF_MAX_COLOURS],
                const struct nsgif_colour_layout *layout,
                size_t colour_table_entries,
-               const uint8_t **pos,
+               const uint8_t *data,
+               size_t data_len,
+               size_t *used,
                bool decode)
 {
-       const uint8_t *data = *pos;
-       size_t len = gif->buf + gif->buf_len - data;
-
-       if (len < colour_table_entries * 3) {
+       if (data_len < colour_table_entries * 3) {
                return NSGIF_ERR_END_OF_DATA;
        }
 
        if (decode) {
-               int count = colour_table_entries;
-               uint8_t *entry = (uint8_t *)colour_table;
-
-               while (count--) {
-                       /* Gif colour map contents are r,g,b.
-                        *
-                        * We want to pack them bytewise into the colour table,
-                        * according to the client colour layout.
-                        */
-
-                       entry[layout->r] = *data++;
-                       entry[layout->g] = *data++;
-                       entry[layout->b] = *data++;
-                       entry[layout->a] = 0xff;
-
-                       entry += sizeof(uint32_t);
-               }
+               nsgif__colour_table_decode(colour_table, layout,
+                               colour_table_entries, data);
        }
 
-       *pos += colour_table_entries * 3;
+       *used = colour_table_entries * 3;
        return NSGIF_OK;
 }
 
@@ -1103,6 +1118,9 @@ static nsgif_error nsgif__parse_colour_table(
                bool decode)
 {
        nsgif_error ret;
+       const uint8_t *data = *pos;
+       size_t len = gif->buf + gif->buf_len - data;
+       size_t used_bytes;
 
        assert(gif != NULL);
        assert(frame != NULL);
@@ -1112,19 +1130,21 @@ static nsgif_error nsgif__parse_colour_table(
                return NSGIF_OK;
        }
 
-       if (decode == false) {
-               frame->info.colour_table = true;
-       }
-
-       ret = nsgif__colour_table_extract(gif,
+       ret = nsgif__colour_table_extract(
                        gif->local_colour_table, &gif->colour_layout,
                        2 << (frame->flags & NSGIF_COLOUR_TABLE_SIZE_MASK),
-                       pos, decode);
+                       data, len, &used_bytes, decode);
        if (ret != NSGIF_OK) {
                return ret;
        }
+       *pos += used_bytes;
+
+       if (decode) {
+               gif->colour_table = gif->local_colour_table;
+       } else {
+               frame->info.colour_table = true;
+       }
 
-       gif->colour_table = gif->local_colour_table;
        return NSGIF_OK;
 }
 
@@ -1641,15 +1661,19 @@ nsgif_error nsgif_data_scan(
        if (gif->global_colour_table[0] == NSGIF_PROCESS_COLOURS) {
                /* Check for a global colour map signified by bit 7 */
                if (gif->info.colour_table) {
-                       ret = nsgif__colour_table_extract(gif,
+                       size_t remaining = gif->buf + gif->buf_len - nsgif_data;
+                       size_t used;
+
+                       ret = nsgif__colour_table_extract(
                                        gif->global_colour_table,
                                        &gif->colour_layout,
                                        gif->colour_table_size,
-                                       &nsgif_data, true);
+                                       nsgif_data, remaining, &used, true);
                        if (ret != NSGIF_OK) {
                                return ret;
                        }
 
+                       nsgif_data += used;
                        gif->buf_pos = (nsgif_data - gif->buf);
                } else {
                        /* Create a default colour table with the first two


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=76cc3a8ae804d398816ab9454731948f0ecb4c70
commit 76cc3a8ae804d398816ab9454731948f0ecb4c70
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    API: Add function to get global colour table.

diff --git a/include/nsgif.h b/include/nsgif.h
index bd0fd58..9eec0f8 100644
--- a/include/nsgif.h
+++ b/include/nsgif.h
@@ -23,6 +23,9 @@
 /** Representation of infinity. */
 #define NSGIF_INFINITE (UINT32_MAX)
 
+/** Maximum colour table size */
+#define NSGIF_MAX_COLOURS 256
+
 /**
  * Opaque type used by LibNSGIF to represent a GIF object in memory.
  */
@@ -428,6 +431,23 @@ const nsgif_frame_info_t *nsgif_get_frame_info(
                uint32_t frame);
 
 /**
+ * Get the global colour palette.
+ *
+ * If the GIF has no global colour table, this will return the default
+ * colour palette.
+ *
+ * Colours in same pixel format as \ref nsgif_bitmap_t.
+ *
+ * \param[in]  gif      The \ref nsgif_t object.
+ * \param[out] table    Client buffer to hold the colour table.
+ * \param[out] entries  The number of used entries in the colour table.
+ */
+void nsgif_global_palette(
+               const nsgif_t *gif,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries);
+
+/**
  * Configure handling of small frame delays.
  *
  * Historically people created GIFs with a tiny frame delay, however the slow
diff --git a/src/gif.c b/src/gif.c
index 038ebf9..34b4e58 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -17,9 +17,6 @@
 #include "lzw.h"
 #include "nsgif.h"
 
-/** Maximum colour table size */
-#define NSGIF_MAX_COLOURS 256
-
 /** Default minimum allowable frame delay in cs. */
 #define NSGIF_FRAME_DELAY_MIN 2
 
@@ -1672,6 +1669,8 @@ nsgif_error nsgif_data_scan(
                        entry[gif->colour_layout.g] = 0xFF;
                        entry[gif->colour_layout.b] = 0xFF;
                        entry[gif->colour_layout.a] = 0xFF;
+
+                       gif->colour_table_size = 2;
                }
 
                if (gif->info.colour_table &&
@@ -1909,6 +1908,18 @@ const nsgif_frame_info_t *nsgif_get_frame_info(
 }
 
 /* exported function documented in nsgif.h */
+void nsgif_global_palette(
+               const nsgif_t *gif,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries)
+{
+       size_t len = sizeof(*table) * NSGIF_MAX_COLOURS;
+
+       memcpy(table, gif->global_colour_table, len);
+       *entries = gif->colour_table_size;
+}
+
+/* exported function documented in nsgif.h */
 const char *nsgif_strerror(nsgif_error err)
 {
        static const char *const str[] = {


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=2b93687087490cb5e760405709961a9abf8e205b
commit 2b93687087490cb5e760405709961a9abf8e205b
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    Test: Add local/global colour table to info output.

diff --git a/test/nsgif.c b/test/nsgif.c
index 61c63d0..a87ab69 100644
--- a/test/nsgif.c
+++ b/test/nsgif.c
@@ -142,6 +142,8 @@ static void print_gif_info(const nsgif_info_t *info)
        fprintf(stdout, "  height: %"PRIu32"\n", info->height);
        fprintf(stdout, "  max-loops: %"PRIu32"\n", info->loop_max);
        fprintf(stdout, "  frame-count: %"PRIu32"\n", info->frame_count);
+       fprintf(stdout, "  global colour table: %s\n",
+                       info->colour_table ? "yes" : "no");
        fprintf(stdout, "  background:\n");
        fprintf(stdout, "    red: 0x%"PRIx8"\n", bg[0]);
        fprintf(stdout, "    green: 0x%"PRIx8"\n", bg[1]);
@@ -154,6 +156,7 @@ static void print_gif_frame_info(const nsgif_frame_info_t 
*info, uint32_t i)
        const char *disposal = nsgif_str_disposal(info->disposal);
 
        fprintf(stdout, "  - frame: %"PRIu32"\n", i);
+       fprintf(stdout, "    local colour table: %s\n", info->colour_table ? 
"yes" : "no");
        fprintf(stdout, "    disposal-method: %s\n", disposal);
        fprintf(stdout, "    transparency: %s\n", info->transparency ? "yes" : 
"no");
        fprintf(stdout, "    display: %s\n", info->display ? "yes" : "no");


commitdiff 
http://git.netsurf-browser.org/libnsgif.git/commit/?id=bdb312737d57497db67dda2543c7ea8b62315d0a
commit bdb312737d57497db67dda2543c7ea8b62315d0a
Author: Michael Drake <[email protected]>
Commit: Michael Drake <[email protected]>

    API: Store presence of global/local colour table in GIF/frame info.

diff --git a/include/nsgif.h b/include/nsgif.h
index 0ea792b..bd0fd58 100644
--- a/include/nsgif.h
+++ b/include/nsgif.h
@@ -360,6 +360,8 @@ typedef struct nsgif_info {
        int loop_max;
        /** background colour in same pixel format as \ref nsgif_bitmap_t. */
        uint32_t background;
+       /** whether the GIF has a global colour table */
+       bool colour_table;
 } nsgif_info_t;
 
 /**
@@ -392,6 +394,8 @@ typedef struct nsgif_frame_info {
        bool display;
        /** whether the frame may have transparency */
        bool transparency;
+       /** whether the frame has a local colour table */
+       bool colour_table;
 
        /** Disposal method for previous frame; affects plotting */
        uint8_t disposal;
diff --git a/src/gif.c b/src/gif.c
index 435d0d9..038ebf9 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -103,11 +103,9 @@ struct nsgif {
        uint32_t bg_index;
        /** image aspect ratio (ignored) */
        uint32_t aspect_ratio;
-       /** size of colour table (in entries) */
+       /** size of global colour table (in entries) */
        uint32_t colour_table_size;
 
-       /** whether the GIF has a global colour table */
-       bool global_colours;
        /** current colour table */
        uint32_t *colour_table;
        /** Client's colour component order. */
@@ -1117,6 +1115,10 @@ static nsgif_error nsgif__parse_colour_table(
                return NSGIF_OK;
        }
 
+       if (decode == false) {
+               frame->info.colour_table = true;
+       }
+
        ret = nsgif__colour_table_extract(gif,
                        gif->local_colour_table, &gif->colour_layout,
                        2 << (frame->flags & NSGIF_COLOUR_TABLE_SIZE_MASK),
@@ -1234,6 +1236,7 @@ static struct nsgif_frame *nsgif__get_frame(
 
                frame->transparency_index = NSGIF_NO_TRANSPARENCY;
                frame->frame_pointer = gif->buf_pos;
+               frame->info.colour_table = false;
                frame->info.transparency = false;
                frame->redraw_required = false;
                frame->info.display = false;
@@ -1546,7 +1549,7 @@ static nsgif_error nsgif__parse_logical_screen_descriptor(
 
        gif->info.width = data[0] | (data[1] << 8);
        gif->info.height = data[2] | (data[3] << 8);
-       gif->global_colours = data[4] & NSGIF_COLOUR_TABLE_MASK;
+       gif->info.colour_table = data[4] & NSGIF_COLOUR_TABLE_MASK;
        gif->colour_table_size = 2 << (data[4] & NSGIF_COLOUR_TABLE_SIZE_MASK);
        gif->bg_index = data[5];
        gif->aspect_ratio = data[6];
@@ -1640,7 +1643,7 @@ nsgif_error nsgif_data_scan(
         */
        if (gif->global_colour_table[0] == NSGIF_PROCESS_COLOURS) {
                /* Check for a global colour map signified by bit 7 */
-               if (gif->global_colours) {
+               if (gif->info.colour_table) {
                        ret = nsgif__colour_table_extract(gif,
                                        gif->global_colour_table,
                                        &gif->colour_layout,
@@ -1671,7 +1674,7 @@ nsgif_error nsgif_data_scan(
                        entry[gif->colour_layout.a] = 0xFF;
                }
 
-               if (gif->global_colours &&
+               if (gif->info.colour_table &&
                    gif->bg_index < gif->colour_table_size) {
                        size_t bg_idx = gif->bg_index;
                        gif->info.background = gif->global_colour_table[bg_idx];


-----------------------------------------------------------------------

Summary of changes:
 include/nsgif.h |   44 ++++++++++++++++
 src/gif.c       |  154 ++++++++++++++++++++++++++++++++++++++++---------------
 test/nsgif.c    |  106 +++++++++++++++++++++++++++++++++++---
 3 files changed, 256 insertions(+), 48 deletions(-)

diff --git a/include/nsgif.h b/include/nsgif.h
index 0ea792b..208bc27 100644
--- a/include/nsgif.h
+++ b/include/nsgif.h
@@ -23,6 +23,9 @@
 /** Representation of infinity. */
 #define NSGIF_INFINITE (UINT32_MAX)
 
+/** Maximum colour table size */
+#define NSGIF_MAX_COLOURS 256
+
 /**
  * Opaque type used by LibNSGIF to represent a GIF object in memory.
  */
@@ -360,6 +363,8 @@ typedef struct nsgif_info {
        int loop_max;
        /** background colour in same pixel format as \ref nsgif_bitmap_t. */
        uint32_t background;
+       /** whether the GIF has a global colour table */
+       bool global_palette;
 } nsgif_info_t;
 
 /**
@@ -392,6 +397,8 @@ typedef struct nsgif_frame_info {
        bool display;
        /** whether the frame may have transparency */
        bool transparency;
+       /** whether the frame has a local colour table */
+       bool local_palette;
 
        /** Disposal method for previous frame; affects plotting */
        uint8_t disposal;
@@ -424,6 +431,43 @@ const nsgif_frame_info_t *nsgif_get_frame_info(
                uint32_t frame);
 
 /**
+ * Get the global colour palette.
+ *
+ * If the GIF has no global colour table, this will return the default
+ * colour palette.
+ *
+ * Colours in same pixel format as \ref nsgif_bitmap_t.
+ *
+ * \param[in]  gif      The \ref nsgif_t object.
+ * \param[out] table    Client buffer to hold the colour table.
+ * \param[out] entries  The number of used entries in the colour table.
+ */
+void nsgif_global_palette(
+               const nsgif_t *gif,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries);
+
+/**
+ * Get the local colour palette for a frame.
+ *
+ * Frames may have no local palette. In this case they use the global palette.
+ * This function returns false if the frame has no local palette.
+ *
+ * Colours in same pixel format as \ref nsgif_bitmap_t.
+ *
+ * \param[in]  gif      The \ref nsgif_t object.
+ * \param[in]  frame    The \ref frame to get the palette for.
+ * \param[out] table    Client buffer to hold the colour table.
+ * \param[out] entries  The number of used entries in the colour table.
+ * \return true if a palette is returned, false otherwise.
+ */
+bool nsgif_local_palette(
+               const nsgif_t *gif,
+               uint32_t frame,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries);
+
+/**
  * Configure handling of small frame delays.
  *
  * Historically people created GIFs with a tiny frame delay, however the slow
diff --git a/src/gif.c b/src/gif.c
index 435d0d9..d2b6054 100644
--- a/src/gif.c
+++ b/src/gif.c
@@ -17,9 +17,6 @@
 #include "lzw.h"
 #include "nsgif.h"
 
-/** Maximum colour table size */
-#define NSGIF_MAX_COLOURS 256
-
 /** Default minimum allowable frame delay in cs. */
 #define NSGIF_FRAME_DELAY_MIN 2
 
@@ -35,7 +32,7 @@ typedef struct nsgif_frame {
        struct nsgif_frame_info info;
 
        /** offset (in bytes) to the GIF frame data */
-       uint32_t frame_pointer;
+       uint32_t frame_offset;
        /** whether the frame has previously been decoded. */
        bool decoded;
        /** whether the frame is totally opaque */
@@ -46,6 +43,9 @@ typedef struct nsgif_frame {
        /** the index designating a transparent pixel */
        uint32_t transparency_index;
 
+       /** offset to frame colour table */
+       uint32_t colour_table_offset;
+
        /* Frame flags */
        uint32_t flags;
 } nsgif_frame;
@@ -103,11 +103,9 @@ struct nsgif {
        uint32_t bg_index;
        /** image aspect ratio (ignored) */
        uint32_t aspect_ratio;
-       /** size of colour table (in entries) */
+       /** size of global colour table (in entries) */
        uint32_t colour_table_size;
 
-       /** whether the GIF has a global colour table */
-       bool global_colours;
        /** current colour table */
        uint32_t *colour_table;
        /** Client's colour component order. */
@@ -1044,6 +1042,38 @@ static nsgif_error nsgif__parse_image_descriptor(
 /**
  * Extract a GIF colour table into a LibNSGIF colour table buffer.
  *
+ * \param[in] colour_table          The colour table to populate.
+ * \param[in] layout                la.
+ * \param[in] colour_table_entries  The number of colour table entries.
+ * \param[in] Data                  Raw colour table data.
+ */
+static void nsgif__colour_table_decode(
+               uint32_t colour_table[NSGIF_MAX_COLOURS],
+               const struct nsgif_colour_layout *layout,
+               size_t colour_table_entries,
+               const uint8_t *data)
+{
+       uint8_t *entry = (uint8_t *)colour_table;
+
+       while (colour_table_entries--) {
+               /* Gif colour map contents are r,g,b.
+                *
+                * We want to pack them bytewise into the colour table,
+                * according to the client colour layout.
+                */
+
+               entry[layout->r] = *data++;
+               entry[layout->g] = *data++;
+               entry[layout->b] = *data++;
+               entry[layout->a] = 0xff;
+
+               entry += sizeof(uint32_t);
+       }
+}
+
+/**
+ * Extract a GIF colour table into a LibNSGIF colour table buffer.
+ *
  * \param[in] gif                   The gif object we're decoding.
  * \param[in] colour_table          The colour table to populate.
  * \param[in] colour_table_entries  The number of colour table entries.
@@ -1051,42 +1081,25 @@ static nsgif_error nsgif__parse_image_descriptor(
  * \param[in] decode                Whether to decode the colour table.
  * \return NSGIF_OK on success, appropriate error otherwise.
  */
-static nsgif_error nsgif__colour_table_extract(
-               struct nsgif *gif,
+static inline nsgif_error nsgif__colour_table_extract(
                uint32_t colour_table[NSGIF_MAX_COLOURS],
                const struct nsgif_colour_layout *layout,
                size_t colour_table_entries,
-               const uint8_t **pos,
+               const uint8_t *data,
+               size_t data_len,
+               size_t *used,
                bool decode)
 {
-       const uint8_t *data = *pos;
-       size_t len = gif->buf + gif->buf_len - data;
-
-       if (len < colour_table_entries * 3) {
+       if (data_len < colour_table_entries * 3) {
                return NSGIF_ERR_END_OF_DATA;
        }
 
        if (decode) {
-               int count = colour_table_entries;
-               uint8_t *entry = (uint8_t *)colour_table;
-
-               while (count--) {
-                       /* Gif colour map contents are r,g,b.
-                        *
-                        * We want to pack them bytewise into the colour table,
-                        * according to the client colour layout.
-                        */
-
-                       entry[layout->r] = *data++;
-                       entry[layout->g] = *data++;
-                       entry[layout->b] = *data++;
-                       entry[layout->a] = 0xff;
-
-                       entry += sizeof(uint32_t);
-               }
+               nsgif__colour_table_decode(colour_table, layout,
+                               colour_table_entries, data);
        }
 
-       *pos += colour_table_entries * 3;
+       *used = colour_table_entries * 3;
        return NSGIF_OK;
 }
 
@@ -1108,6 +1121,9 @@ static nsgif_error nsgif__parse_colour_table(
                bool decode)
 {
        nsgif_error ret;
+       const uint8_t *data = *pos;
+       size_t len = gif->buf + gif->buf_len - data;
+       size_t used_bytes;
 
        assert(gif != NULL);
        assert(frame != NULL);
@@ -1117,15 +1133,25 @@ static nsgif_error nsgif__parse_colour_table(
                return NSGIF_OK;
        }
 
-       ret = nsgif__colour_table_extract(gif,
+       if (decode == false) {
+               frame->colour_table_offset = *pos - gif->buf;
+       }
+
+       ret = nsgif__colour_table_extract(
                        gif->local_colour_table, &gif->colour_layout,
                        2 << (frame->flags & NSGIF_COLOUR_TABLE_SIZE_MASK),
-                       pos, decode);
+                       data, len, &used_bytes, decode);
        if (ret != NSGIF_OK) {
                return ret;
        }
+       *pos += used_bytes;
+
+       if (decode) {
+               gif->colour_table = gif->local_colour_table;
+       } else {
+               frame->info.local_palette = true;
+       }
 
-       gif->colour_table = gif->local_colour_table;
        return NSGIF_OK;
 }
 
@@ -1233,7 +1259,8 @@ static struct nsgif_frame *nsgif__get_frame(
                frame = &gif->frames[frame_idx];
 
                frame->transparency_index = NSGIF_NO_TRANSPARENCY;
-               frame->frame_pointer = gif->buf_pos;
+               frame->frame_offset = gif->buf_pos;
+               frame->info.local_palette = false;
                frame->info.transparency = false;
                frame->redraw_required = false;
                frame->info.display = false;
@@ -1271,7 +1298,7 @@ static nsgif_error nsgif__process_frame(
        end = gif->buf + gif->buf_len;
 
        if (decode) {
-               pos = gif->buf + frame->frame_pointer;
+               pos = gif->buf + frame->frame_offset;
 
                /* Ensure this frame is supposed to be decoded */
                if (frame->info.display == false) {
@@ -1546,7 +1573,7 @@ static nsgif_error nsgif__parse_logical_screen_descriptor(
 
        gif->info.width = data[0] | (data[1] << 8);
        gif->info.height = data[2] | (data[3] << 8);
-       gif->global_colours = data[4] & NSGIF_COLOUR_TABLE_MASK;
+       gif->info.global_palette = data[4] & NSGIF_COLOUR_TABLE_MASK;
        gif->colour_table_size = 2 << (data[4] & NSGIF_COLOUR_TABLE_SIZE_MASK);
        gif->bg_index = data[5];
        gif->aspect_ratio = data[6];
@@ -1640,16 +1667,20 @@ nsgif_error nsgif_data_scan(
         */
        if (gif->global_colour_table[0] == NSGIF_PROCESS_COLOURS) {
                /* Check for a global colour map signified by bit 7 */
-               if (gif->global_colours) {
-                       ret = nsgif__colour_table_extract(gif,
+               if (gif->info.global_palette) {
+                       size_t remaining = gif->buf + gif->buf_len - nsgif_data;
+                       size_t used;
+
+                       ret = nsgif__colour_table_extract(
                                        gif->global_colour_table,
                                        &gif->colour_layout,
                                        gif->colour_table_size,
-                                       &nsgif_data, true);
+                                       nsgif_data, remaining, &used, true);
                        if (ret != NSGIF_OK) {
                                return ret;
                        }
 
+                       nsgif_data += used;
                        gif->buf_pos = (nsgif_data - gif->buf);
                } else {
                        /* Create a default colour table with the first two
@@ -1669,9 +1700,11 @@ nsgif_error nsgif_data_scan(
                        entry[gif->colour_layout.g] = 0xFF;
                        entry[gif->colour_layout.b] = 0xFF;
                        entry[gif->colour_layout.a] = 0xFF;
+
+                       gif->colour_table_size = 2;
                }
 
-               if (gif->global_colours &&
+               if (gif->info.global_palette &&
                    gif->bg_index < gif->colour_table_size) {
                        size_t bg_idx = gif->bg_index;
                        gif->info.background = gif->global_colour_table[bg_idx];
@@ -1906,6 +1939,43 @@ const nsgif_frame_info_t *nsgif_get_frame_info(
 }
 
 /* exported function documented in nsgif.h */
+void nsgif_global_palette(
+               const nsgif_t *gif,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries)
+{
+       size_t len = sizeof(*table) * NSGIF_MAX_COLOURS;
+
+       memcpy(table, gif->global_colour_table, len);
+       *entries = gif->colour_table_size;
+}
+
+/* exported function documented in nsgif.h */
+bool nsgif_local_palette(
+               const nsgif_t *gif,
+               uint32_t frame,
+               uint32_t table[NSGIF_MAX_COLOURS],
+               size_t *entries)
+{
+       const nsgif_frame *f;
+
+       if (frame >= gif->frame_count_partial) {
+               return false;
+       }
+
+       f = &gif->frames[frame];
+       if (f->info.local_palette == false) {
+               return false;
+       }
+
+       *entries = 2 << (f->flags & NSGIF_COLOUR_TABLE_SIZE_MASK);
+       nsgif__colour_table_decode(table, &gif->colour_layout,
+                       *entries, gif->buf + f->colour_table_offset);
+
+       return true;
+}
+
+/* exported function documented in nsgif.h */
 const char *nsgif_strerror(nsgif_error err)
 {
        static const char *const str[] = {
diff --git a/test/nsgif.c b/test/nsgif.c
index 61c63d0..4a9e31c 100644
--- a/test/nsgif.c
+++ b/test/nsgif.c
@@ -27,6 +27,7 @@ static struct nsgif_options {
        const char *file;
        const char *ppm;
        uint64_t loops;
+       bool palette;
        bool info;
 } nsgif_options;
 
@@ -54,6 +55,13 @@ static const struct cli_table_entry cli_entries[] = {
                     "The default is 1."
        },
        {
+               .s = 'p',
+               .l = "palette",
+               .t = CLI_BOOL,
+               .v.b = &nsgif_options.palette,
+               .d = "Save palette images."
+       },
+       {
                .p = true,
                .l = "FILE",
                .t = CLI_STRING,
@@ -142,6 +150,7 @@ static void print_gif_info(const nsgif_info_t *info)
        fprintf(stdout, "  height: %"PRIu32"\n", info->height);
        fprintf(stdout, "  max-loops: %"PRIu32"\n", info->loop_max);
        fprintf(stdout, "  frame-count: %"PRIu32"\n", info->frame_count);
+       fprintf(stdout, "  global palette: %s\n", info->global_palette ? "yes" 
: "no");
        fprintf(stdout, "  background:\n");
        fprintf(stdout, "    red: 0x%"PRIx8"\n", bg[0]);
        fprintf(stdout, "    green: 0x%"PRIx8"\n", bg[1]);
@@ -154,6 +163,7 @@ static void print_gif_frame_info(const nsgif_frame_info_t 
*info, uint32_t i)
        const char *disposal = nsgif_str_disposal(info->disposal);
 
        fprintf(stdout, "  - frame: %"PRIu32"\n", i);
+       fprintf(stdout, "    local palette: %s\n", info->local_palette ? "yes" 
: "no");
        fprintf(stdout, "    disposal-method: %s\n", disposal);
        fprintf(stdout, "    transparency: %s\n", info->transparency ? "yes" : 
"no");
        fprintf(stdout, "    display: %s\n", info->display ? "yes" : "no");
@@ -165,7 +175,82 @@ static void print_gif_frame_info(const nsgif_frame_info_t 
*info, uint32_t i)
        fprintf(stdout, "      h: %"PRIu32"\n", info->rect.y1 - info->rect.y0);
 }
 
-static void decode(FILE* ppm, const char *name, nsgif_t *gif)
+static bool save_palette(
+               const char *img_filename,
+               const char *palette_filename,
+               const uint32_t palette[NSGIF_MAX_COLOURS],
+               size_t used_entries)
+{
+       enum {
+               SIZE = 32,
+               COUNT = 16,
+       };
+       FILE *f;
+       int size = COUNT * SIZE + 1;
+
+       f = fopen(palette_filename, "w+");
+       if (f == NULL) {
+               fprintf(stderr, "Unable to open %s for writing\n",
+                               palette_filename);
+               return false;
+       }
+
+       fprintf(f, "P3\n");
+       fprintf(f, "# %s: %s\n", img_filename, palette_filename);
+       fprintf(f, "# Colour count: %zu\n", used_entries);
+       fprintf(f, "%u %u 256\n", size, size);
+
+       for (int y = 0; y < size; y++) {
+               for (int x = 0; x < size; x++) {
+                       if (x % SIZE == 0 || y % SIZE == 0) {
+                               fprintf(f, "0 0 0 ");
+                       } else {
+                               size_t offset = y / SIZE * COUNT + x / SIZE;
+                               uint8_t *entry = (uint8_t *)&palette[offset];
+
+                               fprintf(f, "%u %u %u ",
+                                               entry[0],
+                                               entry[1],
+                                               entry[2]);
+                       }
+               }
+
+               fprintf(f, "\n");
+       }
+
+       fclose(f);
+
+       return true;
+}
+
+static bool save_global_palette(const nsgif_t *gif)
+{
+       uint32_t table[NSGIF_MAX_COLOURS];
+       size_t entries;
+
+       nsgif_global_palette(gif, table, &entries);
+
+       return save_palette(nsgif_options.file, "global-palette.ppm",
+                       table, entries);
+}
+
+static bool save_local_palette(const nsgif_t *gif, uint32_t frame)
+{
+       static uint32_t table[NSGIF_MAX_COLOURS];
+       char filename[64];
+       size_t entries;
+
+       snprintf(filename, sizeof(filename), "local-palette-%"PRIu32".ppm",
+                       frame);
+
+       if (!nsgif_local_palette(gif, frame, table, &entries)) {
+               return false;
+       }
+
+       return save_palette(nsgif_options.file, filename, table, entries);
+}
+
+static void decode(FILE* ppm, const char *name, nsgif_t *gif, bool first)
 {
        nsgif_error err;
        uint32_t frame_prev = 0;
@@ -173,7 +258,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
 
        info = nsgif_get_info(gif);
 
-       if (ppm != NULL) {
+       if (first && ppm != NULL) {
                fprintf(ppm, "P3\n");
                fprintf(ppm, "# %s\n", name);
                fprintf(ppm, "# width                %u \n", info->width);
@@ -184,9 +269,12 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                                info->height * info->frame_count);
        }
 
-       if (nsgif_options.info == true) {
+       if (first && nsgif_options.info) {
                print_gif_info(info);
        }
+       if (first && nsgif_options.palette && info->global_palette) {
+               save_global_palette(gif);
+       }
 
        /* decode the frames */
        while (true) {
@@ -210,7 +298,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                }
                frame_prev = frame_new;
 
-               if (nsgif_options.info == true) {
+               if (first && nsgif_options.info) {
                        const nsgif_frame_info_t *f_info;
 
                        f_info = nsgif_get_frame_info(gif, frame_new);
@@ -218,6 +306,9 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                                print_gif_frame_info(f_info, frame_new);
                        }
                }
+               if (first && nsgif_options.palette) {
+                       save_local_palette(gif, frame_new);
+               }
 
                err = nsgif_frame_decode(gif, frame_new, &bitmap);
                if (err != NSGIF_OK) {
@@ -226,7 +317,7 @@ static void decode(FILE* ppm, const char *name, nsgif_t 
*gif)
                                        frame_new, nsgif_strerror(err));
                        /* Continue decoding the rest of the frames. */
 
-               } else if (ppm != NULL) {
+               } else if (first && ppm != NULL) {
                        fprintf(ppm, "# frame %u:\n", frame_new);
                        image = (const uint8_t *) bitmap;
                        for (uint32_t y = 0; y != info->height; y++) {
@@ -299,7 +390,10 @@ int main(int argc, char *argv[])
        }
 
        for (uint64_t i = 0; i < nsgif_options.loops; i++) {
-               decode((i == 0) ? ppm : NULL, nsgif_options.file, gif);
+               decode(ppm, nsgif_options.file, gif, i == 0);
+
+               /* We want to ignore any loop limit in the GIF. */
+               nsgif_reset(gif);
        }
 
        if (ppm != NULL) {


-- 
NetSurf GIF Decoder
_______________________________________________
netsurf-commits mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to