Let GIF decode an opaque but non-black background
diff --git a/example/gifplayer/gifplayer.c b/example/gifplayer/gifplayer.c
index 74ff1be..84926a2 100644
--- a/example/gifplayer/gifplayer.c
+++ b/example/gifplayer/gifplayer.c
@@ -100,6 +100,7 @@
 wuffs_base__slice_u8 printbuf = {0};
 
 bool first_play = true;
+wuffs_base__color_u32_argb_premul background_color = 0;
 uint32_t num_loops_remaining = 0;
 wuffs_base__pixel_buffer pb = {0};
 
@@ -130,6 +131,7 @@
 const char* reset_color = "\x1B[0m";
 
 bool color_flag = false;
+bool quirk_background_is_opaque_flag = false;
 const int stdout_fd = 1;
 
 static inline uint32_t load_u32le(uint8_t* p) {
@@ -146,7 +148,7 @@
     wuffs_base__color_u32_argb_premul* d =
         curr_dst_buffer + (y * width) + bounds.min_incl_x;
     for (x = bounds.min_incl_x; x < bounds.max_excl_x; x++) {
-      *d++ = 0;
+      *d++ = background_color;
     }
   }
 }
@@ -296,6 +298,11 @@
     return status;
   }
 
+  if (quirk_background_is_opaque_flag) {
+    wuffs_gif__decoder__set_quirk_enabled(
+        &dec, wuffs_gif__quirk_background_is_opaque, true);
+  }
+
   wuffs_base__io_buffer src;
   src.data.ptr = src_buffer;
   src.data.len = src_len;
@@ -316,6 +323,7 @@
     }
     uint32_t width = wuffs_base__pixel_config__width(&ic.pixcfg);
     uint32_t height = wuffs_base__pixel_config__height(&ic.pixcfg);
+    background_color = wuffs_base__image_config__background_color(&ic);
     if ((width > MAX_DIMENSION) || (height > MAX_DIMENSION)) {
       return "image dimensions are too large";
     }
@@ -334,7 +342,14 @@
       return status;
     }
     memset(pixbuf.ptr, 0, pixbuf.len);
-    memset(curr_dst_buffer, 0, dst_len);
+  }
+
+  {
+    size_t i;
+    size_t n = dst_len / sizeof(wuffs_base__color_u32_argb_premul);
+    for (i = 0; i < n; i++) {
+      curr_dst_buffer[i] = background_color;
+    }
   }
 
   while (1) {
@@ -423,6 +438,9 @@
     if (!strcmp(argv[i], "-color")) {
       color_flag = true;
     }
+    if (!strcmp(argv[i], "-quirk_background_is_opaque")) {
+      quirk_background_is_opaque_flag = true;
+    }
   }
 
   const char* status = read_stdin();
diff --git a/internal/cgen/base/image-public.h b/internal/cgen/base/image-public.h
index ec65b09..948075e 100644
--- a/internal/cgen/base/image-public.h
+++ b/internal/cgen/base/image-public.h
@@ -538,6 +538,7 @@
   struct {
     uint64_t first_frame_io_position;
     bool first_frame_is_opaque;
+    wuffs_base__color_u32_argb_premul background_color;
   } private_impl;
 
 #ifdef __cplusplus
@@ -546,11 +547,13 @@
                   uint32_t width,
                   uint32_t height,
                   uint64_t first_frame_io_position,
-                  bool first_frame_is_opaque);
+                  bool first_frame_is_opaque,
+                  wuffs_base__color_u32_argb_premul background_color);
   inline void invalidate();
   inline bool is_valid() const;
   inline uint64_t first_frame_io_position() const;
   inline bool first_frame_is_opaque() const;
+  inline wuffs_base__color_u32_argb_premul background_color() const;
 #endif  // __cplusplus
 
 } wuffs_base__image_config;
@@ -566,13 +569,15 @@
 
 // TODO: Should this function return bool? An error type?
 static inline void  //
-wuffs_base__image_config__set(wuffs_base__image_config* c,
-                              wuffs_base__pixel_format pixfmt,
-                              wuffs_base__pixel_subsampling pixsub,
-                              uint32_t width,
-                              uint32_t height,
-                              uint64_t first_frame_io_position,
-                              bool first_frame_is_opaque) {
+wuffs_base__image_config__set(
+    wuffs_base__image_config* c,
+    wuffs_base__pixel_format pixfmt,
+    wuffs_base__pixel_subsampling pixsub,
+    uint32_t width,
+    uint32_t height,
+    uint64_t first_frame_io_position,
+    bool first_frame_is_opaque,
+    wuffs_base__color_u32_argb_premul background_color) {
   if (!c) {
     return;
   }
@@ -583,6 +588,7 @@
     c->pixcfg.private_impl.height = height;
     c->private_impl.first_frame_io_position = first_frame_io_position;
     c->private_impl.first_frame_is_opaque = first_frame_is_opaque;
+    c->private_impl.background_color = background_color;
     return;
   }
 
@@ -592,6 +598,7 @@
   c->pixcfg.private_impl.height = 0;
   c->private_impl.first_frame_io_position = 0;
   c->private_impl.first_frame_is_opaque = 0;
+  c->private_impl.background_color = 0;
 }
 
 static inline void  //
@@ -603,6 +610,7 @@
     c->pixcfg.private_impl.height = 0;
     c->private_impl.first_frame_io_position = 0;
     c->private_impl.first_frame_is_opaque = 0;
+    c->private_impl.background_color = 0;
   }
 }
 
@@ -623,17 +631,25 @@
   return c ? c->private_impl.first_frame_is_opaque : false;
 }
 
+static inline wuffs_base__color_u32_argb_premul  //
+wuffs_base__image_config__background_color(const wuffs_base__image_config* c) {
+  return c ? c->private_impl.background_color : 0;
+}
+
 #ifdef __cplusplus
 
 inline void  //
-wuffs_base__image_config::set(wuffs_base__pixel_format pixfmt,
-                              wuffs_base__pixel_subsampling pixsub,
-                              uint32_t width,
-                              uint32_t height,
-                              uint64_t first_frame_io_position,
-                              bool first_frame_is_opaque) {
+wuffs_base__image_config::set(
+    wuffs_base__pixel_format pixfmt,
+    wuffs_base__pixel_subsampling pixsub,
+    uint32_t width,
+    uint32_t height,
+    uint64_t first_frame_io_position,
+    bool first_frame_is_opaque,
+    wuffs_base__color_u32_argb_premul background_color) {
   wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,
-                                first_frame_io_position, first_frame_is_opaque);
+                                first_frame_io_position, first_frame_is_opaque,
+                                background_color);
 }
 
 inline void  //
@@ -656,6 +672,11 @@
   return wuffs_base__image_config__first_frame_is_opaque(this);
 }
 
+inline wuffs_base__color_u32_argb_premul  //
+wuffs_base__image_config::background_color() const {
+  return wuffs_base__image_config__background_color(this);
+}
+
 #endif  // __cplusplus
 
 // --------
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 832e20c..f05413e 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -126,11 +126,11 @@
 	"((bits_per_pixel % 8) != 0)) {\n    // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n    return 0;\n  }\n  uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n  uint64_t n =\n      ((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);\n  if (n > (UINT64_MAX / bytes_per_pixel)) {\n    return 0;\n  }\n  n *= bytes_per_pixel;\n\n  if (wuffs_base__pixel_format__is_indexed(c->private_impl.pixfmt)) {\n    if (n > (UINT64_MAX - 1024)) {\n      return 0;\n    }\n    n += 1024;\n  }\n\n  return n;\n}\n\n#ifdef __cplusplus\n\ninline void  //\nwuffs_base__pixel_config::set(wuffs_base__pixel_format pixfmt,\n                              wuffs_base__pixel_subsampling pixsub,\n                              uint32_t width,\n                              uint32_t height) {\n  wuffs_base__pixel_config__set(this, pixfmt, pixsub, width, height);\n}\n\ninline void  //\nwuffs_base__pixel_config::invalidate() {\n  wuffs_base__pixel_config__invalidate(this);\n}\n\ninline bool  //\nwuffs_base__pixel_config::is_valid() const {\n  return wuff" +
 	"s_base__pixel_config__is_valid(this);\n}\n\ninline wuffs_base__pixel_format  //\nwuffs_base__pixel_config::pixel_format() const {\n  return wuffs_base__pixel_config__pixel_format(this);\n}\n\ninline wuffs_base__pixel_subsampling  //\nwuffs_base__pixel_config::pixel_subsampling() const {\n  return wuffs_base__pixel_config__pixel_subsampling(this);\n}\n\ninline wuffs_base__rect_ie_u32  //\nwuffs_base__pixel_config::bounds() const {\n  return wuffs_base__pixel_config__bounds(this);\n}\n\ninline uint32_t  //\nwuffs_base__pixel_config::width() const {\n  return wuffs_base__pixel_config__width(this);\n}\n\ninline uint32_t  //\nwuffs_base__pixel_config::height() const {\n  return wuffs_base__pixel_config__height(this);\n}\n\ninline uint64_t  //\nwuffs_base__pixel_config::pixbuf_len() const {\n  return wuffs_base__pixel_config__pixbuf_len(this);\n}\n\n#endif  // __cplusplus\n\n" +
 	"" +
-	"// --------\n\ntypedef struct {\n  wuffs_base__pixel_config pixcfg;\n\n  // Do not access the private_impl's fields directly. There is no API/ABI\n  // compatibility or safety guarantee if you do so.\n  struct {\n    uint64_t first_frame_io_position;\n    bool first_frame_is_opaque;\n  } private_impl;\n\n#ifdef __cplusplus\n  inline void set(wuffs_base__pixel_format pixfmt,\n                  wuffs_base__pixel_subsampling pixsub,\n                  uint32_t width,\n                  uint32_t height,\n                  uint64_t first_frame_io_position,\n                  bool first_frame_is_opaque);\n  inline void invalidate();\n  inline bool is_valid() const;\n  inline uint64_t first_frame_io_position() const;\n  inline bool first_frame_is_opaque() const;\n#endif  // __cplusplus\n\n} wuffs_base__image_config;\n\nstatic inline wuffs_base__image_config  //\nwuffs_base__null_image_config() {\n  wuffs_base__image_config ret;\n  ret.pixcfg = wuffs_base__null_pixel_config();\n  ret.private_impl.first_frame_io_position = 0;\n  ret.private_impl.fir" +
-	"st_frame_is_opaque = false;\n  return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void  //\nwuffs_base__image_config__set(wuffs_base__image_config* c,\n                              wuffs_base__pixel_format pixfmt,\n                              wuffs_base__pixel_subsampling pixsub,\n                              uint32_t width,\n                              uint32_t height,\n                              uint64_t first_frame_io_position,\n                              bool first_frame_is_opaque) {\n  if (!c) {\n    return;\n  }\n  if (wuffs_base__pixel_format__is_valid(pixfmt)) {\n    c->pixcfg.private_impl.pixfmt = pixfmt;\n    c->pixcfg.private_impl.pixsub = pixsub;\n    c->pixcfg.private_impl.width = width;\n    c->pixcfg.private_impl.height = height;\n    c->private_impl.first_frame_io_position = first_frame_io_position;\n    c->private_impl.first_frame_is_opaque = first_frame_is_opaque;\n    return;\n  }\n\n  c->pixcfg.private_impl.pixfmt = 0;\n  c->pixcfg.private_impl.pixsub = 0;\n  c->pix" +
-	"cfg.private_impl.width = 0;\n  c->pixcfg.private_impl.height = 0;\n  c->private_impl.first_frame_io_position = 0;\n  c->private_impl.first_frame_is_opaque = 0;\n}\n\nstatic inline void  //\nwuffs_base__image_config__invalidate(wuffs_base__image_config* c) {\n  if (c) {\n    c->pixcfg.private_impl.pixfmt = 0;\n    c->pixcfg.private_impl.pixsub = 0;\n    c->pixcfg.private_impl.width = 0;\n    c->pixcfg.private_impl.height = 0;\n    c->private_impl.first_frame_io_position = 0;\n    c->private_impl.first_frame_is_opaque = 0;\n  }\n}\n\nstatic inline bool  //\nwuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {\n  return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));\n}\n\nstatic inline uint64_t  //\nwuffs_base__image_config__first_frame_io_position(\n    const wuffs_base__image_config* c) {\n  return c ? c->private_impl.first_frame_io_position : 0;\n}\n\nstatic inline bool  //\nwuffs_base__image_config__first_frame_is_opaque(\n    const wuffs_base__image_config* c) {\n  return c ? c->private_impl.first_frame_is_opaqu" +
-	"e : false;\n}\n\n#ifdef __cplusplus\n\ninline void  //\nwuffs_base__image_config::set(wuffs_base__pixel_format pixfmt,\n                              wuffs_base__pixel_subsampling pixsub,\n                              uint32_t width,\n                              uint32_t height,\n                              uint64_t first_frame_io_position,\n                              bool first_frame_is_opaque) {\n  wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,\n                                first_frame_io_position, first_frame_is_opaque);\n}\n\ninline void  //\nwuffs_base__image_config::invalidate() {\n  wuffs_base__image_config__invalidate(this);\n}\n\ninline bool  //\nwuffs_base__image_config::is_valid() const {\n  return wuffs_base__image_config__is_valid(this);\n}\n\ninline uint64_t  //\nwuffs_base__image_config::first_frame_io_position() const {\n  return wuffs_base__image_config__first_frame_io_position(this);\n}\n\ninline bool  //\nwuffs_base__image_config::first_frame_is_opaque() const {\n  return wuffs_base__image_co" +
-	"nfig__first_frame_is_opaque(this);\n}\n\n#endif  // __cplusplus\n\n" +
+	"// --------\n\ntypedef struct {\n  wuffs_base__pixel_config pixcfg;\n\n  // Do not access the private_impl's fields directly. There is no API/ABI\n  // compatibility or safety guarantee if you do so.\n  struct {\n    uint64_t first_frame_io_position;\n    bool first_frame_is_opaque;\n    wuffs_base__color_u32_argb_premul background_color;\n  } private_impl;\n\n#ifdef __cplusplus\n  inline void set(wuffs_base__pixel_format pixfmt,\n                  wuffs_base__pixel_subsampling pixsub,\n                  uint32_t width,\n                  uint32_t height,\n                  uint64_t first_frame_io_position,\n                  bool first_frame_is_opaque,\n                  wuffs_base__color_u32_argb_premul background_color);\n  inline void invalidate();\n  inline bool is_valid() const;\n  inline uint64_t first_frame_io_position() const;\n  inline bool first_frame_is_opaque() const;\n  inline wuffs_base__color_u32_argb_premul background_color() const;\n#endif  // __cplusplus\n\n} wuffs_base__image_config;\n\nstatic inline wuffs_base__image_" +
+	"config  //\nwuffs_base__null_image_config() {\n  wuffs_base__image_config ret;\n  ret.pixcfg = wuffs_base__null_pixel_config();\n  ret.private_impl.first_frame_io_position = 0;\n  ret.private_impl.first_frame_is_opaque = false;\n  return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void  //\nwuffs_base__image_config__set(\n    wuffs_base__image_config* c,\n    wuffs_base__pixel_format pixfmt,\n    wuffs_base__pixel_subsampling pixsub,\n    uint32_t width,\n    uint32_t height,\n    uint64_t first_frame_io_position,\n    bool first_frame_is_opaque,\n    wuffs_base__color_u32_argb_premul background_color) {\n  if (!c) {\n    return;\n  }\n  if (wuffs_base__pixel_format__is_valid(pixfmt)) {\n    c->pixcfg.private_impl.pixfmt = pixfmt;\n    c->pixcfg.private_impl.pixsub = pixsub;\n    c->pixcfg.private_impl.width = width;\n    c->pixcfg.private_impl.height = height;\n    c->private_impl.first_frame_io_position = first_frame_io_position;\n    c->private_impl.first_frame_is_opaque = first_frame_is_opaque;" +
+	"\n    c->private_impl.background_color = background_color;\n    return;\n  }\n\n  c->pixcfg.private_impl.pixfmt = 0;\n  c->pixcfg.private_impl.pixsub = 0;\n  c->pixcfg.private_impl.width = 0;\n  c->pixcfg.private_impl.height = 0;\n  c->private_impl.first_frame_io_position = 0;\n  c->private_impl.first_frame_is_opaque = 0;\n  c->private_impl.background_color = 0;\n}\n\nstatic inline void  //\nwuffs_base__image_config__invalidate(wuffs_base__image_config* c) {\n  if (c) {\n    c->pixcfg.private_impl.pixfmt = 0;\n    c->pixcfg.private_impl.pixsub = 0;\n    c->pixcfg.private_impl.width = 0;\n    c->pixcfg.private_impl.height = 0;\n    c->private_impl.first_frame_io_position = 0;\n    c->private_impl.first_frame_is_opaque = 0;\n    c->private_impl.background_color = 0;\n  }\n}\n\nstatic inline bool  //\nwuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {\n  return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));\n}\n\nstatic inline uint64_t  //\nwuffs_base__image_config__first_frame_io_position(\n    const wuffs_base__ima" +
+	"ge_config* c) {\n  return c ? c->private_impl.first_frame_io_position : 0;\n}\n\nstatic inline bool  //\nwuffs_base__image_config__first_frame_is_opaque(\n    const wuffs_base__image_config* c) {\n  return c ? c->private_impl.first_frame_is_opaque : false;\n}\n\nstatic inline wuffs_base__color_u32_argb_premul  //\nwuffs_base__image_config__background_color(const wuffs_base__image_config* c) {\n  return c ? c->private_impl.background_color : 0;\n}\n\n#ifdef __cplusplus\n\ninline void  //\nwuffs_base__image_config::set(\n    wuffs_base__pixel_format pixfmt,\n    wuffs_base__pixel_subsampling pixsub,\n    uint32_t width,\n    uint32_t height,\n    uint64_t first_frame_io_position,\n    bool first_frame_is_opaque,\n    wuffs_base__color_u32_argb_premul background_color) {\n  wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,\n                                first_frame_io_position, first_frame_is_opaque,\n                                background_color);\n}\n\ninline void  //\nwuffs_base__image_config::invalidate() {\n  wuffs_ba" +
+	"se__image_config__invalidate(this);\n}\n\ninline bool  //\nwuffs_base__image_config::is_valid() const {\n  return wuffs_base__image_config__is_valid(this);\n}\n\ninline uint64_t  //\nwuffs_base__image_config::first_frame_io_position() const {\n  return wuffs_base__image_config__first_frame_io_position(this);\n}\n\ninline bool  //\nwuffs_base__image_config::first_frame_is_opaque() const {\n  return wuffs_base__image_config__first_frame_is_opaque(this);\n}\n\ninline wuffs_base__color_u32_argb_premul  //\nwuffs_base__image_config::background_color() const {\n  return wuffs_base__image_config__background_color(this);\n}\n\n#endif  // __cplusplus\n\n" +
 	"" +
 	"// --------\n\n// wuffs_base__animation_blend encodes, for an animated image, how to blend the\n// transparent pixels of this frame with the existing canvas. In Porter-Duff\n// compositing operator terminology:\n//  - 0 means the frame may be transparent, and should be blended \"src over\n//    dst\", also known as just \"over\".\n//  - 1 means the frame may be transparent, and should be blended \"src\".\n//  - 2 means the frame is completely opaque, so that \"src over dst\" and \"src\"\n//    are equivalent.\n//\n// These semantics are conservative. It is valid for a completely opaque frame\n// to have a blend value other than 2.\ntypedef uint8_t wuffs_base__animation_blend;\n\n#define WUFFS_BASE__ANIMATION_BLEND__SRC_OVER_DST \\\n  ((wuffs_base__animation_blend)0)\n#define WUFFS_BASE__ANIMATION_BLEND__SRC ((wuffs_base__animation_blend)1)\n#define WUFFS_BASE__ANIMATION_BLEND__OPAQUE ((wuffs_base__animation_blend)2)\n\n" +
 	"" +
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index 8ec2a1d..96f7a62 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -312,7 +312,7 @@
 	// ---- image_config
 
 	"image_config.set!(pixfmt u32, pixsub u32, width u32, height u32, " +
-		"first_frame_io_position u64, first_frame_is_opaque bool)",
+		"first_frame_io_position u64, first_frame_is_opaque bool, background_color u32)",
 
 	// ---- pixel_buffer
 
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 71fbd24..5b40d60 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -2068,6 +2068,7 @@
   struct {
     uint64_t first_frame_io_position;
     bool first_frame_is_opaque;
+    wuffs_base__color_u32_argb_premul background_color;
   } private_impl;
 
 #ifdef __cplusplus
@@ -2076,11 +2077,13 @@
                   uint32_t width,
                   uint32_t height,
                   uint64_t first_frame_io_position,
-                  bool first_frame_is_opaque);
+                  bool first_frame_is_opaque,
+                  wuffs_base__color_u32_argb_premul background_color);
   inline void invalidate();
   inline bool is_valid() const;
   inline uint64_t first_frame_io_position() const;
   inline bool first_frame_is_opaque() const;
+  inline wuffs_base__color_u32_argb_premul background_color() const;
 #endif  // __cplusplus
 
 } wuffs_base__image_config;
@@ -2096,13 +2099,15 @@
 
 // TODO: Should this function return bool? An error type?
 static inline void  //
-wuffs_base__image_config__set(wuffs_base__image_config* c,
-                              wuffs_base__pixel_format pixfmt,
-                              wuffs_base__pixel_subsampling pixsub,
-                              uint32_t width,
-                              uint32_t height,
-                              uint64_t first_frame_io_position,
-                              bool first_frame_is_opaque) {
+wuffs_base__image_config__set(
+    wuffs_base__image_config* c,
+    wuffs_base__pixel_format pixfmt,
+    wuffs_base__pixel_subsampling pixsub,
+    uint32_t width,
+    uint32_t height,
+    uint64_t first_frame_io_position,
+    bool first_frame_is_opaque,
+    wuffs_base__color_u32_argb_premul background_color) {
   if (!c) {
     return;
   }
@@ -2113,6 +2118,7 @@
     c->pixcfg.private_impl.height = height;
     c->private_impl.first_frame_io_position = first_frame_io_position;
     c->private_impl.first_frame_is_opaque = first_frame_is_opaque;
+    c->private_impl.background_color = background_color;
     return;
   }
 
@@ -2122,6 +2128,7 @@
   c->pixcfg.private_impl.height = 0;
   c->private_impl.first_frame_io_position = 0;
   c->private_impl.first_frame_is_opaque = 0;
+  c->private_impl.background_color = 0;
 }
 
 static inline void  //
@@ -2133,6 +2140,7 @@
     c->pixcfg.private_impl.height = 0;
     c->private_impl.first_frame_io_position = 0;
     c->private_impl.first_frame_is_opaque = 0;
+    c->private_impl.background_color = 0;
   }
 }
 
@@ -2153,17 +2161,25 @@
   return c ? c->private_impl.first_frame_is_opaque : false;
 }
 
+static inline wuffs_base__color_u32_argb_premul  //
+wuffs_base__image_config__background_color(const wuffs_base__image_config* c) {
+  return c ? c->private_impl.background_color : 0;
+}
+
 #ifdef __cplusplus
 
 inline void  //
-wuffs_base__image_config::set(wuffs_base__pixel_format pixfmt,
-                              wuffs_base__pixel_subsampling pixsub,
-                              uint32_t width,
-                              uint32_t height,
-                              uint64_t first_frame_io_position,
-                              bool first_frame_is_opaque) {
+wuffs_base__image_config::set(
+    wuffs_base__pixel_format pixfmt,
+    wuffs_base__pixel_subsampling pixsub,
+    uint32_t width,
+    uint32_t height,
+    uint64_t first_frame_io_position,
+    bool first_frame_is_opaque,
+    wuffs_base__color_u32_argb_premul background_color) {
   wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,
-                                first_frame_io_position, first_frame_is_opaque);
+                                first_frame_io_position, first_frame_is_opaque,
+                                background_color);
 }
 
 inline void  //
@@ -2186,6 +2202,11 @@
   return wuffs_base__image_config__first_frame_is_opaque(this);
 }
 
+inline wuffs_base__color_u32_argb_premul  //
+wuffs_base__image_config::background_color() const {
+  return wuffs_base__image_config__background_color(this);
+}
+
 #endif  // __cplusplus
 
 // --------
@@ -3290,10 +3311,10 @@
     wuffs_gif__quirk_image_bounds_are_strict  //
         WUFFS_BASE__POTENTIALLY_UNUSED = 1041635330;
 
-#define WUFFS_GIF__QUIRK_INITIAL_BACKGROUND_IS_OPAQUE 1041635331
+#define WUFFS_GIF__QUIRK_BACKGROUND_IS_OPAQUE 1041635331
 
-static const uint32_t                              //
-    wuffs_gif__quirk_initial_background_is_opaque  //
+static const uint32_t                      //
+    wuffs_gif__quirk_background_is_opaque  //
         WUFFS_BASE__POTENTIALLY_UNUSED = 1041635331;
 
 #define WUFFS_GIF__QUIRK_REJECT_EMPTY_PALETTE 1041635332
@@ -3416,7 +3437,7 @@
     uint64_t f_metadata_io_position;
     bool f_quirk_enabled_ignore_too_much_pixel_data;
     bool f_quirk_enabled_image_bounds_are_strict;
-    bool f_quirk_enabled_initial_background_is_opaque;
+    bool f_quirk_enabled_background_is_opaque;
     bool f_quirk_enabled_reject_empty_palette;
     bool f_end_of_data;
     bool f_restarted;
@@ -3425,6 +3446,7 @@
     uint8_t f_interlace;
     bool f_seen_num_loops;
     uint32_t f_num_loops;
+    uint32_t f_background_color_u32_argb_premul;
     bool f_gc_has_transparent_index;
     uint8_t f_gc_transparent_index;
     uint8_t f_gc_disposal;
@@ -3475,6 +3497,7 @@
     } s_decode_header[1];
     struct {
       uint8_t v_flags;
+      uint8_t v_background_color_index;
       uint32_t v_num_palette_entries;
       uint32_t v_i;
       uint64_t scratch;
@@ -8713,7 +8736,7 @@
   } else if (a_quirk == 1041635330) {
     self->private_impl.f_quirk_enabled_image_bounds_are_strict = a_enabled;
   } else if (a_quirk == 1041635331) {
-    self->private_impl.f_quirk_enabled_initial_background_is_opaque = a_enabled;
+    self->private_impl.f_quirk_enabled_background_is_opaque = a_enabled;
   } else if (a_quirk == 1041635332) {
     self->private_impl.f_quirk_enabled_reject_empty_palette = a_enabled;
   }
@@ -8771,7 +8794,7 @@
       goto suspend;
     }
     v_ffio = !self->private_impl.f_gc_has_transparent_index;
-    if (!self->private_impl.f_quirk_enabled_initial_background_is_opaque) {
+    if (!self->private_impl.f_quirk_enabled_background_is_opaque) {
       v_ffio =
           (v_ffio && (self->private_impl.f_frame_rect_x0 == 0) &&
            (self->private_impl.f_frame_rect_y0 == 0) &&
@@ -8782,7 +8805,8 @@
       wuffs_base__image_config__set(
           a_dst, 1191444488, 0, self->private_impl.f_width,
           self->private_impl.f_height,
-          self->private_impl.f_frame_config_io_position, v_ffio);
+          self->private_impl.f_frame_config_io_position, v_ffio,
+          self->private_impl.f_background_color_u32_argb_premul);
     }
     self->private_impl.f_call_sequence = 3;
 
@@ -9586,8 +9610,10 @@
   wuffs_base__status status = NULL;
 
   uint8_t v_flags = 0;
+  uint8_t v_background_color_index = 0;
   uint32_t v_num_palette_entries = 0;
   uint32_t v_i = 0;
+  uint32_t v_j = 0;
   uint32_t v_argb = 0;
 
   uint8_t* iop_a_src = NULL;
@@ -9608,6 +9634,8 @@
   uint32_t coro_susp_point = self->private_impl.p_decode_lsd[0];
   if (coro_susp_point) {
     v_flags = self->private_data.s_decode_lsd[0].v_flags;
+    v_background_color_index =
+        self->private_data.s_decode_lsd[0].v_background_color_index;
     v_num_palette_entries =
         self->private_data.s_decode_lsd[0].v_num_palette_entries;
     v_i = self->private_data.s_decode_lsd[0].v_i;
@@ -9682,50 +9710,54 @@
       uint8_t t_2 = *iop_a_src++;
       v_flags = t_2;
     }
-    self->private_data.s_decode_lsd[0].scratch = 2;
-    WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
-    if (self->private_data.s_decode_lsd[0].scratch >
-        ((uint64_t)(io1_a_src - iop_a_src))) {
-      self->private_data.s_decode_lsd[0].scratch -=
-          ((uint64_t)(io1_a_src - iop_a_src));
-      iop_a_src = io1_a_src;
+    {
+      WUFFS_BASE__COROUTINE_SUSPENSION_POINT(6);
+      if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
+        status = wuffs_base__suspension__short_read;
+        goto suspend;
+      }
+      uint8_t t_3 = *iop_a_src++;
+      v_background_color_index = t_3;
+    }
+    WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
+    if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
       status = wuffs_base__suspension__short_read;
       goto suspend;
     }
-    iop_a_src += self->private_data.s_decode_lsd[0].scratch;
+    iop_a_src++;
     v_i = 0;
     self->private_impl.f_has_global_palette = ((v_flags & 128) != 0);
     if (self->private_impl.f_has_global_palette) {
       v_num_palette_entries = (((uint32_t)(1)) << (1 + (v_flags & 7)));
       while (v_i < v_num_palette_entries) {
         {
-          WUFFS_BASE__COROUTINE_SUSPENSION_POINT(7);
-          uint32_t t_3;
+          WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
+          uint32_t t_4;
           if (WUFFS_BASE__LIKELY(io1_a_src - iop_a_src >= 3)) {
-            t_3 = ((uint32_t)(wuffs_base__load_u24be(iop_a_src)));
+            t_4 = ((uint32_t)(wuffs_base__load_u24be(iop_a_src)));
             iop_a_src += 3;
           } else {
             self->private_data.s_decode_lsd[0].scratch = 0;
-            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(8);
+            WUFFS_BASE__COROUTINE_SUSPENSION_POINT(9);
             while (true) {
               if (WUFFS_BASE__UNLIKELY(iop_a_src == io1_a_src)) {
                 status = wuffs_base__suspension__short_read;
                 goto suspend;
               }
               uint64_t* scratch = &self->private_data.s_decode_lsd[0].scratch;
-              uint32_t num_bits_3 = ((uint32_t)(*scratch & 0xFF));
+              uint32_t num_bits_4 = ((uint32_t)(*scratch & 0xFF));
               *scratch >>= 8;
               *scratch <<= 8;
-              *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_3);
-              if (num_bits_3 == 16) {
-                t_3 = ((uint32_t)(*scratch >> 40));
+              *scratch |= ((uint64_t)(*iop_a_src++)) << (56 - num_bits_4);
+              if (num_bits_4 == 16) {
+                t_4 = ((uint32_t)(*scratch >> 40));
                 break;
               }
-              num_bits_3 += 8;
-              *scratch |= ((uint64_t)(num_bits_3));
+              num_bits_4 += 8;
+              *scratch |= ((uint64_t)(num_bits_4));
             }
           }
-          v_argb = t_3;
+          v_argb = t_4;
         }
         v_argb |= 4278190080;
         self->private_data.f_palettes[0][((4 * v_i) + 0)] =
@@ -9738,6 +9770,23 @@
             ((uint8_t)(((v_argb >> 24) & 255)));
         v_i += 1;
       }
+      if (self->private_impl.f_quirk_enabled_background_is_opaque) {
+        if ((v_background_color_index != 0) &&
+            (((uint32_t)(v_background_color_index)) < v_num_palette_entries)) {
+          v_j = (4 * ((uint32_t)(v_background_color_index)));
+          self->private_impl.f_background_color_u32_argb_premul =
+              ((((uint32_t)(self->private_data.f_palettes[0][(v_j + 0)]))
+                << 0) |
+               (((uint32_t)(self->private_data.f_palettes[0][(v_j + 1)]))
+                << 8) |
+               (((uint32_t)(self->private_data.f_palettes[0][(v_j + 2)]))
+                << 16) |
+               (((uint32_t)(self->private_data.f_palettes[0][(v_j + 3)]))
+                << 24));
+        } else {
+          self->private_impl.f_background_color_u32_argb_premul = 4278190080;
+        }
+      }
     }
     while (v_i < 256) {
       self->private_data.f_palettes[0][((4 * v_i) + 0)] = 0;
@@ -9758,6 +9807,8 @@
   self->private_impl.p_decode_lsd[0] =
       wuffs_base__status__is_suspension(status) ? coro_susp_point : 0;
   self->private_data.s_decode_lsd[0].v_flags = v_flags;
+  self->private_data.s_decode_lsd[0].v_background_color_index =
+      v_background_color_index;
   self->private_data.s_decode_lsd[0].v_num_palette_entries =
       v_num_palette_entries;
   self->private_data.s_decode_lsd[0].v_i = v_i;
diff --git a/script/make-artificial.go b/script/make-artificial.go
index 4c65088..a8c74c6 100644
--- a/script/make-artificial.go
+++ b/script/make-artificial.go
@@ -499,8 +499,9 @@
 }
 
 var gifGlobals struct {
-	imageWidth  uint32
-	imageHeight uint32
+	imageWidth                uint32
+	imageHeight               uint32
+	imageBackgroundColorIndex uint32
 
 	frameLeft   uint32
 	frameTop    uint32
@@ -646,7 +647,7 @@
 		} else {
 			out = append(out, 0x80|uint8(n-1))
 		}
-		out = append(out, 0x00) // TODO: background index.
+		out = append(out, uint8(g.imageBackgroundColorIndex))
 		out = append(out, 0x00)
 		for _, x := range g.globalPalette {
 			out = append(out, x[0], x[1], x[2])
@@ -655,10 +656,18 @@
 	}
 
 	const (
+		cmdBCI = "backgroundColorIndex "
 		cmdIWH = "imageWidthHeight "
 		cmdP   = "palette {"
 	)
 	switch {
+	case strings.HasPrefix(line, cmdBCI):
+		s := line[len(cmdBCI):]
+		if i, _, ok := parseNum(s); ok {
+			g.imageBackgroundColorIndex = i
+		}
+		return stateGifImage, nil
+
 	case strings.HasPrefix(line, cmdIWH):
 		s := line[len(cmdIWH):]
 		if w, s, ok := parseNum(s); ok {
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index dee425c..3298f3b 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -52,10 +52,18 @@
 // https://github.com/google/wuffs/blob/master/test/data/artificial/gif-frame-out-of-bounds.gif.make-artificial.txt
 pub const quirk_image_bounds_are_strict base.u32 = (0xF8586 << 10) | 2
 
-// When this quirk is enabled, if the initial frame bounds is smaller than the
-// image bounds, those pixels outside the initial frame bounds are assumed to
-// start as opaque black instead of transparent black.
-pub const quirk_initial_background_is_opaque base.u32 = (0xF8586 << 10) | 3
+// When this quirk is enabled, the background color is opaque instead of always
+// being transparent black. If the background color index in the GIF header is
+// non-zero but less than the global palette's size, the background color is
+// that global palette's entry. Otherwise, it is opaque black.
+//
+// Specifically, if the initial frame bounds is smaller than the image bounds,
+// those pixels outside the initial frame bounds are assumed to start as that
+// opaque background color. The same color should be used when processing
+// WUFFS_BASE__ANIMATION_DISPOSAL__RESTORE_BACKGROUND. In both cases, the
+// caller of Wuffs, not Wuffs itself, is responsible for filling the pixel
+// buffer with that color.
+pub const quirk_background_is_opaque base.u32 = (0xF8586 << 10) | 3
 
 // When this quirk is enabled, a frame with no explicit palette is rejected,
 // instead of implicitly having a palette with every entry being opaque black.
@@ -127,10 +135,10 @@
 	metadata_chunk_length_value base.u64,
 	metadata_io_position        base.u64,
 
-	quirk_enabled_ignore_too_much_pixel_data   base.bool,
-	quirk_enabled_image_bounds_are_strict      base.bool,
-	quirk_enabled_initial_background_is_opaque base.bool,
-	quirk_enabled_reject_empty_palette         base.bool,
+	quirk_enabled_ignore_too_much_pixel_data base.bool,
+	quirk_enabled_image_bounds_are_strict    base.bool,
+	quirk_enabled_background_is_opaque       base.bool,
+	quirk_enabled_reject_empty_palette       base.bool,
 
 	end_of_data                        base.bool,
 	restarted                          base.bool,
@@ -146,6 +154,8 @@
 	seen_num_loops base.bool,
 	num_loops      base.u32,
 
+	background_color_u32_argb_premul base.u32,
+
 	gc_has_transparent_index base.bool,
 	gc_transparent_index     base.u8,
 	gc_disposal              base.u8,
@@ -188,8 +198,8 @@
 		this.quirk_enabled_ignore_too_much_pixel_data = args.enabled
 	} else if args.quirk == quirk_image_bounds_are_strict {
 		this.quirk_enabled_image_bounds_are_strict = args.enabled
-	} else if args.quirk == quirk_initial_background_is_opaque {
-		this.quirk_enabled_initial_background_is_opaque = args.enabled
+	} else if args.quirk == quirk_background_is_opaque {
+		this.quirk_enabled_background_is_opaque = args.enabled
 	} else if args.quirk == quirk_reject_empty_palette {
 		this.quirk_enabled_reject_empty_palette = args.enabled
 	}
@@ -210,7 +220,7 @@
 	// TODO: if this.end_of_data, return an error and/or set dst to zero?
 
 	ffio = not this.gc_has_transparent_index
-	if not this.quirk_enabled_initial_background_is_opaque {
+	if not this.quirk_enabled_background_is_opaque {
 		ffio = ffio and
 			(this.frame_rect_x0 == 0) and
 			(this.frame_rect_y0 == 0) and
@@ -227,7 +237,8 @@
 			width:this.width,
 			height:this.height,
 			first_frame_io_position:this.frame_config_io_position,
-			first_frame_is_opaque:ffio)
+			first_frame_is_opaque:ffio,
+			background_color:this.background_color_u32_argb_premul)
 	}
 
 	this.call_sequence = 3
@@ -469,16 +480,19 @@
 //
 // See the spec section 18 "Logical Screen Descriptor" on page 8.
 pri func decoder.decode_lsd?(src base.io_reader) {
-	var flags               base.u8
-	var num_palette_entries base.u32[..256]
-	var i                   base.u32
-	var argb                base.u32
+	var flags                  base.u8
+	var background_color_index base.u8
+	var num_palette_entries    base.u32[..256]
+	var i                      base.u32
+	var j                      base.u32[..1020]
+	var argb                   base.u32
 
 	this.width = args.src.read_u16le_as_u32?()
 	this.height = args.src.read_u16le_as_u32?()
 	flags = args.src.read_u8?()
-	// Ignore the Background Color Index and Pixel Aspect Ratio bytes.
-	args.src.skip?(n:2)
+	background_color_index = args.src.read_u8?()
+	// Ignore the Pixel Aspect Ratio byte.
+	args.src.skip?(n:1)
 
 	// Read the optional Global Color Table.
 	i = 0
@@ -497,6 +511,21 @@
 			this.palettes[0][(4 * i) + 3] = ((argb >> 24) & 0xFF) as base.u8
 			i += 1
 		}
+
+		if this.quirk_enabled_background_is_opaque {
+			if (background_color_index <> 0) and
+				((background_color_index as base.u32) < num_palette_entries) {
+
+				j = 4 * (background_color_index as base.u32)
+				this.background_color_u32_argb_premul =
+					((this.palettes[0][j + 0] as base.u32) << 0) |
+					((this.palettes[0][j + 1] as base.u32) << 8) |
+					((this.palettes[0][j + 2] as base.u32) << 16) |
+					((this.palettes[0][j + 3] as base.u32) << 24)
+			} else {
+				this.background_color_u32_argb_premul = 0xFF000000
+			}
+		}
 	}
 
 	// Set the remaining palette entries to opaque black.
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index 42fca32..bfc55ee 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -797,6 +797,48 @@
   return NULL;
 }
 
+const char* test_wuffs_gif_decode_background_color() {
+  CHECK_FOCUS(__func__);
+  wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
+      .data = global_src_slice,
+  });
+  const char* status =
+      read_file(&src, "test/data/artificial/gif-background-color.gif");
+  if (status) {
+    return status;
+  }
+  int q;
+  for (q = 0; q < 2; q++) {
+    src.meta.ri = 0;
+
+    wuffs_gif__decoder dec;
+    status = wuffs_gif__decoder__initialize(
+        &dec, sizeof dec, WUFFS_VERSION,
+        WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED);
+    if (status) {
+      RETURN_FAIL("q=%d: initialize: \"%s\"", q, status);
+    }
+    wuffs_gif__decoder__set_quirk_enabled(
+        &dec, wuffs_gif__quirk_background_is_opaque, q);
+
+    wuffs_base__image_config ic = ((wuffs_base__image_config){});
+    wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
+    status = wuffs_gif__decoder__decode_image_config(&dec, &ic, src_reader);
+    if (status) {
+      RETURN_FAIL("q=%d: decode_image_config: \"%s\"", q, status);
+    }
+
+    wuffs_base__color_u32_argb_premul got =
+        wuffs_base__image_config__background_color(&ic);
+    wuffs_base__color_u32_argb_premul want = q ? 0xFF80C3C3 : 0x00000000;
+
+    if (got != want) {
+      RETURN_FAIL("q=%d: got 0x%08" PRIX32 ", want 0x%08" PRIX32, q, got, want);
+    }
+  }
+  return NULL;
+}
+
 const char* test_wuffs_gif_decode_first_frame_is_opaque() {
   CHECK_FOCUS(__func__);
   wuffs_base__io_buffer src = ((wuffs_base__io_buffer){
@@ -819,7 +861,7 @@
       RETURN_FAIL("q=%d: initialize: \"%s\"", q, status);
     }
     wuffs_gif__decoder__set_quirk_enabled(
-        &dec, wuffs_gif__quirk_initial_background_is_opaque, q);
+        &dec, wuffs_gif__quirk_background_is_opaque, q);
 
     wuffs_base__image_config ic = ((wuffs_base__image_config){});
     wuffs_base__io_reader src_reader = wuffs_base__io_buffer__reader(&src);
@@ -2048,6 +2090,7 @@
     test_wuffs_gif_decode_animated_big,                      //
     test_wuffs_gif_decode_animated_medium,                   //
     test_wuffs_gif_decode_animated_small,                    //
+    test_wuffs_gif_decode_background_color,                  //
     test_wuffs_gif_decode_bgra_nonpremul,                    //
     test_wuffs_gif_decode_empty_palette,                     //
     test_wuffs_gif_decode_first_frame_is_opaque,             //
diff --git a/test/data/artificial/gif-background-color.gif b/test/data/artificial/gif-background-color.gif
new file mode 100644
index 0000000..d25e59e
--- /dev/null
+++ b/test/data/artificial/gif-background-color.gif
Binary files differ
diff --git a/test/data/artificial/gif-background-color.gif.make-artificial.txt b/test/data/artificial/gif-background-color.gif.make-artificial.txt
new file mode 100644
index 0000000..390cf63
--- /dev/null
+++ b/test/data/artificial/gif-background-color.gif.make-artificial.txt
@@ -0,0 +1,36 @@
+# Feed this file to script/make-artificial.go
+
+make gif
+
+header
+
+image {
+	imageWidthHeight 4 1
+	backgroundColorIndex 3
+	palette {
+		0x80 0x00 0x00
+		0x80 0x00 0xC1
+		0x80 0xC2 0x00
+		0x80 0xC3 0xC3
+	}
+}
+
+loopCount 1
+
+# TODO: graphicControl animationDisposalRestoreBackground 100ms
+bytes 0x21 0xF9 0x04 0x08 0x0A 0x00 0x00 0x00
+
+frame {
+	frameLeftTopWidthHeight 0 0 2 1
+}
+lzw 2 0x00 0x01
+
+# TODO: graphicControl animationDisposalRestoreBackground 200ms
+bytes 0x21 0xF9 0x04 0x08 0x14 0x00 0x00 0x00
+
+frame {
+	frameLeftTopWidthHeight 2 0 1 1
+}
+lzw 2 0x02
+
+trailer