Change pixel_subsampling from shift to divide
diff --git a/doc/note/pixel-subsampling.md b/doc/note/pixel-subsampling.md
index ee64478..08f8ea2 100644
--- a/doc/note/pixel-subsampling.md
+++ b/doc/note/pixel-subsampling.md
@@ -2,12 +2,12 @@
 
 `wuffs_base__pixel_subsampling` is a `uint32_t` that encodes whether samples
 cover one pixel or cover multiple pixels. RGBA or BGRA pixel formats are
-typically one pixel per sample. For YCbCr or YCgCo pixel formats (e.g. the
-native format of JPEG and WebP lossy images), the luma channel (Y) is also
-typically one pixel per sample but the chroma channels are often 2 or 4 pixels
-per sample. In JPEG terminology, 1, 2 or 4 pixels per [chroma
-sample](https://en.wikipedia.org/wiki/Chroma_subsampling) correspond to 4:4:4,
-4:2:2 or 4:2:0 subsampling.
+typically one pixel per sample. For YCbCr pixel formats (i.e. the native
+formats of JPEG and WebP lossy images), the luma channel (Y) is also typically
+one pixel per sample but the chroma channels (Cb, Cr) are often 2 or 4 pixels
+per sample. In JPEG terminology, 4:4:4, 4:2:2 or 4:2:0 subsampling correspond
+to 1, 2 or 4 pixels per [chroma
+sample](https://en.wikipedia.org/wiki/Chroma_subsampling).
 
 Equivalently, `wuffs_base__pixel_subsampling` encodes the mapping of pixel
 space coordinates `(x, y)` to sample space coordinates `(i, j)`, also known as
@@ -23,21 +23,22 @@
 sample for every two pixels: pairs of horizontally adjacent pixels form one
 macropixel, `i = x / 2` and `j == y`. In general, for a given `p`:
 
-- `i = (x + bias_x) >> shift_x`.
-- `j = (y + bias_y) >> shift_y`.
+- `i = (x + bias_x) / denominator_x`.
+- `j = (y + bias_y) / denominator_y`.
 
-where biases and shifts are in the range `0 ..= 3` and `0 ..= 2` respectively.
+where biases and denominators are in the range `0 ..= 3` and `1 ..= 4`
+respectively.
 
 In general, the biases will be zero after decoding an image. However, making
 a sub-image may change the bias, since the `(x, y)` coordinates are relative
 to the sub-image's top-left origin, but the backing pixel buffers were
 created relative to the original image's origin.
 
-For example, consider a 10×3 image with what JPEG calls 4:1:1 sampling, where
-each Chroma sample covers a macropixel (a block of pixels) 4 wide and 1 high.
-For a Chroma channel, there are 30 pixels and 9 samples. `bias_x = 0` and
-`shift_x = 2`, so that the 6th pixel column (`x = 5`) maps to the 2nd sample
-column (`i = 1`).
+For example, consider a 10×3 image with what JPEG calls 4:1:1 subsampling,
+where each Chroma sample covers a macropixel (a block of pixels) 4 wide and 1
+high. For a Chroma channel, there are 30 pixels and 9 samples. `bias_x = 0` and
+`denominator_x = 2`, so that the 6th pixel column (`x = 5`) maps to the 2nd
+sample column (`i = 1`).
 
 ```
 Pixel space:
@@ -49,7 +50,7 @@
 |t21 t21 t22|t23 u24 u25|u26 u27 v28 v29|
 +-----------+-----------+---------------+
 
-Sample space:
+Chroma sample space:
 +-----+
 |l m n|
 |     |
@@ -62,7 +63,8 @@
 Now consider the 3×1 sub-image shown above. Even though its pixel width (3) is
 less than the macropixel width (4 columns per sample), as that sub-image shares
 the sample buffer with its containing image, it still straddles 2 sample
-columns (`t` and `u`). `shift_x = 2`, the same as before, but now `bias_x = 3`.
+columns (`t` and `u`). `denominator_x = 2`, the same as before, but now `bias_x
+= 3`.
 
 ```
 Pixel space:
@@ -70,7 +72,7 @@
 |t23 u24 u25|
 +-----------+
 
-Sample space:
+Chroma sample space:
 +---+
 |t u|
 +---+
@@ -79,13 +81,16 @@
 
 ## Bit Packing
 
-For each plane `p`, each of those four numbers (two biases and two shifts) are
-encoded in two bits, which combine to form an 8 bit unsigned integer:
+For each plane `p`, the adjusted denominator is defined to be one less than the
+denominator. The plane's four numbers (two biases and two adjusted
+denominators) are each in the range `0 ..= 3`, and are each encodable in two
+bits. Four groups of two bits combine to form an 8 bit unsigned integer:
 
 ```
-e_p = (bias_x << 6) | (shift_x << 4) | (bias_y << 2) | (shift_y << 0)
+e_p = (bias_x << 6) | (adj_denom_x << 4) | (bias_y << 2) | (adj_denom_y << 0)
 ```
 
+
 Those `e_p` values (`e_0` for the first plane, `e_1` for the second plane, etc)
 combine to form a `wuffs_base__pixel_subsampling` value:
 
@@ -93,7 +98,26 @@
 pixsub = (e_3 << 24) | (e_2 << 16) | (e_1 << 8) | (e_0 << 0)
 ```
 
-For example, 4:2:2 YCbCr (with no bias) is encoded in the `uint32_t` value
+For example, visualizing 4:2:2 YCbCr (with no bias):
+
+```
+Pixel space:
++-------------------+
+|l00 l01 m02 m03 n04|
+|                   |
+|p10 p11 q12 q13 r14|
++-------------------+
+
+Chroma sample space:
++-----+
+|l m n|
+|     |
+|p q r|
++-----+
+```
+
+This corresponds to a `denominator_x` of 1, 2 and 2 for the three planes (Y,
+Cb, Cr) and a `denominator_y` of 1, 1 and 1. The `uint32_t` encoding is
 `0x101000`.
 
 
diff --git a/internal/cgen/base/image-public.h b/internal/cgen/base/image-public.h
index a7a83b7..e242af1 100644
--- a/internal/cgen/base/image-public.h
+++ b/internal/cgen/base/image-public.h
@@ -150,9 +150,9 @@
 #define WUFFS_BASE__PIXEL_SUBSAMPLING__420 \
   ((wuffs_base__pixel_subsampling)0x111100)
 #define WUFFS_BASE__PIXEL_SUBSAMPLING__411 \
-  ((wuffs_base__pixel_subsampling)0x202000)
+  ((wuffs_base__pixel_subsampling)0x303000)
 #define WUFFS_BASE__PIXEL_SUBSAMPLING__410 \
-  ((wuffs_base__pixel_subsampling)0x212100)
+  ((wuffs_base__pixel_subsampling)0x313100)
 
 static inline uint32_t  //
 wuffs_base__pixel_subsampling__bias_x(wuffs_base__pixel_subsampling s,
@@ -162,10 +162,10 @@
 }
 
 static inline uint32_t  //
-wuffs_base__pixel_subsampling__shift_x(wuffs_base__pixel_subsampling s,
-                                       uint32_t plane) {
+wuffs_base__pixel_subsampling__denominator_x(wuffs_base__pixel_subsampling s,
+                                             uint32_t plane) {
   uint32_t shift = ((plane & 0x03) * 8) + 4;
-  return (s >> shift) & 0x03;
+  return ((s >> shift) & 0x03) + 1;
 }
 
 static inline uint32_t  //
@@ -176,10 +176,10 @@
 }
 
 static inline uint32_t  //
-wuffs_base__pixel_subsampling__shift_y(wuffs_base__pixel_subsampling s,
-                                       uint32_t plane) {
+wuffs_base__pixel_subsampling__denominator_y(wuffs_base__pixel_subsampling s,
+                                             uint32_t plane) {
   uint32_t shift = ((plane & 0x03) * 8) + 0;
-  return (s >> shift) & 0x03;
+  return ((s >> shift) & 0x03) + 1;
 }
 
 // --------
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 121ce05..29e7c7e 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -110,8 +110,8 @@
 	"ixel formats.\nstatic inline uint32_t  //\nwuffs_base__pixel_format__bits_per_pixel(wuffs_base__pixel_format f) {\n  if (((f >> 16) & 0x03) != 0) {\n    return 0;\n  }\n  return wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 0)] +\n         wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 4)] +\n         wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 8)] +\n         wuffs_base__pixel_format__bits_per_channel[0x0F & (f >> 12)];\n}\n\nstatic inline bool  //\nwuffs_base__pixel_format__is_indexed(wuffs_base__pixel_format f) {\n  return (f >> 18) & 0x01;\n}\n\nstatic inline bool  //\nwuffs_base__pixel_format__is_interleaved(wuffs_base__pixel_format f) {\n  return ((f >> 16) & 0x03) == 0;\n}\n\nstatic inline bool  //\nwuffs_base__pixel_format__is_planar(wuffs_base__pixel_format f) {\n  return ((f >> 16) & 0x03) != 0;\n}\n\nstatic inline uint32_t  //\nwuffs_base__pixel_format__num_planes(wuffs_base__pixel_format f) {\n  return ((f >> 16) & 0x03) + 1;\n}\n\n#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4\n\n#define WUFFS_B" +
 	"ASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3\n\n" +
 	"" +
-	"// --------\n\n// wuffs_base__pixel_subsampling encodes whether sample values cover one pixel\n// or cover multiple pixels.\n//\n// See https://github.com/google/wuffs/blob/master/doc/note/pixel-subsampling.md\n//\n// Do not manipulate its bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_subsampling__bias_x instead.\ntypedef uint32_t wuffs_base__pixel_subsampling;\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__NONE ((wuffs_base__pixel_subsampling)0)\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__444 \\\n  ((wuffs_base__pixel_subsampling)0x000000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__440 \\\n  ((wuffs_base__pixel_subsampling)0x010100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__422 \\\n  ((wuffs_base__pixel_subsampling)0x101000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__420 \\\n  ((wuffs_base__pixel_subsampling)0x111100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__411 \\\n  ((wuffs_base__pixel_subsampling)0x202000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__410 \\\n  ((wuffs_base__pixel_subsampling)0x212100)\n\ns" +
-	"tatic inline uint32_t  //\nwuffs_base__pixel_subsampling__bias_x(wuffs_base__pixel_subsampling s,\n                                      uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 6;\n  return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t  //\nwuffs_base__pixel_subsampling__shift_x(wuffs_base__pixel_subsampling s,\n                                       uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 4;\n  return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t  //\nwuffs_base__pixel_subsampling__bias_y(wuffs_base__pixel_subsampling s,\n                                      uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 2;\n  return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t  //\nwuffs_base__pixel_subsampling__shift_y(wuffs_base__pixel_subsampling s,\n                                       uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 0;\n  return (s >> shift) & 0x03;\n}\n\n" +
+	"// --------\n\n// wuffs_base__pixel_subsampling encodes whether sample values cover one pixel\n// or cover multiple pixels.\n//\n// See https://github.com/google/wuffs/blob/master/doc/note/pixel-subsampling.md\n//\n// Do not manipulate its bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_subsampling__bias_x instead.\ntypedef uint32_t wuffs_base__pixel_subsampling;\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__NONE ((wuffs_base__pixel_subsampling)0)\n\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__444 \\\n  ((wuffs_base__pixel_subsampling)0x000000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__440 \\\n  ((wuffs_base__pixel_subsampling)0x010100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__422 \\\n  ((wuffs_base__pixel_subsampling)0x101000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__420 \\\n  ((wuffs_base__pixel_subsampling)0x111100)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__411 \\\n  ((wuffs_base__pixel_subsampling)0x303000)\n#define WUFFS_BASE__PIXEL_SUBSAMPLING__410 \\\n  ((wuffs_base__pixel_subsampling)0x313100)\n\ns" +
+	"tatic inline uint32_t  //\nwuffs_base__pixel_subsampling__bias_x(wuffs_base__pixel_subsampling s,\n                                      uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 6;\n  return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t  //\nwuffs_base__pixel_subsampling__denominator_x(wuffs_base__pixel_subsampling s,\n                                             uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 4;\n  return ((s >> shift) & 0x03) + 1;\n}\n\nstatic inline uint32_t  //\nwuffs_base__pixel_subsampling__bias_y(wuffs_base__pixel_subsampling s,\n                                      uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 2;\n  return (s >> shift) & 0x03;\n}\n\nstatic inline uint32_t  //\nwuffs_base__pixel_subsampling__denominator_y(wuffs_base__pixel_subsampling s,\n                                             uint32_t plane) {\n  uint32_t shift = ((plane & 0x03) * 8) + 0;\n  return ((s >> shift) & 0x03) + 1;\n}\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    wuffs_base__pixel_format pixfmt;\n    wuffs_base__pixel_subsampling pixsub;\n    uint32_t width;\n    uint32_t height;\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  inline void invalidate();\n  inline bool is_valid() const;\n  inline wuffs_base__pixel_format pixel_format() const;\n  inline wuffs_base__pixel_subsampling pixel_subsampling() const;\n  inline wuffs_base__rect_ie_u32 bounds() const;\n  inline uint32_t width() const;\n  inline uint32_t height() const;\n  inline uint64_t pixbuf_len() const;\n#endif  // __cplusplus\n\n} wuffs_base__pixel_config;\n\nstatic inline wuffs_base__pixel_config  //\nwuffs_base__null_pixel_config() {\n  wuffs_base__pixel_config ret;\n  ret.private_impl.pix" +
 	"fmt = 0;\n  ret.private_impl.pixsub = 0;\n  ret.private_impl.width = 0;\n  ret.private_impl.height = 0;\n  return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void  //\nwuffs_base__pixel_config__set(wuffs_base__pixel_config* c,\n                              wuffs_base__pixel_format pixfmt,\n                              wuffs_base__pixel_subsampling pixsub,\n                              uint32_t width,\n                              uint32_t height) {\n  if (!c) {\n    return;\n  }\n  if (pixfmt) {\n    uint64_t wh = ((uint64_t)width) * ((uint64_t)height);\n    // TODO: handle things other than 1 byte per pixel.\n    if (wh <= ((uint64_t)SIZE_MAX)) {\n      c->private_impl.pixfmt = pixfmt;\n      c->private_impl.pixsub = pixsub;\n      c->private_impl.width = width;\n      c->private_impl.height = height;\n      return;\n    }\n  }\n\n  c->private_impl.pixfmt = 0;\n  c->private_impl.pixsub = 0;\n  c->private_impl.width = 0;\n  c->private_impl.height = 0;\n}\n\nstatic inline void  //\nwuffs_base__pixel_co" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 2bfa358..8fb3b69 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -1545,9 +1545,9 @@
 #define WUFFS_BASE__PIXEL_SUBSAMPLING__420 \
   ((wuffs_base__pixel_subsampling)0x111100)
 #define WUFFS_BASE__PIXEL_SUBSAMPLING__411 \
-  ((wuffs_base__pixel_subsampling)0x202000)
+  ((wuffs_base__pixel_subsampling)0x303000)
 #define WUFFS_BASE__PIXEL_SUBSAMPLING__410 \
-  ((wuffs_base__pixel_subsampling)0x212100)
+  ((wuffs_base__pixel_subsampling)0x313100)
 
 static inline uint32_t  //
 wuffs_base__pixel_subsampling__bias_x(wuffs_base__pixel_subsampling s,
@@ -1557,10 +1557,10 @@
 }
 
 static inline uint32_t  //
-wuffs_base__pixel_subsampling__shift_x(wuffs_base__pixel_subsampling s,
-                                       uint32_t plane) {
+wuffs_base__pixel_subsampling__denominator_x(wuffs_base__pixel_subsampling s,
+                                             uint32_t plane) {
   uint32_t shift = ((plane & 0x03) * 8) + 4;
-  return (s >> shift) & 0x03;
+  return ((s >> shift) & 0x03) + 1;
 }
 
 static inline uint32_t  //
@@ -1571,10 +1571,10 @@
 }
 
 static inline uint32_t  //
-wuffs_base__pixel_subsampling__shift_y(wuffs_base__pixel_subsampling s,
-                                       uint32_t plane) {
+wuffs_base__pixel_subsampling__denominator_y(wuffs_base__pixel_subsampling s,
+                                             uint32_t plane) {
   uint32_t shift = ((plane & 0x03) * 8) + 0;
-  return (s >> shift) & 0x03;
+  return ((s >> shift) & 0x03) + 1;
 }
 
 // --------