Add wuffs_base__pixel_buffer__set_from_table
diff --git a/internal/cgen/base/image-public.h b/internal/cgen/base/image-public.h
index 29cce4e..9961d73 100644
--- a/internal/cgen/base/image-public.h
+++ b/internal/cgen/base/image-public.h
@@ -908,6 +908,8 @@
 #ifdef __cplusplus
   inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,
                                            wuffs_base__slice_u8 pixbuf_memory);
+  inline wuffs_base__status set_from_table(wuffs_base__pixel_config* pixcfg,
+                                           wuffs_base__table_u8 pixbuf_memory);
   inline wuffs_base__slice_u8 palette();
   inline wuffs_base__pixel_format pixel_format() const;
   inline wuffs_base__table_u8 plane(uint32_t p);
@@ -991,6 +993,38 @@
   return NULL;
 }
 
+static inline wuffs_base__status  //
+wuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* b,
+                                         wuffs_base__pixel_config* pixcfg,
+                                         wuffs_base__table_u8 pixbuf_memory) {
+  if (!b) {
+    return wuffs_base__error__bad_receiver;
+  }
+  memset(b, 0, sizeof(*b));
+  if (!pixcfg ||
+      wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {
+    return wuffs_base__error__bad_argument;
+  }
+  uint32_t bits_per_pixel =
+      wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);
+  if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
+    // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
+    return wuffs_base__error__unsupported_option;
+  }
+  uint64_t bytes_per_pixel = bits_per_pixel / 8;
+
+  uint64_t width_in_bytes =
+      ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
+  if ((width_in_bytes > pixbuf_memory.width) ||
+      (pixcfg->private_impl.height > pixbuf_memory.height)) {
+    return wuffs_base__error__bad_argument;
+  }
+
+  b->pixcfg = *pixcfg;
+  b->private_impl.planes[0] = pixbuf_memory;
+  return NULL;
+}
+
 // wuffs_base__pixel_buffer__palette returns the palette color data. If
 // non-empty, it will have length 1024.
 static inline wuffs_base__slice_u8  //
@@ -1036,6 +1070,12 @@
   return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);
 }
 
+inline wuffs_base__status  //
+wuffs_base__pixel_buffer::set_from_table(wuffs_base__pixel_config* pixcfg,
+                                         wuffs_base__table_u8 pixbuf_memory) {
+  return wuffs_base__pixel_buffer__set_from_table(this, pixcfg, pixbuf_memory);
+}
+
 inline wuffs_base__slice_u8  //
 wuffs_base__pixel_buffer::palette() {
   return wuffs_base__pixel_buffer__palette(this);
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 37b62df..188ee94 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -146,12 +146,13 @@
 	"ase__frame_config::bounds() const {\n  return wuffs_base__frame_config__bounds(this);\n}\n\ninline uint32_t  //\nwuffs_base__frame_config::width() const {\n  return wuffs_base__frame_config__width(this);\n}\n\ninline uint32_t  //\nwuffs_base__frame_config::height() const {\n  return wuffs_base__frame_config__height(this);\n}\n\ninline wuffs_base__flicks  //\nwuffs_base__frame_config::duration() const {\n  return wuffs_base__frame_config__duration(this);\n}\n\ninline uint64_t  //\nwuffs_base__frame_config::index() const {\n  return wuffs_base__frame_config__index(this);\n}\n\ninline uint64_t  //\nwuffs_base__frame_config::io_position() const {\n  return wuffs_base__frame_config__io_position(this);\n}\n\ninline wuffs_base__animation_blend  //\nwuffs_base__frame_config::blend() const {\n  return wuffs_base__frame_config__blend(this);\n}\n\ninline wuffs_base__animation_disposal  //\nwuffs_base__frame_config::disposal() const {\n  return wuffs_base__frame_config__disposal(this);\n}\n\ninline wuffs_base__color_u32_argb_premul  //\nwuffs_base__frame_confi" +
 	"g::background_color() const {\n  return wuffs_base__frame_config__background_color(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    wuffs_base__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];\n    // TODO: color spaces.\n  } private_impl;\n\n#ifdef __cplusplus\n  inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,\n                                           wuffs_base__slice_u8 pixbuf_memory);\n  inline wuffs_base__slice_u8 palette();\n  inline wuffs_base__pixel_format pixel_format() const;\n  inline wuffs_base__table_u8 plane(uint32_t p);\n#endif  // __cplusplus\n\n} wuffs_base__pixel_buffer;\n\nstatic inline wuffs_base__pixel_buffer  //\nwuffs_base__null_pixel_buffer() {\n  wuffs_base__pixel_buffer ret;\n  ret.pixcfg = wuffs_base__null_pixel_config();\n  ret.private_impl.planes[0] = wuffs_base__null_table_u8();\n  ret.private_impl.planes[1] = wuffs_base__null_table_u8();\n  ret.private_impl.planes[2] = wuffs_base__nul" +
-	"l_table_u8();\n  ret.private_impl.planes[3] = wuffs_base__null_table_u8();\n  return ret;\n}\n\nstatic inline wuffs_base__status  //\nwuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* b,\n                                         wuffs_base__pixel_config* pixcfg,\n                                         wuffs_base__slice_u8 pixbuf_memory) {\n  if (!b) {\n    return wuffs_base__error__bad_receiver;\n  }\n  memset(b, 0, sizeof(*b));\n  if (!pixcfg) {\n    return wuffs_base__error__bad_argument;\n  }\n  if (wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {\n    // TODO: support planar pixel formats, concious of pixel subsampling.\n    return wuffs_base__error__unsupported_option;\n  }\n  uint32_t bits_per_pixel =\n      wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);\n  if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {\n    // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n    return wuffs_base__error__unsupported_option;\n  }\n  uint64_t bytes_per_pixel =" +
-	" bits_per_pixel / 8;\n\n  uint8_t* ptr = pixbuf_memory.ptr;\n  uint64_t len = pixbuf_memory.len;\n  if (wuffs_base__pixel_format__is_indexed(pixcfg->private_impl.pixfmt)) {\n    // Split a 1024 byte chunk (256 palette entries × 4 bytes per entry) from\n    // the start of pixbuf_memory. We split from the start, not the end, so\n    // that the both chunks' pointers have the same alignment as the original\n    // pointer, up to an alignment of 1024.\n    if (len < 1024) {\n      return wuffs_base__error__bad_argument_length_too_short;\n    }\n    wuffs_base__table_u8* tab =\n        &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n    tab->ptr = ptr;\n    tab->width = 1024;\n    tab->height = 1;\n    tab->stride = 1024;\n    ptr += 1024;\n    len -= 1024;\n  }\n\n  uint64_t wh = ((uint64_t)pixcfg->private_impl.width) *\n                ((uint64_t)pixcfg->private_impl.height);\n  size_t width = (size_t)(pixcfg->private_impl.width);\n  if ((wh > (UINT64_MAX / bytes_per_pixel)) ||\n      (width > (SIZE_MAX / byte" +
-	"s_per_pixel))) {\n    return wuffs_base__error__bad_argument;\n  }\n  wh *= bytes_per_pixel;\n  width *= bytes_per_pixel;\n  if (wh > len) {\n    return wuffs_base__error__bad_argument_length_too_short;\n  }\n\n  b->pixcfg = *pixcfg;\n  wuffs_base__table_u8* tab = &b->private_impl.planes[0];\n  tab->ptr = ptr;\n  tab->width = width;\n  tab->height = pixcfg->private_impl.height;\n  tab->stride = width;\n  return NULL;\n}\n\n// wuffs_base__pixel_buffer__palette returns the palette color data. If\n// non-empty, it will have length 1024.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* b) {\n  if (b &&\n      wuffs_base__pixel_format__is_indexed(b->pixcfg.private_impl.pixfmt)) {\n    wuffs_base__table_u8* tab =\n        &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n    if ((tab->width == 1024) && (tab->height == 1)) {\n      return wuffs_base__make_slice_u8(tab->ptr, 1024);\n    }\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__pixe" +
-	"l_format  //\nwuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* b) {\n  if (b) {\n    return b->pixcfg.private_impl.pixfmt;\n  }\n  return WUFFS_BASE__PIXEL_FORMAT__INVALID;\n}\n\nstatic inline wuffs_base__table_u8  //\nwuffs_base__pixel_buffer__plane(wuffs_base__pixel_buffer* b, uint32_t p) {\n  if (b && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX)) {\n    return b->private_impl.planes[p];\n  }\n\n  wuffs_base__table_u8 ret;\n  ret.ptr = NULL;\n  ret.width = 0;\n  ret.height = 0;\n  ret.stride = 0;\n  return ret;\n}\n\n#ifdef __cplusplus\n\ninline wuffs_base__status  //\nwuffs_base__pixel_buffer::set_from_slice(wuffs_base__pixel_config* pixcfg,\n                                         wuffs_base__slice_u8 pixbuf_memory) {\n  return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);\n}\n\ninline wuffs_base__slice_u8  //\nwuffs_base__pixel_buffer::palette() {\n  return wuffs_base__pixel_buffer__palette(this);\n}\n\ninline wuffs_base__pixel_format  //\nwuffs_base__pixel_buffer::pixel_format() const {\n  " +
-	"return wuffs_base__pixel_buffer__pixel_format(this);\n}\n\ninline wuffs_base__table_u8  //\nwuffs_base__pixel_buffer::plane(uint32_t p) {\n  return wuffs_base__pixel_buffer__plane(this, p);\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    wuffs_base__table_u8 planes[WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX];\n    // TODO: color spaces.\n  } private_impl;\n\n#ifdef __cplusplus\n  inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,\n                                           wuffs_base__slice_u8 pixbuf_memory);\n  inline wuffs_base__status set_from_table(wuffs_base__pixel_config* pixcfg,\n                                           wuffs_base__table_u8 pixbuf_memory);\n  inline wuffs_base__slice_u8 palette();\n  inline wuffs_base__pixel_format pixel_format() const;\n  inline wuffs_base__table_u8 plane(uint32_t p);\n#endif  // __cplusplus\n\n} wuffs_base__pixel_buffer;\n\nstatic inline wuffs_base__pixel_buffer  //\nwuffs_base__null_pixel_buffer() {\n  wuffs_base__pixel_buffer ret;\n  ret.pixcfg = wuffs_base__null_pixel_config();\n  ret.pri" +
+	"vate_impl.planes[0] = wuffs_base__null_table_u8();\n  ret.private_impl.planes[1] = wuffs_base__null_table_u8();\n  ret.private_impl.planes[2] = wuffs_base__null_table_u8();\n  ret.private_impl.planes[3] = wuffs_base__null_table_u8();\n  return ret;\n}\n\nstatic inline wuffs_base__status  //\nwuffs_base__pixel_buffer__set_from_slice(wuffs_base__pixel_buffer* b,\n                                         wuffs_base__pixel_config* pixcfg,\n                                         wuffs_base__slice_u8 pixbuf_memory) {\n  if (!b) {\n    return wuffs_base__error__bad_receiver;\n  }\n  memset(b, 0, sizeof(*b));\n  if (!pixcfg) {\n    return wuffs_base__error__bad_argument;\n  }\n  if (wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {\n    // TODO: support planar pixel formats, concious of pixel subsampling.\n    return wuffs_base__error__unsupported_option;\n  }\n  uint32_t bits_per_pixel =\n      wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);\n  if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) !=" +
+	" 0)) {\n    // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n    return wuffs_base__error__unsupported_option;\n  }\n  uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n  uint8_t* ptr = pixbuf_memory.ptr;\n  uint64_t len = pixbuf_memory.len;\n  if (wuffs_base__pixel_format__is_indexed(pixcfg->private_impl.pixfmt)) {\n    // Split a 1024 byte chunk (256 palette entries × 4 bytes per entry) from\n    // the start of pixbuf_memory. We split from the start, not the end, so\n    // that the both chunks' pointers have the same alignment as the original\n    // pointer, up to an alignment of 1024.\n    if (len < 1024) {\n      return wuffs_base__error__bad_argument_length_too_short;\n    }\n    wuffs_base__table_u8* tab =\n        &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n    tab->ptr = ptr;\n    tab->width = 1024;\n    tab->height = 1;\n    tab->stride = 1024;\n    ptr += 1024;\n    len -= 1024;\n  }\n\n  uint64_t wh = ((uint64_t)pixcfg->private_impl.width) *\n                ((uint64_t)pixcfg" +
+	"->private_impl.height);\n  size_t width = (size_t)(pixcfg->private_impl.width);\n  if ((wh > (UINT64_MAX / bytes_per_pixel)) ||\n      (width > (SIZE_MAX / bytes_per_pixel))) {\n    return wuffs_base__error__bad_argument;\n  }\n  wh *= bytes_per_pixel;\n  width *= bytes_per_pixel;\n  if (wh > len) {\n    return wuffs_base__error__bad_argument_length_too_short;\n  }\n\n  b->pixcfg = *pixcfg;\n  wuffs_base__table_u8* tab = &b->private_impl.planes[0];\n  tab->ptr = ptr;\n  tab->width = width;\n  tab->height = pixcfg->private_impl.height;\n  tab->stride = width;\n  return NULL;\n}\n\nstatic inline wuffs_base__status  //\nwuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* b,\n                                         wuffs_base__pixel_config* pixcfg,\n                                         wuffs_base__table_u8 pixbuf_memory) {\n  if (!b) {\n    return wuffs_base__error__bad_receiver;\n  }\n  memset(b, 0, sizeof(*b));\n  if (!pixcfg ||\n      wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {\n    return wuffs_b" +
+	"ase__error__bad_argument;\n  }\n  uint32_t bits_per_pixel =\n      wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);\n  if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {\n    // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n    return wuffs_base__error__unsupported_option;\n  }\n  uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n  uint64_t width_in_bytes =\n      ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;\n  if ((width_in_bytes > pixbuf_memory.width) ||\n      (pixcfg->private_impl.height > pixbuf_memory.height)) {\n    return wuffs_base__error__bad_argument;\n  }\n\n  b->pixcfg = *pixcfg;\n  b->private_impl.planes[0] = pixbuf_memory;\n  return NULL;\n}\n\n// wuffs_base__pixel_buffer__palette returns the palette color data. If\n// non-empty, it will have length 1024.\nstatic inline wuffs_base__slice_u8  //\nwuffs_base__pixel_buffer__palette(wuffs_base__pixel_buffer* b) {\n  if (b &&\n      wuffs_base__pixel_format__is_indexed(b->pixcfg.private_impl.pixfmt)) {\n    wuffs_base" +
+	"__table_u8* tab =\n        &b->private_impl.planes[WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE];\n    if ((tab->width == 1024) && (tab->height == 1)) {\n      return wuffs_base__make_slice_u8(tab->ptr, 1024);\n    }\n  }\n  return wuffs_base__make_slice_u8(NULL, 0);\n}\n\nstatic inline wuffs_base__pixel_format  //\nwuffs_base__pixel_buffer__pixel_format(const wuffs_base__pixel_buffer* b) {\n  if (b) {\n    return b->pixcfg.private_impl.pixfmt;\n  }\n  return WUFFS_BASE__PIXEL_FORMAT__INVALID;\n}\n\nstatic inline wuffs_base__table_u8  //\nwuffs_base__pixel_buffer__plane(wuffs_base__pixel_buffer* b, uint32_t p) {\n  if (b && (p < WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX)) {\n    return b->private_impl.planes[p];\n  }\n\n  wuffs_base__table_u8 ret;\n  ret.ptr = NULL;\n  ret.width = 0;\n  ret.height = 0;\n  ret.stride = 0;\n  return ret;\n}\n\n#ifdef __cplusplus\n\ninline wuffs_base__status  //\nwuffs_base__pixel_buffer::set_from_slice(wuffs_base__pixel_config* pixcfg,\n                                         wuffs_base__slice_u8 pixbuf_memory" +
+	") {\n  return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);\n}\n\ninline wuffs_base__status  //\nwuffs_base__pixel_buffer::set_from_table(wuffs_base__pixel_config* pixcfg,\n                                         wuffs_base__table_u8 pixbuf_memory) {\n  return wuffs_base__pixel_buffer__set_from_table(this, pixcfg, pixbuf_memory);\n}\n\ninline wuffs_base__slice_u8  //\nwuffs_base__pixel_buffer::palette() {\n  return wuffs_base__pixel_buffer__palette(this);\n}\n\ninline wuffs_base__pixel_format  //\nwuffs_base__pixel_buffer::pixel_format() const {\n  return wuffs_base__pixel_buffer__pixel_format(this);\n}\n\ninline wuffs_base__table_u8  //\nwuffs_base__pixel_buffer::plane(uint32_t p) {\n  return wuffs_base__pixel_buffer__plane(this, p);\n}\n\n#endif  // __cplusplus\n\n" +
 	"" +
 	"// --------\n\ntypedef struct {\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    uint8_t TODO;\n  } private_impl;\n\n#ifdef __cplusplus\n#endif  // __cplusplus\n\n} wuffs_base__decode_frame_options;\n\n#ifdef __cplusplus\n\n#endif  // __cplusplus\n\n" +
 	"" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index fa0386c..efe73c2 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -2439,6 +2439,8 @@
 #ifdef __cplusplus
   inline wuffs_base__status set_from_slice(wuffs_base__pixel_config* pixcfg,
                                            wuffs_base__slice_u8 pixbuf_memory);
+  inline wuffs_base__status set_from_table(wuffs_base__pixel_config* pixcfg,
+                                           wuffs_base__table_u8 pixbuf_memory);
   inline wuffs_base__slice_u8 palette();
   inline wuffs_base__pixel_format pixel_format() const;
   inline wuffs_base__table_u8 plane(uint32_t p);
@@ -2522,6 +2524,38 @@
   return NULL;
 }
 
+static inline wuffs_base__status  //
+wuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* b,
+                                         wuffs_base__pixel_config* pixcfg,
+                                         wuffs_base__table_u8 pixbuf_memory) {
+  if (!b) {
+    return wuffs_base__error__bad_receiver;
+  }
+  memset(b, 0, sizeof(*b));
+  if (!pixcfg ||
+      wuffs_base__pixel_format__is_planar(pixcfg->private_impl.pixfmt)) {
+    return wuffs_base__error__bad_argument;
+  }
+  uint32_t bits_per_pixel =
+      wuffs_base__pixel_format__bits_per_pixel(pixcfg->private_impl.pixfmt);
+  if ((bits_per_pixel == 0) || ((bits_per_pixel % 8) != 0)) {
+    // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?
+    return wuffs_base__error__unsupported_option;
+  }
+  uint64_t bytes_per_pixel = bits_per_pixel / 8;
+
+  uint64_t width_in_bytes =
+      ((uint64_t)pixcfg->private_impl.width) * bytes_per_pixel;
+  if ((width_in_bytes > pixbuf_memory.width) ||
+      (pixcfg->private_impl.height > pixbuf_memory.height)) {
+    return wuffs_base__error__bad_argument;
+  }
+
+  b->pixcfg = *pixcfg;
+  b->private_impl.planes[0] = pixbuf_memory;
+  return NULL;
+}
+
 // wuffs_base__pixel_buffer__palette returns the palette color data. If
 // non-empty, it will have length 1024.
 static inline wuffs_base__slice_u8  //
@@ -2567,6 +2601,12 @@
   return wuffs_base__pixel_buffer__set_from_slice(this, pixcfg, pixbuf_memory);
 }
 
+inline wuffs_base__status  //
+wuffs_base__pixel_buffer::set_from_table(wuffs_base__pixel_config* pixcfg,
+                                         wuffs_base__table_u8 pixbuf_memory) {
+  return wuffs_base__pixel_buffer__set_from_table(this, pixcfg, pixbuf_memory);
+}
+
 inline wuffs_base__slice_u8  //
 wuffs_base__pixel_buffer::palette() {
   return wuffs_base__pixel_buffer__palette(this);