Clip std/gif output to the image rect
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 4dd0e55..bdd505e 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -11104,6 +11104,7 @@
wuffs_base__slice_u8 a_src) {
wuffs_base__slice_u8 v_dst = {0};
wuffs_base__slice_u8 v_src = {0};
+ uint64_t v_width_in_bytes = 0;
uint64_t v_n = 0;
uint64_t v_src_ri = 0;
uint32_t v_bytes_per_pixel = 0;
@@ -11125,6 +11126,8 @@
} else {
return wuffs_base__error__unsupported_option;
}
+ v_width_in_bytes = (((uint64_t)(self->private_impl.f_width)) *
+ ((uint64_t)(v_bytes_per_pixel)));
v_tab = wuffs_base__pixel_buffer__plane(a_pb, 0);
label_0_continue:;
while (v_src_ri < ((uint64_t)(a_src.len))) {
@@ -11136,6 +11139,11 @@
return wuffs_base__error__too_much_data;
}
v_dst = wuffs_base__table_u8__row(v_tab, self->private_impl.f_dst_y);
+ if (self->private_impl.f_dst_y >= self->private_impl.f_height) {
+ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, 0);
+ } else if (v_width_in_bytes < ((uint64_t)(v_dst.len))) {
+ v_dst = wuffs_base__slice_u8__subslice_j(v_dst, v_width_in_bytes);
+ }
v_i = (((uint64_t)(self->private_impl.f_dst_x)) *
((uint64_t)(v_bytes_per_pixel)));
if (v_i < ((uint64_t)(v_dst.len))) {
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index be2064f..83e6d25 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -1096,6 +1096,7 @@
// TODO: don't assume an interleaved pixel format.
var dst slice base.u8
var src slice base.u8
+ var width_in_bytes base.u64
var n base.u64
var src_ri base.u64
var bytes_per_pixel base.u32[..64]
@@ -1120,6 +1121,7 @@
return base."#unsupported option"
}
+ width_in_bytes = (this.width as base.u64) * (bytes_per_pixel as base.u64)
tab = args.pb.plane(p:0)
while src_ri < args.src.length() {
src = args.src[src_ri:]
@@ -1132,9 +1134,15 @@
}
// First, copy from src to that part of the frame rect that is inside
- // args.pb's bounds.
+ // args.pb's bounds (clipped to the image bounds).
dst = tab.row(y:this.dst_y)
+ if this.dst_y >= this.height {
+ dst = dst[:0]
+ } else if width_in_bytes < dst.length() {
+ dst = dst[:width_in_bytes]
+ }
+
i = (this.dst_x as base.u64) * (bytes_per_pixel as base.u64)
if i < dst.length() {
j = (this.frame_rect_x1 as base.u64) * (bytes_per_pixel as base.u64)
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index e30c3c2..57763d6 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -996,8 +996,12 @@
wuffs_base__pixel_config__height(&ic.pixcfg), height);
}
+ wuffs_base__pixel_config five_by_five = ((wuffs_base__pixel_config){});
+ wuffs_base__pixel_config__set(
+ &five_by_five, wuffs_base__pixel_config__pixel_format(&ic.pixcfg),
+ wuffs_base__pixel_config__pixel_subsampling(&ic.pixcfg), 5, 5);
wuffs_base__pixel_buffer pb = ((wuffs_base__pixel_buffer){});
- status = wuffs_base__pixel_buffer__set_from_slice(&pb, &ic.pixcfg,
+ status = wuffs_base__pixel_buffer__set_from_slice(&pb, &five_by_five,
global_pixel_slice);
if (status) {
RETURN_FAIL("q=%d: set_from_slice: \"%s\"", q, status);
@@ -1053,6 +1057,11 @@
{
wuffs_base__table_u8 p = wuffs_base__pixel_buffer__plane(&pb, 0);
uint32_t y, x;
+ for (y = 0; y < 5; y++) {
+ for (x = 0; x < 5; x++) {
+ p.ptr[(y * p.stride) + x] = 0xEE;
+ }
+ }
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
p.ptr[(y * p.stride) + x] = 0;
@@ -1066,6 +1075,20 @@
status);
}
+ for (y = 0; y < 5; y++) {
+ for (x = 0; x < 5; x++) {
+ if ((x < width) && (y < height)) {
+ continue;
+ }
+ if (p.ptr[(y * p.stride) + x] != 0xEE) {
+ RETURN_FAIL("q=%d: decode_frame #%" PRIu32
+ ": dirty pixel (%" PRIu32 ", %" PRIu32
+ ") outside of image bounds",
+ q, i, x, y);
+ }
+ }
+ }
+
wuffs_base__rect_ie_u32 frame_rect =
wuffs_base__frame_config__bounds(&fc);
wuffs_base__rect_ie_u32 dirty_rect =