Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support GIF's with no colormap #10

Open
wcout opened this issue Jan 9, 2019 · 2 comments
Open

Support GIF's with no colormap #10

wcout opened this issue Jan 9, 2019 · 2 comments
Assignees

Comments

@wcout
Copy link

wcout commented Jan 9, 2019

This is just a request for a feature you may want to support:

The standard says, that both global and local color tables are no required blocks. In that case the application can use a default colormap.

Currently gif_load.h does not parse such images.

I have made some changes in my copy to support it:

(1) Continue parsing when clrs is 0.
(2) Give access to the palette definition in the GIF_WHDR structure.
(3) Return the value of the GIF header field color resultion. As I read it, it can be used in such a case to determine how many colors the palette has in order to supply a suitable replacement.

(1) and (2) would be nice to have, (3) could in principle also be done in the application, because the value is at a fixed position in the file.

These are my changes:

diff --git a/gif_load.h b/gif_load.h
index 12cc402..99324bb 100644
--- a/gif_load.h
+++ b/gif_load.h
@@ -48,12 +48,13 @@ extern "C" {
 #pragma pack(push, 1)
 struct GIF_WHDR {                /** ======== frame writer info: ======== **/
     long xdim, ydim, clrs,       /** global dimensions, palette size      **/
+         cres,                   /** color resolution: 2^(cres+1) = #clrs **/
          bkgd, tran,             /** background index, transparent index  **/
          intr, mode,             /** interlace flag, frame blending mode  **/
          frxd, fryd, frxo, fryo, /** current frame dimensions and offset  **/
          time, ifrm, nfrm;       /** delay, frame number, frame count     **/
     uint8_t *bptr;               /** frame pixel indices or metadata      **/
-    struct {                     /** [==== GIF RGB palette element: ====] **/
+    struct CPAL {                /** [==== GIF RGB palette element: ====] **/
         uint8_t R, G, B;         /** [color values - red, green, blue   ] **/
     } *cpal;                     /** current palette                      **/
 };
@@ -225,6 +226,7 @@ GIF_EXTR long GIF_Load(void *data, long size,
     || ((buff[4] != 55) && (buff[4] != 57)) || (buff[5] != 97) || !gwfr)
         return 0;
 
+    whdr.cres = (ghdr->flgs >> 4) & 7;
     buff = (uint8_t*)(ghdr + 1) /** skipping the global header and palette **/
          + _GIF_LoadHeader(ghdr->flgs, 0, 0, 0, 0, 0L) * 3L;
     if ((size -= buff - (uint8_t*)ghdr) <= 0)
@@ -238,7 +240,7 @@ GIF_EXTR long GIF_Load(void *data, long size,
         if (desc == GIF_FHDM) {
             fhdr = (struct GIF_FHDR*)whdr.bptr;
             if (_GIF_LoadHeader(ghdr->flgs, &whdr.bptr, (void**)&whdr.cpal,
-                                fhdr->flgs, &blen, sizeof(*fhdr)) <= 0)
+                                fhdr->flgs, &blen, sizeof(*fhdr)) < 0)
                 break;
             whdr.frxd = _GIF_SWAP(fhdr->frxd);
             whdr.fryd = _GIF_SWAP(fhdr->fryd);
@@ -258,7 +260,7 @@ GIF_EXTR long GIF_Load(void *data, long size,
             *(void**)&whdr.cpal = (void*)(ghdr + 1); /** interlaced? -^ **/
             whdr.clrs = _GIF_LoadHeader(ghdr->flgs, &buff, (void**)&whdr.cpal,
                                         fhdr->flgs, &size, sizeof(*fhdr));
-            if ((skip <= ++whdr.ifrm) && ((whdr.clrs <= 0)
+            if ((skip <= ++whdr.ifrm) && ((whdr.clrs < 0)
             ||  (_GIF_LoadFrame(&buff, &size,
                                  whdr.bptr, whdr.bptr + blen) < 0)))
                 size = -(whdr.ifrm--) - 1; /** failed to load the frame **/

In my program I'm doing something like that, when there are no colors:

void frame_cb(void *data_, GIF_WHDR *whdr_) {
  // ...
  if (!whdr_.clrs) {
    // no colors: use default table
    static struct GIF_WHDR::CPAL defClrs[256];
    whdr_.clrs = 1 << (whdr_.cres + 1);
    whdr_.cpal = defClrs;
    memset(defClrs, 0, sizeof(defClrs)); // Note: also sets first color to black
    defClrs[1].R = defClrs[1].G = defClrs[1].B = 0xff; // white
    for (int i = 2; i < whdr_.clrs; i++)
      defClrs[i].R = defClrs[i].G = defClrs[i].B = (uchar)(255 * i / (whdr_.clrs - 1));
  }
  // ...
}
@hidefromkgb
Copy link
Owner

hidefromkgb commented Jan 9, 2019

I can modify the loader so it won`t panic on empty palettes, just boldly returning 0 in cpal.
The additional field seems superfluous, since the right field to hold the number of colors requested by the GIF is definitely clrs.

@wcout
Copy link
Author

wcout commented Jan 9, 2019

That would also be an option. And you would set if from color resolution?
The naming of the cpal struct would be required also.

@hidefromkgb hidefromkgb self-assigned this Jan 15, 2019
wcout added a commit to wcout/gif_load that referenced this issue Dec 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants