login

<     >

2021-04-06 20:39:02 (UTC-03:00)

Marcel Rodrigues <marcelgmr@gmail.com>

Add option to copy default palette to array.

diff --git a/README b/README
index 1d1fd39..35b159e 100644
--- a/README
+++ b/README
@@ -61,6 +61,9 @@ default table is composed  of the 16 standard VGA colors,  plus the 216 web-safe
 colors (all combinations of  RGB with only 6 valid values  per channel), plus 24
 grey colors equally spaced between black and white, excluding both.
 
+If `depth` < 0 and `palette` is not NULL, then the default table with 2 ^ -depth
+colors is used and it is stored in the array at the `palette` address.
+
 If the `loop` parameter is zero, the resulting GIF will loop forever. If it is a
 positive number, the  animation will  be played that number  of times. If `loop`
 is negative,  no looping  information is stored  in the GIF  file (for  most GIF

diff --git a/gifenc.c b/gifenc.c
index c0e4e11..5be9ffe 100644
--- a/gifenc.c
+++ b/gifenc.c
@@ -70,6 +70,15 @@ del_trie(Node *root, int degree)
     free(root);
 }
 
+#define write_and_store(s, dst, fd, src, n) \
+do { \
+    write(fd, src, n); \
+    if (s) { \
+        memcpy(dst, src, n); \
+        dst += n; \
+    } \
+} while (0);
+
 static void put_loop(ge_GIF *gif, uint16_t loop);
 
 ge_GIF *
@@ -79,11 +88,11 @@ ge_new_gif(
 )
 {
     int i, r, g, b, v;
+    int store_gct, custom_gct;
     ge_GIF *gif = calloc(1, sizeof(*gif) + 2*width*height);
     if (!gif)
         goto no_gif;
     gif->w = width; gif->h = height;
-    gif->depth = depth > 1 ? depth : 2;
     gif->frame = (uint8_t *) &gif[1];
     gif->back = &gif->frame[width*height];
 #ifdef _WIN32
@@ -99,18 +108,30 @@ ge_new_gif(
     write(gif->fd, "GIF89a", 6);
     write_num(gif->fd, width);
     write_num(gif->fd, height);
-    write(gif->fd, (uint8_t []) {0xF0 | (depth-1), 0x00, 0x00}, 3);
+    store_gct = custom_gct = 0;
     if (palette) {
+        if (depth < 0)
+            store_gct = 1;
+        else
+            custom_gct = 1;
+    }
+    if (depth < 0)
+        depth = -depth;
+    gif->depth = depth > 1 ? depth : 2;
+    write(gif->fd, (uint8_t []) {0xF0 | (depth-1), 0x00, 0x00}, 3);
+    if (custom_gct) {
         write(gif->fd, palette, 3 << depth);
     } else if (depth <= 4) {
-        write(gif->fd, vga, 3 << depth);
+        write_and_store(store_gct, palette, gif->fd, vga, 3 << depth);
     } else {
-        write(gif->fd, vga, sizeof(vga));
+        write_and_store(store_gct, palette, gif->fd, vga, sizeof(vga));
         i = 0x10;
         for (r = 0; r < 6; r++) {
             for (g = 0; g < 6; g++) {
                 for (b = 0; b < 6; b++) {
-                    write(gif->fd, (uint8_t []) {r*51, g*51, b*51}, 3);
+                    write_and_store(store_gct, palette, gif->fd,
+                      ((uint8_t []) {r*51, g*51, b*51}), 3
+                    );
                     if (++i == 1 << depth)
                         goto done_gct;
                 }
@@ -118,7 +139,9 @@ ge_new_gif(
         }
         for (i = 1; i <= 24; i++) {
             v = i * 0xFF / 25;
-            write(gif->fd, (uint8_t []) {v, v, v}, 3);
+            write_and_store(store_gct, palette, gif->fd,
+              ((uint8_t []) {v, v, v}), 3
+            );
         }
     }
 done_gct: