login

<     >

2017-11-15 23:26:39 (UTC-02:00)

Marcel Rodrigues <marcelgmr@gmail.com>

Implement background color and disposal methods.

diff --git a/gifdec.c b/gifdec.c
index 0671ed4..7945c35 100644
--- a/gifdec.c
+++ b/gifdec.c
@@ -80,7 +80,7 @@ gd_open_gif(const char *fname)
     /* Aspect Ratio */
     read(fd, &aspect, 1);
     /* Create gd_GIF Structure. */
-    gif = calloc(1, sizeof(*gif) + width * height);
+    gif = calloc(1, sizeof(*gif) + 2 * width * height);
     if (!gif) goto fail;
     gif->fd = fd;
     gif->width  = width;
@@ -89,7 +89,11 @@ gd_open_gif(const char *fname)
     gif->gct.size = gct_sz;
     read(fd, gif->gct.colors, 3 * gif->gct.size);
     gif->palette = &gif->gct;
+    gif->bgcolor = bgidx;
     gif->frame = (uint8_t *) &gif[1];
+    gif->back = &gif->frame[gif->width * gif->height];
+    if (gif->bgcolor)
+        memset(gif->frame, gif->bgcolor, gif->width * gif->height);
     goto ok;
 fail:
     close(fd);
@@ -327,7 +331,7 @@ read_image_data(gd_GIF *gif, uint16_t x, uint16_t y, uint16_t w)
 static int
 read_image(gd_GIF *gif)
 {
-    uint16_t x, y, w, h;
+    uint16_t x, y, w, h, i, j;
     uint8_t fisrz;
     int interlace;
 
@@ -347,6 +351,31 @@ read_image(gd_GIF *gif)
         gif->palette = &gif->lct;
     } else
         gif->palette = &gif->gct;
+    if (gif->prev_disposal == 3) {
+        j = gif->prev_y * gif->width + gif->prev_x;
+        for (i = 0; i < gif->prev_h; i++) {
+            memcpy(&gif->frame[j], &gif->back[j], gif->prev_w);
+            j += gif->width;
+        }
+    } else if (gif->prev_disposal == 2) {
+        j = gif->prev_y * gif->width + gif->prev_x;
+        for (i = 0; i < gif->prev_h; i++) {
+            memset(&gif->frame[j], gif->bgcolor, gif->prev_w);
+            j += gif->width;
+        }
+    }
+    if (gif->gce.disposal == 3) {
+        j = y * gif->width + x;
+        for (i = 0; i < h; i++) {
+            memcpy(&gif->back[j], &gif->frame[j], w);
+            j += gif->width;
+        }
+        gif->prev_x = x;
+        gif->prev_y = y;
+        gif->prev_w = w;
+        gif->prev_h = h;
+    }
+    gif->prev_disposal = gif->gce.disposal;
     /* Image Data. */
     return read_image_data(gif, x, y, w);
 }

diff --git a/gifdec.h b/gifdec.h
index 08fcbfe..9712e6e 100644
--- a/gifdec.h
+++ b/gifdec.h
@@ -23,7 +23,10 @@ typedef struct gd_GIF {
     gd_GCE gce;
     gd_Palette *palette;
     gd_Palette lct, gct;
-    uint8_t *frame;
+    uint16_t prev_x, prev_y, prev_w, prev_h;
+    uint8_t prev_disposal;
+    uint8_t bgcolor;
+    uint8_t *frame, *back;
 } gd_GIF;
 
 gd_GIF *gd_open_gif(const char *fname);