Let GIF decode BGR/RGB, not just BGRA/RGBA
diff --git a/internal/cgen/base/image-impl.c b/internal/cgen/base/image-impl.c
index 8b1fb5d..abac9ec 100644
--- a/internal/cgen/base/image-impl.c
+++ b/internal/cgen/base/image-impl.c
@@ -29,6 +29,61 @@
}
static uint64_t //
+wuffs_base__pixel_swizzler__copy_3_1(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) {
+ if (dst_palette.len != 1024) {
+ return 0;
+ }
+ size_t dst_len3 = dst.len / 3;
+ size_t len = dst_len3 < src.len ? dst_len3 : src.len;
+ uint8_t* d = dst.ptr;
+ uint8_t* s = src.ptr;
+ size_t n = len;
+
+ // N is the loop unroll count.
+ const int N = 4;
+
+ // The comparison in the while condition is ">", not ">=", because with ">=",
+ // the last 4-byte store could write past the end of the dst slice.
+ //
+ // Each 4-byte store writes one too many bytes, but a subsequent store will
+ // overwrite that with the correct byte. There is always another store,
+ // whether a 4-byte store in this loop or a 1-byte store in the next loop.
+ while (n > N) {
+ wuffs_base__store_u32le(
+ d + (0 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));
+ wuffs_base__store_u32le(
+ d + (1 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));
+ wuffs_base__store_u32le(
+ d + (2 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));
+ wuffs_base__store_u32le(
+ d + (3 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));
+
+ s += 1 * N;
+ d += 3 * N;
+ n -= (size_t)(1 * N);
+ }
+
+ while (n >= 1) {
+ uint32_t color =
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4));
+ d[0] = (uint8_t)(color >> 0);
+ d[1] = (uint8_t)(color >> 8);
+ d[2] = (uint8_t)(color >> 16);
+
+ s += 1 * 1;
+ d += 3 * 1;
+ n -= (size_t)(1 * 1);
+ }
+
+ return len;
+}
+static uint64_t //
wuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src) {
@@ -39,8 +94,9 @@
size_t len = dst_len4 < src.len ? dst_len4 : src.len;
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
-
size_t n = len;
+
+ // N is the loop unroll count.
const int N = 4;
while (n >= N) {
@@ -125,6 +181,13 @@
}
func = wuffs_base__pixel_swizzler__copy_1_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
+ 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
@@ -134,6 +197,13 @@
}
func = wuffs_base__pixel_swizzler__copy_4_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,
+ src_palette) != 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index 96105e8..2cf5e13 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -24,11 +24,13 @@
""
const baseImageImplC = "" +
- "// ---------------- Images\n\nconst uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {\n 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,\n};\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_1_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n return wuffs_base__slice_u8__copy_from_slice(dst, src);\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (dst_palette.len != 1024) {\n return 0;\n }\n size_t dst_len4 = dst.len / 4;\n size_t len = dst_len4 < src.len ? dst_len4 : src.len;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n\n size_t n = len;\n const int N = 4;\n\n while (n >= N) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u3" +
- "2le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n wuffs_base__store_u32le(\n d + (1 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));\n wuffs_base__store_u32le(\n d + (2 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));\n wuffs_base__store_u32le(\n d + (3 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));\n\n s += 1 * N;\n d += 4 * N;\n n -= (size_t)(1 * N);\n }\n\n while (n >= 1) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n\n s += 1 * 1;\n d += 4 * 1;\n n -= (size_t)(1 * 1);\n }\n\n return len;\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__swap_rgbx_bgrx(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src) {\n size_t len4 = (dst.len < src.len ? dst.len : src.len) / 4;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n\n size_t n = len4;\n while (n--) {\n uin" +
- "t8_t b0 = s[0];\n uint8_t b1 = s[1];\n uint8_t b2 = s[2];\n uint8_t b3 = s[3];\n d[0] = b2;\n d[1] = b1;\n d[2] = b0;\n d[3] = b3;\n s += 4;\n d += 4;\n }\n return len4 * 4;\n}\n\nwuffs_base__status //\nwuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_swizzler* p,\n wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette) {\n if (!p) {\n return wuffs_base__error__bad_receiver;\n }\n\n // TODO: support many more formats.\n\n uint64_t (*func)(wuffs_base__slice_u8 dst, wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) = NULL;\n\n switch (src_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n switch (dst_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXE" +
- "D__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_1_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_4_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:\n if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,\n src_palette) != 1024) {\n break;\n }\n func = wuffs_base__pixel_" +
- "swizzler__copy_4_1;\n break;\n default:\n break;\n }\n break;\n\n default:\n break;\n }\n\n p->private_impl.func = func;\n return func ? NULL : wuffs_base__error__unsupported_option;\n}\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_packed(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, dst_palette, src);\n }\n return 0;\n}\n" +
+ "// ---------------- Images\n\nconst uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {\n 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\n 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,\n};\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_1_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n return wuffs_base__slice_u8__copy_from_slice(dst, src);\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_3_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (dst_palette.len != 1024) {\n return 0;\n }\n size_t dst_len3 = dst.len / 3;\n size_t len = dst_len3 < src.len ? dst_len3 : src.len;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n // N is the loop unroll count.\n const int N = 4;\n\n // The comparison in the while condition is \">\", not \">=\", be" +
+ "cause with \">=\",\n // the last 4-byte store could write past the end of the dst slice.\n //\n // Each 4-byte store writes one too many bytes, but a subsequent store will\n // overwrite that with the correct byte. There is always another store,\n // whether a 4-byte store in this loop or a 1-byte store in the next loop.\n while (n > N) {\n wuffs_base__store_u32le(\n d + (0 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n wuffs_base__store_u32le(\n d + (1 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));\n wuffs_base__store_u32le(\n d + (2 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));\n wuffs_base__store_u32le(\n d + (3 * 3),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));\n\n s += 1 * N;\n d += 3 * N;\n n -= (size_t)(1 * N);\n }\n\n while (n >= 1) {\n uint32_t color =\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4));\n d[0" +
+ "] = (uint8_t)(color >> 0);\n d[1] = (uint8_t)(color >> 8);\n d[2] = (uint8_t)(color >> 16);\n\n s += 1 * 1;\n d += 3 * 1;\n n -= (size_t)(1 * 1);\n }\n\n return len;\n}\nstatic uint64_t //\nwuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) {\n if (dst_palette.len != 1024) {\n return 0;\n }\n size_t dst_len4 = dst.len / 4;\n size_t len = dst_len4 < src.len ? dst_len4 : src.len;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n size_t n = len;\n\n // N is the loop unroll count.\n const int N = 4;\n\n while (n >= N) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n wuffs_base__store_u32le(\n d + (1 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));\n wuffs_base__store_u32le(\n d + (2 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + (" +
+ "(uint32_t)(s[2]) * 4)));\n wuffs_base__store_u32le(\n d + (3 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));\n\n s += 1 * N;\n d += 4 * N;\n n -= (size_t)(1 * N);\n }\n\n while (n >= 1) {\n wuffs_base__store_u32le(\n d + (0 * 4),\n wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));\n\n s += 1 * 1;\n d += 4 * 1;\n n -= (size_t)(1 * 1);\n }\n\n return len;\n}\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__swap_rgbx_bgrx(wuffs_base__slice_u8 dst,\n wuffs_base__slice_u8 src) {\n size_t len4 = (dst.len < src.len ? dst.len : src.len) / 4;\n uint8_t* d = dst.ptr;\n uint8_t* s = src.ptr;\n\n size_t n = len4;\n while (n--) {\n uint8_t b0 = s[0];\n uint8_t b1 = s[1];\n uint8_t b2 = s[2];\n uint8_t b3 = s[3];\n d[0] = b2;\n d[1] = b1;\n d[2] = b0;\n d[3] = b3;\n s += 4;\n d += 4;\n }\n return len4 * 4;\n}\n\nwuffs_base__status //\nwuffs_base__pixel_swizzler__prepare(wuffs_base__pixel_s" +
+ "wizzler* p,\n wuffs_base__pixel_format dst_format,\n wuffs_base__slice_u8 dst_palette,\n wuffs_base__pixel_format src_format,\n wuffs_base__slice_u8 src_palette) {\n if (!p) {\n return wuffs_base__error__bad_receiver;\n }\n\n // TODO: support many more formats.\n\n uint64_t (*func)(wuffs_base__slice_u8 dst, wuffs_base__slice_u8 dst_palette,\n wuffs_base__slice_u8 src) = NULL;\n\n switch (src_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n switch (dst_format) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_1_1;\n " +
+ " break;\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_3_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:\n if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=\n 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_4_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGB:\n if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,\n src_palette) != 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_3_1;\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PR" +
+ "EMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:\n if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,\n src_palette) != 1024) {\n break;\n }\n func = wuffs_base__pixel_swizzler__copy_4_1;\n break;\n default:\n break;\n }\n break;\n\n default:\n break;\n }\n\n p->private_impl.func = func;\n return func ? NULL : wuffs_base__error__unsupported_option;\n}\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_packed(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, dst_palette, src);\n }\n return 0;\n}\n" +
""
const baseCorePrivateH = "" +
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index 1d2b578..75df621 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -4834,6 +4834,61 @@
}
static uint64_t //
+wuffs_base__pixel_swizzler__copy_3_1(wuffs_base__slice_u8 dst,
+ wuffs_base__slice_u8 dst_palette,
+ wuffs_base__slice_u8 src) {
+ if (dst_palette.len != 1024) {
+ return 0;
+ }
+ size_t dst_len3 = dst.len / 3;
+ size_t len = dst_len3 < src.len ? dst_len3 : src.len;
+ uint8_t* d = dst.ptr;
+ uint8_t* s = src.ptr;
+ size_t n = len;
+
+ // N is the loop unroll count.
+ const int N = 4;
+
+ // The comparison in the while condition is ">", not ">=", because with ">=",
+ // the last 4-byte store could write past the end of the dst slice.
+ //
+ // Each 4-byte store writes one too many bytes, but a subsequent store will
+ // overwrite that with the correct byte. There is always another store,
+ // whether a 4-byte store in this loop or a 1-byte store in the next loop.
+ while (n > N) {
+ wuffs_base__store_u32le(
+ d + (0 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4)));
+ wuffs_base__store_u32le(
+ d + (1 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[1]) * 4)));
+ wuffs_base__store_u32le(
+ d + (2 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[2]) * 4)));
+ wuffs_base__store_u32le(
+ d + (3 * 3),
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[3]) * 4)));
+
+ s += 1 * N;
+ d += 3 * N;
+ n -= (size_t)(1 * N);
+ }
+
+ while (n >= 1) {
+ uint32_t color =
+ wuffs_base__load_u32le(dst_palette.ptr + ((uint32_t)(s[0]) * 4));
+ d[0] = (uint8_t)(color >> 0);
+ d[1] = (uint8_t)(color >> 8);
+ d[2] = (uint8_t)(color >> 16);
+
+ s += 1 * 1;
+ d += 3 * 1;
+ n -= (size_t)(1 * 1);
+ }
+
+ return len;
+}
+static uint64_t //
wuffs_base__pixel_swizzler__copy_4_1(wuffs_base__slice_u8 dst,
wuffs_base__slice_u8 dst_palette,
wuffs_base__slice_u8 src) {
@@ -4844,8 +4899,9 @@
size_t len = dst_len4 < src.len ? dst_len4 : src.len;
uint8_t* d = dst.ptr;
uint8_t* s = src.ptr;
-
size_t n = len;
+
+ // N is the loop unroll count.
const int N = 4;
while (n >= N) {
@@ -4930,6 +4986,13 @@
}
func = wuffs_base__pixel_swizzler__copy_1_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ if (wuffs_base__slice_u8__copy_from_slice(dst_palette, src_palette) !=
+ 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
@@ -4939,6 +5002,13 @@
}
func = wuffs_base__pixel_swizzler__copy_4_1;
break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ if (wuffs_base__pixel_swizzler__swap_rgbx_bgrx(dst_palette,
+ src_palette) != 1024) {
+ break;
+ }
+ func = wuffs_base__pixel_swizzler__copy_3_1;
+ break;
case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
@@ -11175,17 +11245,20 @@
uint64_t v_n = 0;
uint64_t v_src_ri = 0;
uint32_t v_bytes_per_pixel = 0;
- uint32_t v_pixfmt = 0;
+ uint32_t v_pixfmt_channels = 0;
wuffs_base__table_u8 v_tab = {0};
uint64_t v_i = 0;
uint64_t v_j = 0;
- v_bytes_per_pixel = 1;
- v_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_pb);
- if ((v_pixfmt == 1157662856) || (v_pixfmt == 1426098312) ||
- (v_pixfmt == 1174440072) || (v_pixfmt == 1442875528) ||
- (v_pixfmt == 1191217288) || (v_pixfmt == 1459652744)) {
+ v_pixfmt_channels = (wuffs_base__pixel_buffer__pixel_format(a_pb) & 65535);
+ if (v_pixfmt_channels == 34952) {
v_bytes_per_pixel = 4;
+ } else if (v_pixfmt_channels == 2184) {
+ v_bytes_per_pixel = 3;
+ } else if (v_pixfmt_channels == 8) {
+ v_bytes_per_pixel = 1;
+ } else {
+ return wuffs_base__error__unsupported_option;
}
v_tab = wuffs_base__pixel_buffer__plane(a_pb, 0);
label_0_continue:;
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs
index 37364c8..0cd3067 100644
--- a/std/gif/decode_gif.wuffs
+++ b/std/gif/decode_gif.wuffs
@@ -1110,19 +1110,22 @@
var n base.u64
var src_ri base.u64
var bytes_per_pixel base.u32[..64]
- var pixfmt base.u32
+ var pixfmt_channels base.u32
var tab table base.u8
var i base.u64
var j base.u64
// TODO: a Wuffs (not just C) name for the WUFFS_BASE__PIXEL_FORMAT__ETC
// magic pixfmt constants. Also, support more formats.
- bytes_per_pixel = 1
- pixfmt = args.pb.pixel_format()
- if (pixfmt == 0x45008888) or (pixfmt == 0x55008888) or
- (pixfmt == 0x46008888) or (pixfmt == 0x56008888) or
- (pixfmt == 0x47008888) or (pixfmt == 0x57008888) {
+ pixfmt_channels = args.pb.pixel_format() & 0xFFFF
+ if (pixfmt_channels == 0x8888) {
bytes_per_pixel = 4
+ } else if (pixfmt_channels == 0x0888) {
+ bytes_per_pixel = 3
+ } else if (pixfmt_channels == 0x0008) {
+ bytes_per_pixel = 1
+ } else {
+ return base."#unsupported option"
}
tab = args.pb.plane(p:0)
diff --git a/test/c/std/gif.c b/test/c/std/gif.c
index 796f65b..876bb9f 100644
--- a/test/c/std/gif.c
+++ b/test/c/std/gif.c
@@ -432,15 +432,49 @@
if (ind_want.meta.wi > (expanded_want.data.len / 4)) {
RETURN_FAIL("indexes are too long to expand into the work buffer");
}
- size_t i;
- for (i = 0; i < ind_want.meta.wi; i++) {
- uint8_t index = ind_want.data.ptr[i];
- expanded_want.data.ptr[4 * i + 0] = pal_want_array[4 * index + 0];
- expanded_want.data.ptr[4 * i + 1] = pal_want_array[4 * index + 1];
- expanded_want.data.ptr[4 * i + 2] = pal_want_array[4 * index + 2];
- expanded_want.data.ptr[4 * i + 3] = pal_want_array[4 * index + 3];
+
+ if (dst_pixfmt == WUFFS_BASE__PIXEL_FORMAT__BGR) {
+ size_t i;
+ for (i = 0; i < ind_want.meta.wi; i++) {
+ uint8_t index = ind_want.data.ptr[i];
+ expanded_want.data.ptr[3 * i + 0] = pal_want_array[4 * index + 0];
+ expanded_want.data.ptr[3 * i + 1] = pal_want_array[4 * index + 1];
+ expanded_want.data.ptr[3 * i + 2] = pal_want_array[4 * index + 2];
+ }
+ expanded_want.meta.wi = 3 * ind_want.meta.wi;
+ } else if (dst_pixfmt == WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL) {
+ size_t i;
+ for (i = 0; i < ind_want.meta.wi; i++) {
+ uint8_t index = ind_want.data.ptr[i];
+ expanded_want.data.ptr[4 * i + 0] = pal_want_array[4 * index + 0];
+ expanded_want.data.ptr[4 * i + 1] = pal_want_array[4 * index + 1];
+ expanded_want.data.ptr[4 * i + 2] = pal_want_array[4 * index + 2];
+ expanded_want.data.ptr[4 * i + 3] = pal_want_array[4 * index + 3];
+ }
+ expanded_want.meta.wi = 4 * ind_want.meta.wi;
+ } else if (dst_pixfmt == WUFFS_BASE__PIXEL_FORMAT__RGB) {
+ size_t i;
+ for (i = 0; i < ind_want.meta.wi; i++) {
+ uint8_t index = ind_want.data.ptr[i];
+ expanded_want.data.ptr[3 * i + 0] = pal_want_array[4 * index + 2];
+ expanded_want.data.ptr[3 * i + 1] = pal_want_array[4 * index + 1];
+ expanded_want.data.ptr[3 * i + 2] = pal_want_array[4 * index + 0];
+ }
+ expanded_want.meta.wi = 3 * ind_want.meta.wi;
+ } else if (dst_pixfmt == WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL) {
+ size_t i;
+ for (i = 0; i < ind_want.meta.wi; i++) {
+ uint8_t index = ind_want.data.ptr[i];
+ expanded_want.data.ptr[4 * i + 0] = pal_want_array[4 * index + 2];
+ expanded_want.data.ptr[4 * i + 1] = pal_want_array[4 * index + 1];
+ expanded_want.data.ptr[4 * i + 2] = pal_want_array[4 * index + 0];
+ expanded_want.data.ptr[4 * i + 3] = pal_want_array[4 * index + 3];
+ }
+ expanded_want.meta.wi = 4 * ind_want.meta.wi;
+ } else {
+ return "unsupported pixel format";
}
- expanded_want.meta.wi = 4 * ind_want.meta.wi;
+
status = check_io_buffers_equal("pixels ", &got, &expanded_want);
if (status) {
return status;
@@ -1148,7 +1182,14 @@
return NULL;
}
-const char* test_wuffs_gif_decode_bgra_nonpremul() {
+const char* test_wuffs_gif_decode_pixfmt_bgr() {
+ CHECK_FOCUS(__func__);
+ return do_test_wuffs_gif_decode(
+ "test/data/bricks-dither.gif", "test/data/bricks-dither.palette",
+ "test/data/bricks-dither.indexes", 0, WUFFS_BASE__PIXEL_FORMAT__BGR);
+}
+
+const char* test_wuffs_gif_decode_pixfmt_bgra_nonpremul() {
CHECK_FOCUS(__func__);
return do_test_wuffs_gif_decode("test/data/bricks-dither.gif",
"test/data/bricks-dither.palette",
@@ -1156,6 +1197,21 @@
WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL);
}
+const char* test_wuffs_gif_decode_pixfmt_rgb() {
+ CHECK_FOCUS(__func__);
+ return do_test_wuffs_gif_decode(
+ "test/data/bricks-dither.gif", "test/data/bricks-dither.palette",
+ "test/data/bricks-dither.indexes", 0, WUFFS_BASE__PIXEL_FORMAT__RGB);
+}
+
+const char* test_wuffs_gif_decode_pixfmt_rgba_nonpremul() {
+ CHECK_FOCUS(__func__);
+ return do_test_wuffs_gif_decode("test/data/bricks-dither.gif",
+ "test/data/bricks-dither.palette",
+ "test/data/bricks-dither.indexes", 0,
+ WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL);
+}
+
const char* test_wuffs_gif_decode_input_is_a_gif_just_one_read() {
CHECK_FOCUS(__func__);
return do_test_wuffs_gif_decode(
@@ -2208,7 +2264,6 @@
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_delay_num_frames_decoded, //
test_wuffs_gif_decode_empty_palette, //
test_wuffs_gif_decode_first_frame_is_opaque, //
@@ -2226,6 +2281,10 @@
test_wuffs_gif_decode_pixel_data_not_enough, //
test_wuffs_gif_decode_pixel_data_too_much_sans_quirk, //
test_wuffs_gif_decode_pixel_data_too_much_with_quirk, //
+ test_wuffs_gif_decode_pixfmt_bgr, //
+ test_wuffs_gif_decode_pixfmt_bgra_nonpremul, //
+ test_wuffs_gif_decode_pixfmt_rgb, //
+ test_wuffs_gif_decode_pixfmt_rgba_nonpremul, //
test_wuffs_gif_decode_zero_width_frame, //
test_wuffs_gif_frame_dirty_rect, //
test_wuffs_gif_num_decoded_frame_configs, //