Add limited_swizzle_u32_interleaved_from_reader
diff --git a/internal/cgen/base/image-private.h b/internal/cgen/base/image-private.h
index 2a4808f..7c12b22 100644
--- a/internal/cgen/base/image-private.h
+++ b/internal/cgen/base/image-private.h
@@ -17,6 +17,15 @@
 // ---------------- Images
 
 WUFFS_BASE__MAYBE_STATIC uint64_t  //
+wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
+    const wuffs_base__pixel_swizzler* p,
+    uint32_t up_to_num_pixels,
+    wuffs_base__slice_u8 dst,
+    wuffs_base__slice_u8 dst_palette,
+    const uint8_t** ptr_iop_r,
+    const uint8_t* io2_r);
+
+WUFFS_BASE__MAYBE_STATIC uint64_t  //
 wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
     const wuffs_base__pixel_swizzler* p,
     wuffs_base__slice_u8 dst,
diff --git a/internal/cgen/base/pixconv-submodule.c b/internal/cgen/base/pixconv-submodule.c
index 2089e78..39be01d 100644
--- a/internal/cgen/base/pixconv-submodule.c
+++ b/internal/cgen/base/pixconv-submodule.c
@@ -2114,6 +2114,28 @@
 }
 
 WUFFS_BASE__MAYBE_STATIC uint64_t  //
+wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
+    const wuffs_base__pixel_swizzler* p,
+    uint32_t up_to_num_pixels,
+    wuffs_base__slice_u8 dst,
+    wuffs_base__slice_u8 dst_palette,
+    const uint8_t** ptr_iop_r,
+    const uint8_t* io2_r) {
+  if (p && p->private_impl.func) {
+    const uint8_t* iop_r = *ptr_iop_r;
+    uint64_t src_len = wuffs_base__u64__min(
+        ((uint64_t)up_to_num_pixels) *
+            ((uint64_t)p->private_impl.src_pixfmt_bytes_per_pixel),
+        ((uint64_t)(io2_r - iop_r)));
+    uint64_t n = (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
+                                         dst_palette.len, iop_r, src_len);
+    *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
+    return n;
+  }
+  return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC uint64_t  //
 wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
     const wuffs_base__pixel_swizzler* p,
     wuffs_base__slice_u8 dst,
@@ -2122,9 +2144,9 @@
     const uint8_t* io2_r) {
   if (p && p->private_impl.func) {
     const uint8_t* iop_r = *ptr_iop_r;
+    uint64_t src_len = ((uint64_t)(io2_r - iop_r));
     uint64_t n = (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
-                                         dst_palette.len, iop_r,
-                                         (size_t)(io2_r - iop_r));
+                                         dst_palette.len, iop_r, src_len);
     *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
     return n;
   }
diff --git a/internal/cgen/builtin.go b/internal/cgen/builtin.go
index 1163cd0..6e24158 100644
--- a/internal/cgen/builtin.go
+++ b/internal/cgen/builtin.go
@@ -103,8 +103,14 @@
 			return g.writeBuiltinIOWriter(b, recv, method.Ident(), n.Args(), depth)
 		case t.IDPixelSwizzler:
 			switch method.Ident() {
-			case t.IDSwizzleInterleavedFromReader:
-				b.writes("wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(\n&")
+			case t.IDLimitedSwizzleU32InterleavedFromReader, t.IDSwizzleInterleavedFromReader:
+				b.writes("wuffs_base__pixel_swizzler__")
+				if method.Ident() == t.IDLimitedSwizzleU32InterleavedFromReader {
+					b.writes("limited_swizzle_u32_interleaved_from_reader")
+				} else {
+					b.writes("swizzle_interleaved_from_reader")
+				}
+				b.writes("(\n&")
 				if err := g.writeExpr(b, recv, depth); err != nil {
 					return err
 				}
diff --git a/internal/cgen/data/data.go b/internal/cgen/data/data.go
index 3084730..c77b9c1 100644
--- a/internal/cgen/data/data.go
+++ b/internal/cgen/data/data.go
@@ -109,7 +109,7 @@
 	""
 
 const BaseImagePrivateH = "" +
-	"// ---------------- Images\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    const uint8_t** ptr_iop_r,\n    const uint8_t* io2_r);\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    uint64_t num_pixels);\n\n" +
+	"// ---------------- Images\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(\n    const wuffs_base__pixel_swizzler* p,\n    uint32_t up_to_num_pixels,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    const uint8_t** ptr_iop_r,\n    const uint8_t* io2_r);\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    const uint8_t** ptr_iop_r,\n    const uint8_t* io2_r);\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    uint64_t num_pixels);\n\n" +
 	"" +
 	"// ---------------- Images (Utility)\n\n#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format\n" +
 	""
@@ -605,8 +605,9 @@
 	"// --------\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__status  //\nwuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,\n                                    wuffs_base__pixel_format dst_pixfmt,\n                                    wuffs_base__slice_u8 dst_palette,\n                                    wuffs_base__pixel_format src_pixfmt,\n                                    wuffs_base__slice_u8 src_palette,\n                                    wuffs_base__pixel_blend blend) {\n  if (!p) {\n    return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n  }\n  p->private_impl.func = NULL;\n  p->private_impl.transparent_black_func = NULL;\n  p->private_impl.dst_pixfmt_bytes_per_pixel = 0;\n  p->private_impl.src_pixfmt_bytes_per_pixel = 0;\n\n  wuffs_base__pixel_swizzler__func func = NULL;\n  wuffs_base__pixel_swizzler__transparent_black_func transparent_black_func =\n      NULL;\n\n  uint32_t dst_pixfmt_bits_per_pixel =\n      wuffs_base__pixel_format__bits_per_pixel(&dst_pixfmt);\n  if ((dst_pixfmt_bits_per_pixel == " +
 	"0) ||\n      ((dst_pixfmt_bits_per_pixel & 7) != 0)) {\n    return wuffs_base__make_status(\n        wuffs_base__error__unsupported_pixel_swizzler_option);\n  }\n\n  uint32_t src_pixfmt_bits_per_pixel =\n      wuffs_base__pixel_format__bits_per_pixel(&src_pixfmt);\n  if ((src_pixfmt_bits_per_pixel == 0) ||\n      ((src_pixfmt_bits_per_pixel & 7) != 0)) {\n    return wuffs_base__make_status(\n        wuffs_base__error__unsupported_pixel_swizzler_option);\n  }\n\n  // TODO: support many more formats.\n\n  switch (blend) {\n    case WUFFS_BASE__PIXEL_BLEND__SRC:\n      transparent_black_func =\n          wuffs_base__pixel_swizzler__transparent_black_src;\n      break;\n\n    case WUFFS_BASE__PIXEL_BLEND__SRC_OVER:\n      transparent_black_func =\n          wuffs_base__pixel_swizzler__transparent_black_src_over;\n      break;\n  }\n\n  switch (src_pixfmt.repr) {\n    case WUFFS_BASE__PIXEL_FORMAT__Y:\n      func = wuffs_base__pixel_swizzler__prepare__y(p, dst_pixfmt, dst_palette,\n                                                    src_palette" +
 	", blend);\n      break;\n\n    case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n      func = wuffs_base__pixel_swizzler__prepare__indexed__bgra_binary(\n          p, dst_pixfmt, dst_palette, src_palette, blend);\n      break;\n\n    case WUFFS_BASE__PIXEL_FORMAT__BGR:\n      func = wuffs_base__pixel_swizzler__prepare__bgr(\n          p, dst_pixfmt, dst_palette, src_palette, blend);\n      break;\n\n    case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n      func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul(\n          p, dst_pixfmt, dst_palette, src_palette, blend);\n      break;\n\n    case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL_4X16LE:\n      func = wuffs_base__pixel_swizzler__prepare__bgra_nonpremul_4x16le(\n          p, dst_pixfmt, dst_palette, src_palette, blend);\n      break;\n\n    case WUFFS_BASE__PIXEL_FORMAT__BGRX:\n      func = wuffs_base__pixel_swizzler__prepare__bgrx(\n          p, dst_pixfmt, dst_palette, src_palette, blend);\n      break;\n  }\n\n  p->private_impl.func = func;\n  p->private_impl.transparent_b" +
-	"lack_func = transparent_black_func;\n  p->private_impl.dst_pixfmt_bytes_per_pixel = dst_pixfmt_bits_per_pixel / 8;\n  p->private_impl.src_pixfmt_bytes_per_pixel = src_pixfmt_bits_per_pixel / 8;\n  return wuffs_base__make_status(\n      func ? NULL : wuffs_base__error__unsupported_pixel_swizzler_option);\n}\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    const uint8_t** ptr_iop_r,\n    const uint8_t* io2_r) {\n  if (p && p->private_impl.func) {\n    const uint8_t* iop_r = *ptr_iop_r;\n    uint64_t n = (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,\n                                         dst_palette.len, iop_r,\n                                         (size_t)(io2_r - iop_r));\n    *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;\n    return n;\n  }\n  return 0;\n}\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzl" +
-	"e_interleaved_from_slice(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    wuffs_base__slice_u8 src) {\n  if (p && p->private_impl.func) {\n    return (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,\n                                   dst_palette.len, src.ptr, src.len);\n  }\n  return 0;\n}\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    uint64_t num_pixels) {\n  if (p && p->private_impl.transparent_black_func) {\n    return (*p->private_impl.transparent_black_func)(\n        dst.ptr, dst.len, dst_palette.ptr, dst_palette.len, num_pixels,\n        p->private_impl.dst_pixfmt_bytes_per_pixel);\n  }\n  return 0;\n}\n" +
+	"lack_func = transparent_black_func;\n  p->private_impl.dst_pixfmt_bytes_per_pixel = dst_pixfmt_bits_per_pixel / 8;\n  p->private_impl.src_pixfmt_bytes_per_pixel = src_pixfmt_bits_per_pixel / 8;\n  return wuffs_base__make_status(\n      func ? NULL : wuffs_base__error__unsupported_pixel_swizzler_option);\n}\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(\n    const wuffs_base__pixel_swizzler* p,\n    uint32_t up_to_num_pixels,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    const uint8_t** ptr_iop_r,\n    const uint8_t* io2_r) {\n  if (p && p->private_impl.func) {\n    const uint8_t* iop_r = *ptr_iop_r;\n    uint64_t src_len = wuffs_base__u64__min(\n        ((uint64_t)up_to_num_pixels) *\n            ((uint64_t)p->private_impl.src_pixfmt_bytes_per_pixel),\n        ((uint64_t)(io2_r - iop_r)));\n    uint64_t n = (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,\n                                         dst_palette.len, iop_r, src_l" +
+	"en);\n    *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;\n    return n;\n  }\n  return 0;\n}\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    const uint8_t** ptr_iop_r,\n    const uint8_t* io2_r) {\n  if (p && p->private_impl.func) {\n    const uint8_t* iop_r = *ptr_iop_r;\n    uint64_t src_len = ((uint64_t)(io2_r - iop_r));\n    uint64_t n = (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,\n                                         dst_palette.len, iop_r, src_len);\n    *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;\n    return n;\n  }\n  return 0;\n}\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_from_slice(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    wuffs_base__slice_u8 src) {\n  if (p && p->private_impl.func) {\n   " +
+	" return (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,\n                                   dst_palette.len, src.ptr, src.len);\n  }\n  return 0;\n}\n\nWUFFS_BASE__MAYBE_STATIC uint64_t  //\nwuffs_base__pixel_swizzler__swizzle_interleaved_transparent_black(\n    const wuffs_base__pixel_swizzler* p,\n    wuffs_base__slice_u8 dst,\n    wuffs_base__slice_u8 dst_palette,\n    uint64_t num_pixels) {\n  if (p && p->private_impl.transparent_black_func) {\n    return (*p->private_impl.transparent_black_func)(\n        dst.ptr, dst.len, dst_palette.ptr, dst_palette.len, num_pixels,\n        p->private_impl.dst_pixfmt_bytes_per_pixel);\n  }\n  return 0;\n}\n" +
 	""
 
 const BaseUTF8SubmoduleC = "" +
diff --git a/lang/builtin/builtin.go b/lang/builtin/builtin.go
index 8ae8a95..4a4387e 100644
--- a/lang/builtin/builtin.go
+++ b/lang/builtin/builtin.go
@@ -514,6 +514,9 @@
 	"pixel_swizzler.prepare!(" +
 		"dst_pixfmt: pixel_format, dst_palette: slice u8," +
 		"src_pixfmt: pixel_format, src_palette: slice u8, blend: pixel_blend) status",
+
+	"pixel_swizzler.limited_swizzle_u32_interleaved_from_reader!(" +
+		"up_to_num_pixels: u32, dst: slice u8, dst_palette: slice u8, src: io_reader) u64",
 	"pixel_swizzler.swizzle_interleaved_from_reader!(" +
 		"dst: slice u8, dst_palette: slice u8, src: io_reader) u64",
 	"pixel_swizzler.swizzle_interleaved_from_slice!(" +
diff --git a/lang/token/list.go b/lang/token/list.go
index 72a60ec..976b030 100644
--- a/lang/token/list.go
+++ b/lang/token/list.go
@@ -663,7 +663,8 @@
 	IDValidUTF8Length = ID(0x249)
 	IDWidth           = ID(0x24A)
 
-	IDSwizzleInterleavedFromReader = ID(0x280)
+	IDLimitedSwizzleU32InterleavedFromReader = ID(0x280)
+	IDSwizzleInterleavedFromReader           = ID(0x281)
 )
 
 var builtInsByID = [nBuiltInIDs]string{
@@ -1026,7 +1027,8 @@
 	IDValidUTF8Length: "valid_utf_8_length",
 	IDWidth:           "width",
 
-	IDSwizzleInterleavedFromReader: "swizzle_interleaved_from_reader",
+	IDLimitedSwizzleU32InterleavedFromReader: "limited_swizzle_u32_interleaved_from_reader",
+	IDSwizzleInterleavedFromReader:           "swizzle_interleaved_from_reader",
 }
 
 var builtInsByName = map[string]ID{}
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 28ab222..e87e854 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -9228,6 +9228,15 @@
 // ---------------- Images
 
 WUFFS_BASE__MAYBE_STATIC uint64_t  //
+wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
+    const wuffs_base__pixel_swizzler* p,
+    uint32_t up_to_num_pixels,
+    wuffs_base__slice_u8 dst,
+    wuffs_base__slice_u8 dst_palette,
+    const uint8_t** ptr_iop_r,
+    const uint8_t* io2_r);
+
+WUFFS_BASE__MAYBE_STATIC uint64_t  //
 wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
     const wuffs_base__pixel_swizzler* p,
     wuffs_base__slice_u8 dst,
@@ -15620,6 +15629,28 @@
 }
 
 WUFFS_BASE__MAYBE_STATIC uint64_t  //
+wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
+    const wuffs_base__pixel_swizzler* p,
+    uint32_t up_to_num_pixels,
+    wuffs_base__slice_u8 dst,
+    wuffs_base__slice_u8 dst_palette,
+    const uint8_t** ptr_iop_r,
+    const uint8_t* io2_r) {
+  if (p && p->private_impl.func) {
+    const uint8_t* iop_r = *ptr_iop_r;
+    uint64_t src_len = wuffs_base__u64__min(
+        ((uint64_t)up_to_num_pixels) *
+            ((uint64_t)p->private_impl.src_pixfmt_bytes_per_pixel),
+        ((uint64_t)(io2_r - iop_r)));
+    uint64_t n = (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
+                                         dst_palette.len, iop_r, src_len);
+    *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
+    return n;
+  }
+  return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC uint64_t  //
 wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
     const wuffs_base__pixel_swizzler* p,
     wuffs_base__slice_u8 dst,
@@ -15628,9 +15659,9 @@
     const uint8_t* io2_r) {
   if (p && p->private_impl.func) {
     const uint8_t* iop_r = *ptr_iop_r;
+    uint64_t src_len = ((uint64_t)(io2_r - iop_r));
     uint64_t n = (*p->private_impl.func)(dst.ptr, dst.len, dst_palette.ptr,
-                                         dst_palette.len, iop_r,
-                                         (size_t)(io2_r - iop_r));
+                                         dst_palette.len, iop_r, src_len);
     *ptr_iop_r += n * p->private_impl.src_pixfmt_bytes_per_pixel;
     return n;
   }
@@ -17411,12 +17442,9 @@
             v_rle_state = 3;
             goto label__inner__continue;
           } else if (v_rle_state == 3) {
-            v_n = (v_dst_bytes_per_pixel * ((uint64_t)(self->private_impl.f_rle_length)));
-            if (v_n < ((uint64_t)(v_dst.len))) {
-              v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_n);
-            }
-            v_n = wuffs_base__pixel_swizzler__swizzle_interleaved_from_reader(
+            v_n = wuffs_base__pixel_swizzler__limited_swizzle_u32_interleaved_from_reader(
                 &self->private_impl.f_swizzler,
+                self->private_impl.f_rle_length,
                 v_dst,
                 v_dst_palette,
                 &iop_a_src,
diff --git a/std/bmp/decode_bmp.wuffs b/std/bmp/decode_bmp.wuffs
index 323ea1e..942fde5 100644
--- a/std/bmp/decode_bmp.wuffs
+++ b/std/bmp/decode_bmp.wuffs
@@ -572,11 +572,8 @@
 					continue.inner
 
 				} else if rle_state == RLE_STATE_LITERAL {
-					n = dst_bytes_per_pixel * (this.rle_length as base.u64)
-					if n < dst.length() {
-						dst = dst[.. n]
-					}
-					n = this.swizzler.swizzle_interleaved_from_reader!(
+					n = this.swizzler.limited_swizzle_u32_interleaved_from_reader!(
+						up_to_num_pixels: this.rle_length,
 						dst: dst,
 						dst_palette: dst_palette,
 						src: args.src)