Make wuffs_base__pixel_format a struct
diff --git a/doc/changelog.md b/doc/changelog.md index a0dc932..6ee47ad 100644 --- a/doc/changelog.md +++ b/doc/changelog.md
@@ -4,6 +4,7 @@ ## Work In Progress - Renamed warnings to notes. +- Made `wuffs_base__pixel_format` a struct. - Made `wuffs_base__status` a struct.
diff --git a/example/gifplayer/gifplayer.c b/example/gifplayer/gifplayer.c index 8658bf3..9a7641f 100644 --- a/example/gifplayer/gifplayer.c +++ b/example/gifplayer/gifplayer.c
@@ -328,7 +328,8 @@ // Override the source's indexed pixel format to be non-indexed. wuffs_base__pixel_config__set( - &ic.pixcfg, WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL, + &ic.pixcfg, + wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL), WUFFS_BASE__PIXEL_SUBSAMPLING__NONE, width, height); const char* msg = allocate(&dec, &ic);
diff --git a/internal/cgen/base/image-impl.c b/internal/cgen/base/image-impl.c index a4dc400..540f05e 100644 --- a/internal/cgen/base/image-impl.c +++ b/internal/cgen/base/image-impl.c
@@ -169,9 +169,9 @@ uint64_t (*func)(wuffs_base__slice_u8 dst, wuffs_base__slice_u8 dst_palette, wuffs_base__slice_u8 src) = NULL; - switch (src_format) { + switch (src_format.repr) { case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: - switch (dst_format) { + switch (dst_format.repr) { case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
diff --git a/internal/cgen/base/image-private.h b/internal/cgen/base/image-private.h index 2da99eb..bd69978 100644 --- a/internal/cgen/base/image-private.h +++ b/internal/cgen/base/image-private.h
@@ -15,3 +15,7 @@ // limitations under the License. // ---------------- Images + +// ---------------- Images (Utility) + +#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format
diff --git a/internal/cgen/base/image-public.h b/internal/cgen/base/image-public.h index f300e17..8c046e9 100644 --- a/internal/cgen/base/image-public.h +++ b/internal/cgen/base/image-public.h
@@ -30,97 +30,103 @@ // // Do not manipulate its bits directly; they are private implementation // details. Use methods such as wuffs_base__pixel_format__num_planes instead. -typedef uint32_t wuffs_base__pixel_format; +typedef struct { + uint32_t repr; -// Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid -// wuffs_base__pixel_format values are present. +#ifdef __cplusplus + inline bool is_valid() const; + inline uint32_t bits_per_pixel() const; + inline bool is_indexed() const; + inline bool is_interleaved() const; + inline bool is_planar() const; + inline uint32_t num_planes() const; +#endif // __cplusplus -#define WUFFS_BASE__PIXEL_FORMAT__INVALID ((wuffs_base__pixel_format)0x00000000) +} wuffs_base__pixel_format; -#define WUFFS_BASE__PIXEL_FORMAT__A ((wuffs_base__pixel_format)0x02000008) +static inline wuffs_base__pixel_format // +wuffs_base__make_pixel_format(uint32_t repr) { + wuffs_base__pixel_format f; + f.repr = repr; + return f; +} -#define WUFFS_BASE__PIXEL_FORMAT__Y ((wuffs_base__pixel_format)0x10000008) -#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL \ - ((wuffs_base__pixel_format)0x15000008) -#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL \ - ((wuffs_base__pixel_format)0x16000008) + // Common 8-bit-depth pixel formats. This list is not exhaustive; not all + // valid wuffs_base__pixel_format values are present. -#define WUFFS_BASE__PIXEL_FORMAT__YCBCR ((wuffs_base__pixel_format)0x20020888) -#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK ((wuffs_base__pixel_format)0x21038888) -#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL \ - ((wuffs_base__pixel_format)0x25038888) +#define WUFFS_BASE__PIXEL_FORMAT__INVALID 0x00000000 -#define WUFFS_BASE__PIXEL_FORMAT__YCOCG ((wuffs_base__pixel_format)0x30020888) -#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK ((wuffs_base__pixel_format)0x31038888) -#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL \ - ((wuffs_base__pixel_format)0x35038888) +#define WUFFS_BASE__PIXEL_FORMAT__A 0x02000008 -#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL \ - ((wuffs_base__pixel_format)0x45040008) -#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL \ - ((wuffs_base__pixel_format)0x46040008) -#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY \ - ((wuffs_base__pixel_format)0x47040008) +#define WUFFS_BASE__PIXEL_FORMAT__Y 0x10000008 +#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL 0x15000008 +#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL 0x16000008 -#define WUFFS_BASE__PIXEL_FORMAT__BGR ((wuffs_base__pixel_format)0x40000888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRX ((wuffs_base__pixel_format)0x41008888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL \ - ((wuffs_base__pixel_format)0x45008888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL \ - ((wuffs_base__pixel_format)0x46008888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY \ - ((wuffs_base__pixel_format)0x47008888) +#define WUFFS_BASE__PIXEL_FORMAT__YCBCR 0x20020888 +#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK 0x21038888 +#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL 0x25038888 -#define WUFFS_BASE__PIXEL_FORMAT__RGB ((wuffs_base__pixel_format)0x50000888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBX ((wuffs_base__pixel_format)0x51008888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL \ - ((wuffs_base__pixel_format)0x55008888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL \ - ((wuffs_base__pixel_format)0x56008888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY \ - ((wuffs_base__pixel_format)0x57008888) +#define WUFFS_BASE__PIXEL_FORMAT__YCOCG 0x30020888 +#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK 0x31038888 +#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL 0x35038888 -#define WUFFS_BASE__PIXEL_FORMAT__CMY ((wuffs_base__pixel_format)0x60020888) -#define WUFFS_BASE__PIXEL_FORMAT__CMYK ((wuffs_base__pixel_format)0x61038888) +#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL 0x45040008 +#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL 0x46040008 +#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY 0x47040008 + +#define WUFFS_BASE__PIXEL_FORMAT__BGR 0x40000888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRX 0x41008888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL 0x45008888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL 0x46008888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY 0x47008888 + +#define WUFFS_BASE__PIXEL_FORMAT__RGB 0x50000888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBX 0x51008888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL 0x55008888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL 0x56008888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY 0x57008888 + +#define WUFFS_BASE__PIXEL_FORMAT__CMY 0x60020888 +#define WUFFS_BASE__PIXEL_FORMAT__CMYK 0x61038888 extern const uint32_t wuffs_base__pixel_format__bits_per_channel[16]; static inline bool // wuffs_base__pixel_format__is_valid(const wuffs_base__pixel_format* f) { - return *f != 0; + return f->repr != 0; } // wuffs_base__pixel_format__bits_per_pixel returns the number of bits per // pixel for interleaved pixel formats, and returns 0 for planar pixel formats. static inline uint32_t // wuffs_base__pixel_format__bits_per_pixel(const wuffs_base__pixel_format* f) { - if (((*f >> 16) & 0x03) != 0) { + if (((f->repr >> 16) & 0x03) != 0) { return 0; } - return wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 0)] + - wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 4)] + - wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 8)] + - wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 12)]; + return wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 0)] + + wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 4)] + + wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 8)] + + wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 12)]; } static inline bool // wuffs_base__pixel_format__is_indexed(const wuffs_base__pixel_format* f) { - return (*f >> 18) & 0x01; + return (f->repr >> 18) & 0x01; } static inline bool // wuffs_base__pixel_format__is_interleaved(const wuffs_base__pixel_format* f) { - return ((*f >> 16) & 0x03) == 0; + return ((f->repr >> 16) & 0x03) == 0; } static inline bool // wuffs_base__pixel_format__is_planar(const wuffs_base__pixel_format* f) { - return ((*f >> 16) & 0x03) != 0; + return ((f->repr >> 16) & 0x03) != 0; } static inline uint32_t // wuffs_base__pixel_format__num_planes(const wuffs_base__pixel_format* f) { - return ((*f >> 16) & 0x03) + 1; + return ((f->repr >> 16) & 0x03) + 1; } #define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4 @@ -128,6 +134,40 @@ #define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0 #define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3 +#ifdef __cplusplus + +inline bool // +wuffs_base__pixel_format::is_valid() const { + return wuffs_base__pixel_format__is_valid(this); +} + +inline uint32_t // +wuffs_base__pixel_format::bits_per_pixel() const { + return wuffs_base__pixel_format__bits_per_pixel(this); +} + +inline bool // +wuffs_base__pixel_format::is_indexed() const { + return wuffs_base__pixel_format__is_indexed(this); +} + +inline bool // +wuffs_base__pixel_format::is_interleaved() const { + return wuffs_base__pixel_format__is_interleaved(this); +} + +inline bool // +wuffs_base__pixel_format::is_planar() const { + return wuffs_base__pixel_format__is_planar(this); +} + +inline uint32_t // +wuffs_base__pixel_format::num_planes() const { + return wuffs_base__pixel_format__num_planes(this); +} + +#endif // __cplusplus + // -------- // wuffs_base__pixel_subsampling encodes whether sample values cover one pixel @@ -216,7 +256,7 @@ static inline wuffs_base__pixel_config // wuffs_base__null_pixel_config() { wuffs_base__pixel_config ret; - ret.private_impl.pixfmt = 0; + ret.private_impl.pixfmt.repr = 0; ret.private_impl.pixsub = 0; ret.private_impl.width = 0; ret.private_impl.height = 0; @@ -233,7 +273,7 @@ if (!c) { return; } - if (pixfmt) { + if (pixfmt.repr) { uint64_t wh = ((uint64_t)width) * ((uint64_t)height); // TODO: handle things other than 1 byte per pixel. if (wh <= ((uint64_t)SIZE_MAX)) { @@ -245,7 +285,7 @@ } } - c->private_impl.pixfmt = 0; + c->private_impl.pixfmt.repr = 0; c->private_impl.pixsub = 0; c->private_impl.width = 0; c->private_impl.height = 0; @@ -254,7 +294,7 @@ static inline void // wuffs_base__pixel_config__invalidate(wuffs_base__pixel_config* c) { if (c) { - c->private_impl.pixfmt = 0; + c->private_impl.pixfmt.repr = 0; c->private_impl.pixsub = 0; c->private_impl.width = 0; c->private_impl.height = 0; @@ -263,12 +303,12 @@ static inline bool // wuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) { - return c && c->private_impl.pixfmt; + return c && c->private_impl.pixfmt.repr; } static inline wuffs_base__pixel_format // wuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) { - return c ? c->private_impl.pixfmt : 0; + return c ? c->private_impl.pixfmt : wuffs_base__make_pixel_format(0); } static inline wuffs_base__pixel_subsampling // @@ -407,7 +447,7 @@ } private_impl; #ifdef __cplusplus - inline void set(wuffs_base__pixel_format pixfmt, + inline void set(uint32_t pixfmt_repr, wuffs_base__pixel_subsampling pixsub, uint32_t width, uint32_t height, @@ -433,7 +473,7 @@ // TODO: Should this function return bool? An error type? static inline void // wuffs_base__image_config__set(wuffs_base__image_config* c, - wuffs_base__pixel_format pixfmt, + uint32_t pixfmt_repr, wuffs_base__pixel_subsampling pixsub, uint32_t width, uint32_t height, @@ -442,8 +482,8 @@ if (!c) { return; } - if (wuffs_base__pixel_format__is_valid(&pixfmt)) { - c->pixcfg.private_impl.pixfmt = pixfmt; + if (pixfmt_repr) { + c->pixcfg.private_impl.pixfmt.repr = pixfmt_repr; c->pixcfg.private_impl.pixsub = pixsub; c->pixcfg.private_impl.width = width; c->pixcfg.private_impl.height = height; @@ -452,7 +492,7 @@ return; } - c->pixcfg.private_impl.pixfmt = 0; + c->pixcfg.private_impl.pixfmt.repr = 0; c->pixcfg.private_impl.pixsub = 0; c->pixcfg.private_impl.width = 0; c->pixcfg.private_impl.height = 0; @@ -463,7 +503,7 @@ static inline void // wuffs_base__image_config__invalidate(wuffs_base__image_config* c) { if (c) { - c->pixcfg.private_impl.pixfmt = 0; + c->pixcfg.private_impl.pixfmt.repr = 0; c->pixcfg.private_impl.pixsub = 0; c->pixcfg.private_impl.width = 0; c->pixcfg.private_impl.height = 0; @@ -492,13 +532,13 @@ #ifdef __cplusplus inline void // -wuffs_base__image_config::set(wuffs_base__pixel_format pixfmt, +wuffs_base__image_config::set(uint32_t pixfmt_repr, wuffs_base__pixel_subsampling pixsub, uint32_t width, uint32_t height, uint64_t first_frame_io_position, bool first_frame_is_opaque) { - wuffs_base__image_config__set(this, pixfmt, pixsub, width, height, + wuffs_base__image_config__set(this, pixfmt_repr, pixsub, width, height, first_frame_io_position, first_frame_is_opaque); } @@ -915,7 +955,7 @@ if (b) { return b->pixcfg.private_impl.pixfmt; } - return WUFFS_BASE__PIXEL_FORMAT__INVALID; + return wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__INVALID); } static inline wuffs_base__table_u8 //
diff --git a/internal/cgen/data.go b/internal/cgen/data.go index e1b4d80..33636c1 100644 --- a/internal/cgen/data.go +++ b/internal/cgen/data.go
@@ -28,9 +28,9 @@ "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__make_status(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_sw" + - "izzler__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_BA" + - "SE__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 wuffs_base__make_status(func ? NULL\n : wuffs_base__error__unsupported_option);\n}\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_interleaved(\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, dst_palette, src);\n }\n return 0;\n}\n" + + "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__make_status(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.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n switch (dst_format.repr) {\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 cas" + + "e 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 wuffs_base__make_status(func ? NULL\n : wuffs_base__error__unsupported_option);\n}\n\nuint64_t //\nwuffs_base__pixel_swizzler__swizzle_interleaved(\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, dst_palette, src);\n }\n return 0;\n}\n" + "" const baseCorePrivateH = "" + @@ -99,33 +99,35 @@ "" const baseImagePrivateH = "" + - "// ---------------- Images\n" + + "// ---------------- Images\n\n" + + "" + + "// ---------------- Images (Utility)\n\n#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format\n" + "" const baseImagePublicH = "" + "// ---------------- Images\n\n// wuffs_base__color_u32_argb_premul is an 8 bit per channel premultiplied\n// Alpha, Red, Green, Blue color, as a uint32_t value. It is in word order, not\n// byte order: its value is always 0xAARRGGBB, regardless of endianness.\ntypedef uint32_t wuffs_base__color_u32_argb_premul;\n\n" + "" + - "// --------\n\n// wuffs_base__pixel_format encodes the format of the bytes that constitute an\n// image frame's pixel data.\n//\n// See https://github.com/google/wuffs/blob/master/doc/note/pixel-formats.md\n//\n// Do not manipulate its bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_format__num_planes instead.\ntypedef uint32_t wuffs_base__pixel_format;\n\n// Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid\n// wuffs_base__pixel_format values are present.\n\n#define WUFFS_BASE__PIXEL_FORMAT__INVALID ((wuffs_base__pixel_format)0x00000000)\n\n#define WUFFS_BASE__PIXEL_FORMAT__A ((wuffs_base__pixel_format)0x02000008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__Y ((wuffs_base__pixel_format)0x10000008)\n#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x15000008)\n#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL \\\n ((wuffs_base__pixel_format)0x16000008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCR ((wuffs_base__pixel_format)0x20020888)\n#define" + - " WUFFS_BASE__PIXEL_FORMAT__YCBCRK ((wuffs_base__pixel_format)0x21038888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x25038888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCG ((wuffs_base__pixel_format)0x30020888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK ((wuffs_base__pixel_format)0x31038888)\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x35038888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x45040008)\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL \\\n ((wuffs_base__pixel_format)0x46040008)\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY \\\n ((wuffs_base__pixel_format)0x47040008)\n\n#define WUFFS_BASE__PIXEL_FORMAT__BGR ((wuffs_base__pixel_format)0x40000888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRX ((wuffs_base__pixel_format)0x41008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x45008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL \\\n ((wuffs" + - "_base__pixel_format)0x46008888)\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY \\\n ((wuffs_base__pixel_format)0x47008888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__RGB ((wuffs_base__pixel_format)0x50000888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBX ((wuffs_base__pixel_format)0x51008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL \\\n ((wuffs_base__pixel_format)0x55008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL \\\n ((wuffs_base__pixel_format)0x56008888)\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY \\\n ((wuffs_base__pixel_format)0x57008888)\n\n#define WUFFS_BASE__PIXEL_FORMAT__CMY ((wuffs_base__pixel_format)0x60020888)\n#define WUFFS_BASE__PIXEL_FORMAT__CMYK ((wuffs_base__pixel_format)0x61038888)\n\nextern const uint32_t wuffs_base__pixel_format__bits_per_channel[16];\n\nstatic inline bool //\nwuffs_base__pixel_format__is_valid(const wuffs_base__pixel_format* f) {\n return *f != 0;\n}\n\n// wuffs_base__pixel_format__bits_per_pixel returns the number of bits per\n// pixel for interleaved pixel formats, and returns 0 for " + - "planar pixel formats.\nstatic inline uint32_t //\nwuffs_base__pixel_format__bits_per_pixel(const 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(const wuffs_base__pixel_format* f) {\n return (*f >> 18) & 0x01;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_interleaved(const wuffs_base__pixel_format* f) {\n return ((*f >> 16) & 0x03) == 0;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_planar(const wuffs_base__pixel_format* f) {\n return ((*f >> 16) & 0x03) != 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_format__num_planes(const wuffs_base__pixel_format* f) {\n return ((*f >> 16) & 0x03) + 1;\n}\n\n#define WUFFS_B" + - "ASE__PIXEL_FORMAT__NUM_PLANES_MAX 4\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3\n\n" + + "// --------\n\n// wuffs_base__pixel_format encodes the format of the bytes that constitute an\n// image frame's pixel data.\n//\n// See https://github.com/google/wuffs/blob/master/doc/note/pixel-formats.md\n//\n// Do not manipulate its bits directly; they are private implementation\n// details. Use methods such as wuffs_base__pixel_format__num_planes instead.\ntypedef struct {\n uint32_t repr;\n\n#ifdef __cplusplus\n inline bool is_valid() const;\n inline uint32_t bits_per_pixel() const;\n inline bool is_indexed() const;\n inline bool is_interleaved() const;\n inline bool is_planar() const;\n inline uint32_t num_planes() const;\n#endif // __cplusplus\n\n} wuffs_base__pixel_format;\n\nstatic inline wuffs_base__pixel_format //\nwuffs_base__make_pixel_format(uint32_t repr) {\n wuffs_base__pixel_format f;\n f.repr = repr;\n return f;\n}\n\n // Common 8-bit-depth pixel formats. This list is not exhaustive; not all\n // valid wuffs_base__pixel_format values are present.\n\n#define WUFFS_BASE__PIXEL_FORMAT__INVALID 0x00000000\n\n#define" + + " WUFFS_BASE__PIXEL_FORMAT__A 0x02000008\n\n#define WUFFS_BASE__PIXEL_FORMAT__Y 0x10000008\n#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL 0x15000008\n#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL 0x16000008\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCR 0x20020888\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK 0x21038888\n#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL 0x25038888\n\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCG 0x30020888\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK 0x31038888\n#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL 0x35038888\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL 0x45040008\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL 0x46040008\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY 0x47040008\n\n#define WUFFS_BASE__PIXEL_FORMAT__BGR 0x40000888\n#define WUFFS_BASE__PIXEL_FORMAT__BGRX 0x41008888\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL 0x45008888\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL 0x46008888\n#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY 0x47008888\n\n#define WUFFS_" + + "BASE__PIXEL_FORMAT__RGB 0x50000888\n#define WUFFS_BASE__PIXEL_FORMAT__RGBX 0x51008888\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL 0x55008888\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL 0x56008888\n#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY 0x57008888\n\n#define WUFFS_BASE__PIXEL_FORMAT__CMY 0x60020888\n#define WUFFS_BASE__PIXEL_FORMAT__CMYK 0x61038888\n\nextern const uint32_t wuffs_base__pixel_format__bits_per_channel[16];\n\nstatic inline bool //\nwuffs_base__pixel_format__is_valid(const wuffs_base__pixel_format* f) {\n return f->repr != 0;\n}\n\n// wuffs_base__pixel_format__bits_per_pixel returns the number of bits per\n// pixel for interleaved pixel formats, and returns 0 for planar pixel formats.\nstatic inline uint32_t //\nwuffs_base__pixel_format__bits_per_pixel(const wuffs_base__pixel_format* f) {\n if (((f->repr >> 16) & 0x03) != 0) {\n return 0;\n }\n return wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 0)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 4)] +\n " + + " wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 8)] +\n wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 12)];\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_indexed(const wuffs_base__pixel_format* f) {\n return (f->repr >> 18) & 0x01;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_interleaved(const wuffs_base__pixel_format* f) {\n return ((f->repr >> 16) & 0x03) == 0;\n}\n\nstatic inline bool //\nwuffs_base__pixel_format__is_planar(const wuffs_base__pixel_format* f) {\n return ((f->repr >> 16) & 0x03) != 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_format__num_planes(const wuffs_base__pixel_format* f) {\n return ((f->repr >> 16) & 0x03) + 1;\n}\n\n#define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4\n\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0\n#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3\n\n#ifdef __cplusplus\n\ninline bool //\nwuffs_base__pixel_format::is_valid() const {\n return wuffs_base__pixel_format__is_valid(this);\n}\n\ninline " + + "uint32_t //\nwuffs_base__pixel_format::bits_per_pixel() const {\n return wuffs_base__pixel_format__bits_per_pixel(this);\n}\n\ninline bool //\nwuffs_base__pixel_format::is_indexed() const {\n return wuffs_base__pixel_format__is_indexed(this);\n}\n\ninline bool //\nwuffs_base__pixel_format::is_interleaved() const {\n return wuffs_base__pixel_format__is_interleaved(this);\n}\n\ninline bool //\nwuffs_base__pixel_format::is_planar() const {\n return wuffs_base__pixel_format__is_planar(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_format::num_planes() const {\n return wuffs_base__pixel_format__num_planes(this);\n}\n\n#endif // __cplusplus\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(const 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(\n const 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(const 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(\n const 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" + - "nfig__invalidate(wuffs_base__pixel_config* c) {\n if (c) {\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}\n\nstatic inline bool //\nwuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {\n return c && c->private_impl.pixfmt;\n}\n\nstatic inline wuffs_base__pixel_format //\nwuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixfmt : 0;\n}\n\nstatic inline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixsub : 0;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {\n if (c) {\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = c->private_impl.width;\n ret.max_excl_y = c->private_impl.height;\n return ret;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl" + - "_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.width : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.height : 0;\n}\n\n// TODO: this is the right API for planar (not interleaved) pixbufs? Should it\n// allow decoding into a color model different from the format's intrinsic one?\n// For example, decoding a JPEG image straight to RGBA instead of to YCbCr?\nstatic inline uint64_t //\nwuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {\n if (!c) {\n return 0;\n }\n if (wuffs_base__pixel_format__is_planar(&c->private_impl.pixfmt)) {\n // TODO: support planar pixel formats, concious of pixel subsampling.\n return 0;\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_pixel(&c->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 0;\n }\n uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n uint64_t n =\n ((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);\n if (n > (UINT64_MAX / bytes_per_pixel)) {\n return 0;\n }\n n *= bytes_per_pixel;\n\n if (wuffs_base__pixel_format__is_indexed(&c->private_impl.pixfmt)) {\n if (n > (UINT64_MAX - 1024)) {\n return 0;\n }\n n += 1024;\n }\n\n return n;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__pixel_config::set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height) {\n wuffs_base__pixel_config__set(this, pixfmt, pixsub, width, height);\n}\n\ninline void //\nwuffs_base__pixel_config::invalidate() {\n wuffs_base__pixel_config__invalidate(this);\n}\n\ninline bool //\nwuffs_base__pixel_config::is_valid() const {\n ret" + - "urn wuffs_base__pixel_config__is_valid(this);\n}\n\ninline wuffs_base__pixel_format //\nwuffs_base__pixel_config::pixel_format() const {\n return wuffs_base__pixel_config__pixel_format(this);\n}\n\ninline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config::pixel_subsampling() const {\n return wuffs_base__pixel_config__pixel_subsampling(this);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config::bounds() const {\n return wuffs_base__pixel_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::width() const {\n return wuffs_base__pixel_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::height() const {\n return wuffs_base__pixel_config__height(this);\n}\n\ninline uint64_t //\nwuffs_base__pixel_config::pixbuf_len() const {\n return wuffs_base__pixel_config__pixbuf_len(this);\n}\n\n#endif // __cplusplus\n\n" + + "fmt.repr = 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.repr) {\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.repr = 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_config__invalidate(wuffs_base__pixel_config* c) {\n if (c) {\n c->private_impl.pixfmt.repr = 0;\n c->private_impl.pixsub = 0;\n c->private_impl.width = 0;\n c->private_impl.height = 0;\n }\n}\n\nstatic inline bool //\nwuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) {\n return c && c->private_impl.pixfmt.repr;\n}\n\nstatic inline wuffs_base__pixel_format //\nwuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixfmt : wuffs_base__make_pixel_format(0);\n}\n\nstatic inline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config__pixel_subsampling(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.pixsub : 0;\n}\n\nstatic inline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config__bounds(const wuffs_base__pixel_config* c) {\n if (c) {\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = c->private_impl.width;\n ret.max_excl_y = c->private_impl.height;\n return" + + " ret;\n }\n\n wuffs_base__rect_ie_u32 ret;\n ret.min_incl_x = 0;\n ret.min_incl_y = 0;\n ret.max_excl_x = 0;\n ret.max_excl_y = 0;\n return ret;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__width(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.width : 0;\n}\n\nstatic inline uint32_t //\nwuffs_base__pixel_config__height(const wuffs_base__pixel_config* c) {\n return c ? c->private_impl.height : 0;\n}\n\n// TODO: this is the right API for planar (not interleaved) pixbufs? Should it\n// allow decoding into a color model different from the format's intrinsic one?\n// For example, decoding a JPEG image straight to RGBA instead of to YCbCr?\nstatic inline uint64_t //\nwuffs_base__pixel_config__pixbuf_len(const wuffs_base__pixel_config* c) {\n if (!c) {\n return 0;\n }\n if (wuffs_base__pixel_format__is_planar(&c->private_impl.pixfmt)) {\n // TODO: support planar pixel formats, concious of pixel subsampling.\n return 0;\n }\n uint32_t bits_per_pixel =\n wuffs_base__pixel_format__bits_per_" + + "pixel(&c->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 0;\n }\n uint64_t bytes_per_pixel = bits_per_pixel / 8;\n\n uint64_t n =\n ((uint64_t)c->private_impl.width) * ((uint64_t)c->private_impl.height);\n if (n > (UINT64_MAX / bytes_per_pixel)) {\n return 0;\n }\n n *= bytes_per_pixel;\n\n if (wuffs_base__pixel_format__is_indexed(&c->private_impl.pixfmt)) {\n if (n > (UINT64_MAX - 1024)) {\n return 0;\n }\n n += 1024;\n }\n\n return n;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__pixel_config::set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height) {\n wuffs_base__pixel_config__set(this, pixfmt, pixsub, width, height);\n}\n\ninline void //\nwuffs_base__pixel_config::invalidate() {\n wuffs_base__pixel_config__invalidate(this);\n}\n\ninline boo" + + "l //\nwuffs_base__pixel_config::is_valid() const {\n return wuffs_base__pixel_config__is_valid(this);\n}\n\ninline wuffs_base__pixel_format //\nwuffs_base__pixel_config::pixel_format() const {\n return wuffs_base__pixel_config__pixel_format(this);\n}\n\ninline wuffs_base__pixel_subsampling //\nwuffs_base__pixel_config::pixel_subsampling() const {\n return wuffs_base__pixel_config__pixel_subsampling(this);\n}\n\ninline wuffs_base__rect_ie_u32 //\nwuffs_base__pixel_config::bounds() const {\n return wuffs_base__pixel_config__bounds(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::width() const {\n return wuffs_base__pixel_config__width(this);\n}\n\ninline uint32_t //\nwuffs_base__pixel_config::height() const {\n return wuffs_base__pixel_config__height(this);\n}\n\ninline uint64_t //\nwuffs_base__pixel_config::pixbuf_len() const {\n return wuffs_base__pixel_config__pixbuf_len(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 uint64_t first_frame_io_position;\n bool first_frame_is_opaque;\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 uint64_t first_frame_io_position,\n bool first_frame_is_opaque);\n inline void invalidate();\n inline bool is_valid() const;\n inline uint64_t first_frame_io_position() const;\n inline bool first_frame_is_opaque() const;\n#endif // __cplusplus\n\n} wuffs_base__image_config;\n\nstatic inline wuffs_base__image_config //\nwuffs_base__null_image_config() {\n wuffs_base__image_config ret;\n ret.pixcfg = wuffs_base__null_pixel_config();\n ret.private_impl.first_frame_io_position = 0;\n ret.private_impl.fir" + - "st_frame_is_opaque = false;\n return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void //\nwuffs_base__image_config__set(wuffs_base__image_config* c,\n wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n if (!c) {\n return;\n }\n if (wuffs_base__pixel_format__is_valid(&pixfmt)) {\n c->pixcfg.private_impl.pixfmt = pixfmt;\n c->pixcfg.private_impl.pixsub = pixsub;\n c->pixcfg.private_impl.width = width;\n c->pixcfg.private_impl.height = height;\n c->private_impl.first_frame_io_position = first_frame_io_position;\n c->private_impl.first_frame_is_opaque = first_frame_is_opaque;\n return;\n }\n\n c->pixcfg.private_impl.pixfmt = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pi" + - "xcfg.private_impl.width = 0;\n c->pixcfg.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n}\n\nstatic inline void //\nwuffs_base__image_config__invalidate(wuffs_base__image_config* c) {\n if (c) {\n c->pixcfg.private_impl.pixfmt = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pixcfg.private_impl.width = 0;\n c->pixcfg.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n }\n}\n\nstatic inline bool //\nwuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {\n return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));\n}\n\nstatic inline uint64_t //\nwuffs_base__image_config__first_frame_io_position(\n const wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_io_position : 0;\n}\n\nstatic inline bool //\nwuffs_base__image_config__first_frame_is_opaque(\n const wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_is_opaq" + - "ue : false;\n}\n\n#ifdef __cplusplus\n\ninline void //\nwuffs_base__image_config::set(wuffs_base__pixel_format pixfmt,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n wuffs_base__image_config__set(this, pixfmt, pixsub, width, height,\n first_frame_io_position, first_frame_is_opaque);\n}\n\ninline void //\nwuffs_base__image_config::invalidate() {\n wuffs_base__image_config__invalidate(this);\n}\n\ninline bool //\nwuffs_base__image_config::is_valid() const {\n return wuffs_base__image_config__is_valid(this);\n}\n\ninline uint64_t //\nwuffs_base__image_config::first_frame_io_position() const {\n return wuffs_base__image_config__first_frame_io_position(this);\n}\n\ninline bool //\nwuffs_base__image_config::first_frame_is_opaque() const {\n return wuffs_base__image_c" + - "onfig__first_frame_is_opaque(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 uint64_t first_frame_io_position;\n bool first_frame_is_opaque;\n } private_impl;\n\n#ifdef __cplusplus\n inline void set(uint32_t pixfmt_repr,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque);\n inline void invalidate();\n inline bool is_valid() const;\n inline uint64_t first_frame_io_position() const;\n inline bool first_frame_is_opaque() const;\n#endif // __cplusplus\n\n} wuffs_base__image_config;\n\nstatic inline wuffs_base__image_config //\nwuffs_base__null_image_config() {\n wuffs_base__image_config ret;\n ret.pixcfg = wuffs_base__null_pixel_config();\n ret.private_impl.first_frame_io_position = 0;\n ret.private_impl.first_frame_is" + + "_opaque = false;\n return ret;\n}\n\n// TODO: Should this function return bool? An error type?\nstatic inline void //\nwuffs_base__image_config__set(wuffs_base__image_config* c,\n uint32_t pixfmt_repr,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n if (!c) {\n return;\n }\n if (pixfmt_repr) {\n c->pixcfg.private_impl.pixfmt.repr = pixfmt_repr;\n c->pixcfg.private_impl.pixsub = pixsub;\n c->pixcfg.private_impl.width = width;\n c->pixcfg.private_impl.height = height;\n c->private_impl.first_frame_io_position = first_frame_io_position;\n c->private_impl.first_frame_is_opaque = first_frame_is_opaque;\n return;\n }\n\n c->pixcfg.private_impl.pixfmt.repr = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pixcfg.private_impl.width = 0;\n c->pixcf" + + "g.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n}\n\nstatic inline void //\nwuffs_base__image_config__invalidate(wuffs_base__image_config* c) {\n if (c) {\n c->pixcfg.private_impl.pixfmt.repr = 0;\n c->pixcfg.private_impl.pixsub = 0;\n c->pixcfg.private_impl.width = 0;\n c->pixcfg.private_impl.height = 0;\n c->private_impl.first_frame_io_position = 0;\n c->private_impl.first_frame_is_opaque = 0;\n }\n}\n\nstatic inline bool //\nwuffs_base__image_config__is_valid(const wuffs_base__image_config* c) {\n return c && wuffs_base__pixel_config__is_valid(&(c->pixcfg));\n}\n\nstatic inline uint64_t //\nwuffs_base__image_config__first_frame_io_position(\n const wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_io_position : 0;\n}\n\nstatic inline bool //\nwuffs_base__image_config__first_frame_is_opaque(\n const wuffs_base__image_config* c) {\n return c ? c->private_impl.first_frame_is_opaque : false;\n}\n\n#ifdef __cplusplus\n" + + "\ninline void //\nwuffs_base__image_config::set(uint32_t pixfmt_repr,\n wuffs_base__pixel_subsampling pixsub,\n uint32_t width,\n uint32_t height,\n uint64_t first_frame_io_position,\n bool first_frame_is_opaque) {\n wuffs_base__image_config__set(this, pixfmt_repr, pixsub, width, height,\n first_frame_io_position, first_frame_is_opaque);\n}\n\ninline void //\nwuffs_base__image_config::invalidate() {\n wuffs_base__image_config__invalidate(this);\n}\n\ninline bool //\nwuffs_base__image_config::is_valid() const {\n return wuffs_base__image_config__is_valid(this);\n}\n\ninline uint64_t //\nwuffs_base__image_config::first_frame_io_position() const {\n return wuffs_base__image_config__first_frame_io_position(this);\n}\n\ninline bool //\nwuffs_base__image_config::first_frame_is_opaque() const {\n return wuffs_base__image_config__first_frame_is_opaque(this);\n}\n\n#" + + "endif // __cplusplus\n\n" + "" + "// --------\n\n// wuffs_base__animation_blend encodes, for an animated image, how to blend the\n// transparent pixels of this frame with the existing canvas. In Porter-Duff\n// compositing operator terminology:\n// - 0 means the frame may be transparent, and should be blended \"src over\n// dst\", also known as just \"over\".\n// - 1 means the frame may be transparent, and should be blended \"src\".\n// - 2 means the frame is completely opaque, so that \"src over dst\" and \"src\"\n// are equivalent.\n//\n// These semantics are conservative. It is valid for a completely opaque frame\n// to have a blend value other than 2.\ntypedef uint8_t wuffs_base__animation_blend;\n\n#define WUFFS_BASE__ANIMATION_BLEND__SRC_OVER_DST \\\n ((wuffs_base__animation_blend)0)\n#define WUFFS_BASE__ANIMATION_BLEND__SRC ((wuffs_base__animation_blend)1)\n#define WUFFS_BASE__ANIMATION_BLEND__OPAQUE ((wuffs_base__animation_blend)2)\n\n" + "" + @@ -144,9 +146,9 @@ "pixel == 0) || ((bits_per_pixel % 8) != 0)) {\n // TODO: support fraction-of-byte pixels, e.g. 1 bit per pixel?\n return wuffs_base__make_status(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__make_status(\n 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__make_status(wuffs_base__error__bad_argument);\n }\n wh *= bytes_per_pixel;\n width *= bytes_per_pixel;\n if (wh > len) {\n return wuffs_base__make_status(\n 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 wuffs_base__make_status(NULL);\n}\n\nstatic inline wuffs_base__status //\nwuffs_base__pixel_buffer__set_from_table(wuffs_base__pixel_buffer* b,\n const wuffs_base__pixel_config* pixcfg,\n wuffs_base__table_u8 pixbuf_memory) {\n if (" + "!b) {\n return wuffs_base__make_status(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_base__make_status(wuffs_base__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__make_status(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__make_status(wuffs_base__error__bad_argument);\n }\n\n b->pixcfg = *pixcfg;\n b->private_impl.planes[0] = pixbuf_memory;\n return wuffs_base__make_status(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(const 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(const 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" + + "// 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__make_pixel_format(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 retur" + + "n 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(const 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(const 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/lang/builtin/builtin.go b/lang/builtin/builtin.go index d3bbe9d..a924694 100644 --- a/lang/builtin/builtin.go +++ b/lang/builtin/builtin.go
@@ -82,6 +82,7 @@ "image_config", "pixel_buffer", "pixel_config", + "pixel_format", "pixel_swizzler", "decode_frame_options", @@ -113,6 +114,7 @@ "utility.empty_io_reader() io_reader", "utility.empty_io_writer() io_writer", "utility.empty_slice_u8() slice u8", + "utility.make_pixel_format(repr: u32) pixel_format", "utility.make_range_ii_u32(min_incl: u32, max_incl: u32) range_ii_u32", "utility.make_range_ie_u32(min_incl: u32, max_excl: u32) range_ie_u32", "utility.make_range_ii_u64(min_incl: u64, max_incl: u64) range_ii_u64", @@ -319,13 +321,18 @@ // ---- pixel_buffer "pixel_buffer.palette() slice u8", - "pixel_buffer.pixel_format() u32", + "pixel_buffer.pixel_format() pixel_format", "pixel_buffer.plane(p: u32[..= 3]) table u8", + // ---- pixel_format + + "pixel_format.bits_per_pixel() u32", + // ---- pixel_swizzler "pixel_swizzler.prepare!(" + - "dst_pixfmt: u32, dst_palette: slice u8, src_pixfmt: u32, src_palette: slice u8) status", + "dst_pixfmt: pixel_format, dst_palette: slice u8, " + + "src_pixfmt: pixel_format, src_palette: slice u8) status", "pixel_swizzler.swizzle_interleaved!(" + "dst: slice u8, dst_palette: slice u8, src: slice u8) u64", }
diff --git a/lang/check/resolve.go b/lang/check/resolve.go index 11bb624..0b66ffa 100644 --- a/lang/check/resolve.go +++ b/lang/check/resolve.go
@@ -63,6 +63,7 @@ typeExprImageConfig = a.NewTypeExpr(0, t.IDBase, t.IDImageConfig, nil, nil, nil) typeExprPixelBuffer = a.NewTypeExpr(0, t.IDBase, t.IDPixelBuffer, nil, nil, nil) typeExprPixelConfig = a.NewTypeExpr(0, t.IDBase, t.IDPixelConfig, nil, nil, nil) + typeExprPixelFormat = a.NewTypeExpr(0, t.IDBase, t.IDPixelFormat, nil, nil, nil) typeExprPixelSwizzler = a.NewTypeExpr(0, t.IDBase, t.IDPixelSwizzler, nil, nil, nil) typeExprDecodeFrameOptions = a.NewTypeExpr(0, t.IDBase, t.IDDecodeFrameOptions, nil, nil, nil) @@ -104,6 +105,7 @@ t.IDImageConfig: typeExprImageConfig, t.IDPixelBuffer: typeExprPixelBuffer, t.IDPixelConfig: typeExprPixelConfig, + t.IDPixelFormat: typeExprPixelFormat, t.IDPixelSwizzler: typeExprPixelSwizzler, t.IDDecodeFrameOptions: typeExprDecodeFrameOptions,
diff --git a/lang/token/list.go b/lang/token/list.go index da5063f..5393ade 100644 --- a/lang/token/list.go +++ b/lang/token/list.go
@@ -462,7 +462,8 @@ IDImageConfig = ID(0x151) IDPixelBuffer = ID(0x152) IDPixelConfig = ID(0x153) - IDPixelSwizzler = ID(0x154) + IDPixelFormat = ID(0x154) + IDPixelSwizzler = ID(0x155) IDDecodeFrameOptions = ID(0x158) @@ -801,6 +802,7 @@ IDImageConfig: "image_config", IDPixelBuffer: "pixel_buffer", IDPixelConfig: "pixel_config", + IDPixelFormat: "pixel_format", IDPixelSwizzler: "pixel_swizzler", IDDecodeFrameOptions: "decode_frame_options",
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c index f32e6d2..9105c1c 100644 --- a/release/c/wuffs-unsupported-snapshot.c +++ b/release/c/wuffs-unsupported-snapshot.c
@@ -1472,97 +1472,103 @@ // // Do not manipulate its bits directly; they are private implementation // details. Use methods such as wuffs_base__pixel_format__num_planes instead. -typedef uint32_t wuffs_base__pixel_format; +typedef struct { + uint32_t repr; -// Common 8-bit-depth pixel formats. This list is not exhaustive; not all valid -// wuffs_base__pixel_format values are present. +#ifdef __cplusplus + inline bool is_valid() const; + inline uint32_t bits_per_pixel() const; + inline bool is_indexed() const; + inline bool is_interleaved() const; + inline bool is_planar() const; + inline uint32_t num_planes() const; +#endif // __cplusplus -#define WUFFS_BASE__PIXEL_FORMAT__INVALID ((wuffs_base__pixel_format)0x00000000) +} wuffs_base__pixel_format; -#define WUFFS_BASE__PIXEL_FORMAT__A ((wuffs_base__pixel_format)0x02000008) +static inline wuffs_base__pixel_format // +wuffs_base__make_pixel_format(uint32_t repr) { + wuffs_base__pixel_format f; + f.repr = repr; + return f; +} -#define WUFFS_BASE__PIXEL_FORMAT__Y ((wuffs_base__pixel_format)0x10000008) -#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL \ - ((wuffs_base__pixel_format)0x15000008) -#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL \ - ((wuffs_base__pixel_format)0x16000008) + // Common 8-bit-depth pixel formats. This list is not exhaustive; not all + // valid wuffs_base__pixel_format values are present. -#define WUFFS_BASE__PIXEL_FORMAT__YCBCR ((wuffs_base__pixel_format)0x20020888) -#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK ((wuffs_base__pixel_format)0x21038888) -#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL \ - ((wuffs_base__pixel_format)0x25038888) +#define WUFFS_BASE__PIXEL_FORMAT__INVALID 0x00000000 -#define WUFFS_BASE__PIXEL_FORMAT__YCOCG ((wuffs_base__pixel_format)0x30020888) -#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK ((wuffs_base__pixel_format)0x31038888) -#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL \ - ((wuffs_base__pixel_format)0x35038888) +#define WUFFS_BASE__PIXEL_FORMAT__A 0x02000008 -#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL \ - ((wuffs_base__pixel_format)0x45040008) -#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL \ - ((wuffs_base__pixel_format)0x46040008) -#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY \ - ((wuffs_base__pixel_format)0x47040008) +#define WUFFS_BASE__PIXEL_FORMAT__Y 0x10000008 +#define WUFFS_BASE__PIXEL_FORMAT__YA_NONPREMUL 0x15000008 +#define WUFFS_BASE__PIXEL_FORMAT__YA_PREMUL 0x16000008 -#define WUFFS_BASE__PIXEL_FORMAT__BGR ((wuffs_base__pixel_format)0x40000888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRX ((wuffs_base__pixel_format)0x41008888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL \ - ((wuffs_base__pixel_format)0x45008888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL \ - ((wuffs_base__pixel_format)0x46008888) -#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY \ - ((wuffs_base__pixel_format)0x47008888) +#define WUFFS_BASE__PIXEL_FORMAT__YCBCR 0x20020888 +#define WUFFS_BASE__PIXEL_FORMAT__YCBCRK 0x21038888 +#define WUFFS_BASE__PIXEL_FORMAT__YCBCRA_NONPREMUL 0x25038888 -#define WUFFS_BASE__PIXEL_FORMAT__RGB ((wuffs_base__pixel_format)0x50000888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBX ((wuffs_base__pixel_format)0x51008888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL \ - ((wuffs_base__pixel_format)0x55008888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL \ - ((wuffs_base__pixel_format)0x56008888) -#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY \ - ((wuffs_base__pixel_format)0x57008888) +#define WUFFS_BASE__PIXEL_FORMAT__YCOCG 0x30020888 +#define WUFFS_BASE__PIXEL_FORMAT__YCOCGK 0x31038888 +#define WUFFS_BASE__PIXEL_FORMAT__YCOCGA_NONPREMUL 0x35038888 -#define WUFFS_BASE__PIXEL_FORMAT__CMY ((wuffs_base__pixel_format)0x60020888) -#define WUFFS_BASE__PIXEL_FORMAT__CMYK ((wuffs_base__pixel_format)0x61038888) +#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL 0x45040008 +#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL 0x46040008 +#define WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY 0x47040008 + +#define WUFFS_BASE__PIXEL_FORMAT__BGR 0x40000888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRX 0x41008888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL 0x45008888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL 0x46008888 +#define WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY 0x47008888 + +#define WUFFS_BASE__PIXEL_FORMAT__RGB 0x50000888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBX 0x51008888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL 0x55008888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL 0x56008888 +#define WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY 0x57008888 + +#define WUFFS_BASE__PIXEL_FORMAT__CMY 0x60020888 +#define WUFFS_BASE__PIXEL_FORMAT__CMYK 0x61038888 extern const uint32_t wuffs_base__pixel_format__bits_per_channel[16]; static inline bool // wuffs_base__pixel_format__is_valid(const wuffs_base__pixel_format* f) { - return *f != 0; + return f->repr != 0; } // wuffs_base__pixel_format__bits_per_pixel returns the number of bits per // pixel for interleaved pixel formats, and returns 0 for planar pixel formats. static inline uint32_t // wuffs_base__pixel_format__bits_per_pixel(const wuffs_base__pixel_format* f) { - if (((*f >> 16) & 0x03) != 0) { + if (((f->repr >> 16) & 0x03) != 0) { return 0; } - return wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 0)] + - wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 4)] + - wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 8)] + - wuffs_base__pixel_format__bits_per_channel[0x0F & (*f >> 12)]; + return wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 0)] + + wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 4)] + + wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 8)] + + wuffs_base__pixel_format__bits_per_channel[0x0F & (f->repr >> 12)]; } static inline bool // wuffs_base__pixel_format__is_indexed(const wuffs_base__pixel_format* f) { - return (*f >> 18) & 0x01; + return (f->repr >> 18) & 0x01; } static inline bool // wuffs_base__pixel_format__is_interleaved(const wuffs_base__pixel_format* f) { - return ((*f >> 16) & 0x03) == 0; + return ((f->repr >> 16) & 0x03) == 0; } static inline bool // wuffs_base__pixel_format__is_planar(const wuffs_base__pixel_format* f) { - return ((*f >> 16) & 0x03) != 0; + return ((f->repr >> 16) & 0x03) != 0; } static inline uint32_t // wuffs_base__pixel_format__num_planes(const wuffs_base__pixel_format* f) { - return ((*f >> 16) & 0x03) + 1; + return ((f->repr >> 16) & 0x03) + 1; } #define WUFFS_BASE__PIXEL_FORMAT__NUM_PLANES_MAX 4 @@ -1570,6 +1576,40 @@ #define WUFFS_BASE__PIXEL_FORMAT__INDEXED__INDEX_PLANE 0 #define WUFFS_BASE__PIXEL_FORMAT__INDEXED__COLOR_PLANE 3 +#ifdef __cplusplus + +inline bool // +wuffs_base__pixel_format::is_valid() const { + return wuffs_base__pixel_format__is_valid(this); +} + +inline uint32_t // +wuffs_base__pixel_format::bits_per_pixel() const { + return wuffs_base__pixel_format__bits_per_pixel(this); +} + +inline bool // +wuffs_base__pixel_format::is_indexed() const { + return wuffs_base__pixel_format__is_indexed(this); +} + +inline bool // +wuffs_base__pixel_format::is_interleaved() const { + return wuffs_base__pixel_format__is_interleaved(this); +} + +inline bool // +wuffs_base__pixel_format::is_planar() const { + return wuffs_base__pixel_format__is_planar(this); +} + +inline uint32_t // +wuffs_base__pixel_format::num_planes() const { + return wuffs_base__pixel_format__num_planes(this); +} + +#endif // __cplusplus + // -------- // wuffs_base__pixel_subsampling encodes whether sample values cover one pixel @@ -1658,7 +1698,7 @@ static inline wuffs_base__pixel_config // wuffs_base__null_pixel_config() { wuffs_base__pixel_config ret; - ret.private_impl.pixfmt = 0; + ret.private_impl.pixfmt.repr = 0; ret.private_impl.pixsub = 0; ret.private_impl.width = 0; ret.private_impl.height = 0; @@ -1675,7 +1715,7 @@ if (!c) { return; } - if (pixfmt) { + if (pixfmt.repr) { uint64_t wh = ((uint64_t)width) * ((uint64_t)height); // TODO: handle things other than 1 byte per pixel. if (wh <= ((uint64_t)SIZE_MAX)) { @@ -1687,7 +1727,7 @@ } } - c->private_impl.pixfmt = 0; + c->private_impl.pixfmt.repr = 0; c->private_impl.pixsub = 0; c->private_impl.width = 0; c->private_impl.height = 0; @@ -1696,7 +1736,7 @@ static inline void // wuffs_base__pixel_config__invalidate(wuffs_base__pixel_config* c) { if (c) { - c->private_impl.pixfmt = 0; + c->private_impl.pixfmt.repr = 0; c->private_impl.pixsub = 0; c->private_impl.width = 0; c->private_impl.height = 0; @@ -1705,12 +1745,12 @@ static inline bool // wuffs_base__pixel_config__is_valid(const wuffs_base__pixel_config* c) { - return c && c->private_impl.pixfmt; + return c && c->private_impl.pixfmt.repr; } static inline wuffs_base__pixel_format // wuffs_base__pixel_config__pixel_format(const wuffs_base__pixel_config* c) { - return c ? c->private_impl.pixfmt : 0; + return c ? c->private_impl.pixfmt : wuffs_base__make_pixel_format(0); } static inline wuffs_base__pixel_subsampling // @@ -1849,7 +1889,7 @@ } private_impl; #ifdef __cplusplus - inline void set(wuffs_base__pixel_format pixfmt, + inline void set(uint32_t pixfmt_repr, wuffs_base__pixel_subsampling pixsub, uint32_t width, uint32_t height, @@ -1875,7 +1915,7 @@ // TODO: Should this function return bool? An error type? static inline void // wuffs_base__image_config__set(wuffs_base__image_config* c, - wuffs_base__pixel_format pixfmt, + uint32_t pixfmt_repr, wuffs_base__pixel_subsampling pixsub, uint32_t width, uint32_t height, @@ -1884,8 +1924,8 @@ if (!c) { return; } - if (wuffs_base__pixel_format__is_valid(&pixfmt)) { - c->pixcfg.private_impl.pixfmt = pixfmt; + if (pixfmt_repr) { + c->pixcfg.private_impl.pixfmt.repr = pixfmt_repr; c->pixcfg.private_impl.pixsub = pixsub; c->pixcfg.private_impl.width = width; c->pixcfg.private_impl.height = height; @@ -1894,7 +1934,7 @@ return; } - c->pixcfg.private_impl.pixfmt = 0; + c->pixcfg.private_impl.pixfmt.repr = 0; c->pixcfg.private_impl.pixsub = 0; c->pixcfg.private_impl.width = 0; c->pixcfg.private_impl.height = 0; @@ -1905,7 +1945,7 @@ static inline void // wuffs_base__image_config__invalidate(wuffs_base__image_config* c) { if (c) { - c->pixcfg.private_impl.pixfmt = 0; + c->pixcfg.private_impl.pixfmt.repr = 0; c->pixcfg.private_impl.pixsub = 0; c->pixcfg.private_impl.width = 0; c->pixcfg.private_impl.height = 0; @@ -1934,13 +1974,13 @@ #ifdef __cplusplus inline void // -wuffs_base__image_config::set(wuffs_base__pixel_format pixfmt, +wuffs_base__image_config::set(uint32_t pixfmt_repr, wuffs_base__pixel_subsampling pixsub, uint32_t width, uint32_t height, uint64_t first_frame_io_position, bool first_frame_is_opaque) { - wuffs_base__image_config__set(this, pixfmt, pixsub, width, height, + wuffs_base__image_config__set(this, pixfmt_repr, pixsub, width, height, first_frame_io_position, first_frame_is_opaque); } @@ -2357,7 +2397,7 @@ if (b) { return b->pixcfg.private_impl.pixfmt; } - return WUFFS_BASE__PIXEL_FORMAT__INVALID; + return wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__INVALID); } static inline wuffs_base__table_u8 // @@ -4491,6 +4531,10 @@ // ---------------- Images + // ---------------- Images (Utility) + +#define wuffs_base__utility__make_pixel_format wuffs_base__make_pixel_format + #if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) const uint8_t wuffs_base__low_bits_mask__u8[9] = { @@ -4720,9 +4764,9 @@ uint64_t (*func)(wuffs_base__slice_u8 dst, wuffs_base__slice_u8 dst_palette, wuffs_base__slice_u8 src) = NULL; - switch (src_format) { + switch (src_format.repr) { case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: - switch (dst_format) { + switch (dst_format.repr) { case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL: case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: @@ -10645,7 +10689,7 @@ v_status = wuffs_base__pixel_swizzler__prepare( &self->private_impl.f_swizzler, wuffs_base__pixel_buffer__pixel_format(a_dst), v_dst_palette, - 1191444488, + wuffs_base__utility__make_pixel_format(1191444488), wuffs_base__make_slice_u8( self->private_data.f_palettes[v_which_palette], 1024)); if (!wuffs_base__status__is_ok(&v_status)) { @@ -10957,8 +11001,9 @@ uint64_t v_width_in_bytes = 0; uint64_t v_n = 0; uint64_t v_src_ri = 0; + wuffs_base__pixel_format v_pixfmt = {0}; uint32_t v_bytes_per_pixel = 0; - uint32_t v_pixfmt_channels = 0; + uint32_t v_bits_per_pixel = 0; wuffs_base__table_u8 v_tab = {0}; uint64_t v_i = 0; uint64_t v_j = 0; @@ -10967,12 +11012,13 @@ wuffs_base__slice_u8 v_replicate_dst = {0}; wuffs_base__slice_u8 v_replicate_src = {0}; - v_pixfmt_channels = (wuffs_base__pixel_buffer__pixel_format(a_pb) & 65535); - if (v_pixfmt_channels == 34952) { + v_pixfmt = wuffs_base__pixel_buffer__pixel_format(a_pb); + v_bits_per_pixel = wuffs_base__pixel_format__bits_per_pixel(&v_pixfmt); + if (v_bits_per_pixel == 32) { v_bytes_per_pixel = 4; - } else if (v_pixfmt_channels == 2184) { + } else if (v_bits_per_pixel == 24) { v_bytes_per_pixel = 3; - } else if (v_pixfmt_channels == 8) { + } else if (v_bits_per_pixel == 8) { v_bytes_per_pixel = 1; } else { return wuffs_base__make_status(wuffs_base__error__unsupported_option);
diff --git a/std/gif/decode_gif.wuffs b/std/gif/decode_gif.wuffs index a486b23..9ca9d35 100644 --- a/std/gif/decode_gif.wuffs +++ b/std/gif/decode_gif.wuffs
@@ -881,7 +881,7 @@ status = this.swizzler.prepare!( dst_pixfmt: args.dst.pixel_format(), dst_palette: dst_palette, - src_pixfmt: 0x47040008, + src_pixfmt: this.util.make_pixel_format(repr: 0x47040008), src_palette: this.palettes[which_palette][..]) if not status.is_ok() { return status @@ -1025,8 +1025,9 @@ var width_in_bytes : base.u64 var n : base.u64 var src_ri : base.u64 + var pixfmt : base.pixel_format var bytes_per_pixel : base.u32[..= 64] - var pixfmt_channels : base.u32 + var bits_per_pixel : base.u32 var tab : table base.u8 var i : base.u64 var j : base.u64 @@ -1037,12 +1038,16 @@ // TODO: a Wuffs (not just C) name for the WUFFS_BASE__PIXEL_FORMAT__ETC // magic pixfmt constants. Also, support more formats. - pixfmt_channels = args.pb.pixel_format() & 0xFFFF - if (pixfmt_channels == 0x8888) { + // + // TODO: the pixfmt variable shouldn't be necessary. We should be able to + // chain the two calls: "args.pb.pixel_format().bits_per_pixel()". + pixfmt = args.pb.pixel_format() + bits_per_pixel = pixfmt.bits_per_pixel() + if (bits_per_pixel == 32) { bytes_per_pixel = 4 - } else if (pixfmt_channels == 0x0888) { + } else if (bits_per_pixel == 24) { bytes_per_pixel = 3 - } else if (pixfmt_channels == 0x0008) { + } else if (bits_per_pixel == 8) { bytes_per_pixel = 1 } else { return base."#unsupported option"
diff --git a/test/c/std/gif.c b/test/c/std/gif.c index 24733fc..d4cd2c4 100644 --- a/test/c/std/gif.c +++ b/test/c/std/gif.c
@@ -261,10 +261,10 @@ wuffs_base__image_config ic = ((wuffs_base__image_config){}); CHECK_STATUS("decode_image_config", wuffs_gif__decoder__decode_image_config(&dec, &ic, &src)); - if (wuffs_base__pixel_config__pixel_format(&ic.pixcfg) != + if (wuffs_base__pixel_config__pixel_format(&ic.pixcfg).repr != WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY) { RETURN_FAIL("pixel_format: got 0x%08" PRIX32 ", want 0x%08" PRIX32, - wuffs_base__pixel_config__pixel_format(&ic.pixcfg), + wuffs_base__pixel_config__pixel_format(&ic.pixcfg).repr, WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY); } @@ -370,7 +370,7 @@ }), }); CHECK_STRING(read_file(&pal_want, palette_filename)); - if (dst_pixfmt == WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY) { + if (dst_pixfmt.repr == WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY) { wuffs_base__io_buffer pal_got = ((wuffs_base__io_buffer){ .data = wuffs_base__pixel_buffer__palette(&pb), }); @@ -382,7 +382,7 @@ .data = global_want_slice, }); CHECK_STRING(read_file(&ind_want, indexes_filename)); - if (dst_pixfmt == WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY) { + if (dst_pixfmt.repr == WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY) { CHECK_STRING(check_io_buffers_equal("indexes ", &got, &ind_want)); } else { wuffs_base__io_buffer expanded_want = ((wuffs_base__io_buffer){ @@ -392,7 +392,7 @@ RETURN_FAIL("indexes are too long to expand into the work buffer"); } - if (dst_pixfmt == WUFFS_BASE__PIXEL_FORMAT__BGR) { + if (dst_pixfmt.repr == 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]; @@ -401,7 +401,7 @@ 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) { + } else if (dst_pixfmt.repr == 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]; @@ -411,7 +411,7 @@ 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) { + } else if (dst_pixfmt.repr == 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]; @@ -420,7 +420,7 @@ 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) { + } else if (dst_pixfmt.repr == 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]; @@ -1093,34 +1093,34 @@ 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", UINT64_MAX, - WUFFS_BASE__PIXEL_FORMAT__BGR); + return do_test_wuffs_gif_decode( + "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", + "test/data/bricks-dither.indexes", UINT64_MAX, + wuffs_base__make_pixel_format(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", - "test/data/bricks-dither.indexes", UINT64_MAX, - WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL); + return do_test_wuffs_gif_decode( + "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", + "test/data/bricks-dither.indexes", UINT64_MAX, + wuffs_base__make_pixel_format(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", UINT64_MAX, - WUFFS_BASE__PIXEL_FORMAT__RGB); + return do_test_wuffs_gif_decode( + "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", + "test/data/bricks-dither.indexes", UINT64_MAX, + wuffs_base__make_pixel_format(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", UINT64_MAX, - WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL); + return do_test_wuffs_gif_decode( + "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", + "test/data/bricks-dither.indexes", UINT64_MAX, + wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL)); } const char* test_wuffs_gif_decode_input_is_a_gif_just_one_read() { @@ -1128,7 +1128,8 @@ return do_test_wuffs_gif_decode( "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", "test/data/bricks-dither.indexes", UINT64_MAX, - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY)); } const char* test_wuffs_gif_decode_input_is_a_gif_many_big_reads() { @@ -1136,7 +1137,8 @@ return do_test_wuffs_gif_decode( "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", "test/data/bricks-dither.indexes", 4096, - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY)); } const char* test_wuffs_gif_decode_input_is_a_gif_many_medium_reads() { @@ -1144,7 +1146,8 @@ return do_test_wuffs_gif_decode( "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", "test/data/bricks-dither.indexes", 787, - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY)); // The magic 787 tickles being in the middle of a decode_extension skip // call. // @@ -1156,7 +1159,8 @@ return do_test_wuffs_gif_decode( "test/data/bricks-dither.gif", "test/data/bricks-dither.palette", "test/data/bricks-dither.indexes", 13, - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY)); } const char* test_wuffs_gif_decode_input_is_a_png() { @@ -1207,10 +1211,10 @@ RETURN_FAIL("height: got %" PRIu32 ", want 28", wuffs_base__pixel_config__height(&ic.pixcfg)); } - if (wuffs_base__pixel_config__pixel_format(&ic.pixcfg) != + if (wuffs_base__pixel_config__pixel_format(&ic.pixcfg).repr != WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY) { RETURN_FAIL("pixel_format: got 0x%08" PRIX32 ", want 0x%08" PRIX32, - wuffs_base__pixel_config__pixel_format(&ic.pixcfg), + wuffs_base__pixel_config__pixel_format(&ic.pixcfg).repr, WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY); } const int num_pixel_indexes = 36 * 28 * 1; @@ -1919,15 +1923,21 @@ wuffs_base__io_buffer got = ((wuffs_base__io_buffer){ .data = global_got_slice, }); - CHECK_STRING(wuffs_gif_decode( - &got, 0, WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, &src)); + CHECK_STRING( + wuffs_gif_decode(&got, 0, + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + &src)); src.meta.ri = 0; wuffs_base__io_buffer want = ((wuffs_base__io_buffer){ .data = global_want_slice, }); - CHECK_STRING(mimic_gif_decode( - &want, 0, WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, &src)); + CHECK_STRING( + mimic_gif_decode(&want, 0, + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + &src)); CHECK_STRING(check_io_buffers_equal("", &got, &want)); @@ -2042,7 +2052,9 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, "test/data/pjw-thumbnail.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 2000); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 2000); } const char* bench_wuffs_gif_decode_1k_color_full_init() { @@ -2050,7 +2062,9 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__DEFAULT_OPTIONS, "test/data/hippopotamus.regular.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1000); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1000); } const char* bench_wuffs_gif_decode_1k_color_part_init() { @@ -2058,21 +2072,28 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, "test/data/hippopotamus.regular.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1000); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1000); } const char* bench_wuffs_gif_decode_10k_bgra() { CHECK_FOCUS(__func__); return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, - "test/data/hat.gif", WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL, 100); + "test/data/hat.gif", + wuffs_base__make_pixel_format(WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL), + 100); } const char* bench_wuffs_gif_decode_10k_indexed() { CHECK_FOCUS(__func__); return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, - "test/data/hat.gif", WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 100); + "test/data/hat.gif", + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 100); } const char* bench_wuffs_gif_decode_20k() { @@ -2080,7 +2101,9 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, "test/data/bricks-gray.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 50); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 50); } const char* bench_wuffs_gif_decode_100k_artificial() { @@ -2088,7 +2111,9 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, "test/data/hibiscus.primitive.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 15); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 15); } const char* bench_wuffs_gif_decode_100k_realistic() { @@ -2096,15 +2121,19 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, "test/data/hibiscus.regular.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 10); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 10); } const char* bench_wuffs_gif_decode_1000k_full_init() { CHECK_FOCUS(__func__); - return do_bench_gif_decode(wuffs_gif_decode, - WUFFS_INITIALIZE__DEFAULT_OPTIONS, - "test/data/harvesters.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1); + return do_bench_gif_decode( + wuffs_gif_decode, WUFFS_INITIALIZE__DEFAULT_OPTIONS, + "test/data/harvesters.gif", + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1); } const char* bench_wuffs_gif_decode_1000k_part_init() { @@ -2112,7 +2141,9 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, "test/data/harvesters.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1); } const char* bench_wuffs_gif_decode_anim_screencap() { @@ -2120,7 +2151,9 @@ return do_bench_gif_decode( wuffs_gif_decode, WUFFS_INITIALIZE__LEAVE_INTERNAL_BUFFERS_UNINITIALIZED, "test/data/gifplayer-muybridge.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1); } // ---------------- Mimic Benches @@ -2129,57 +2162,74 @@ const char* bench_mimic_gif_decode_1k_bw() { CHECK_FOCUS(__func__); - return do_bench_gif_decode(mimic_gif_decode, 0, "test/data/pjw-thumbnail.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, - 2000); + return do_bench_gif_decode( + mimic_gif_decode, 0, "test/data/pjw-thumbnail.gif", + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 2000); } const char* bench_mimic_gif_decode_1k_color() { CHECK_FOCUS(__func__); return do_bench_gif_decode( mimic_gif_decode, 0, "test/data/hippopotamus.regular.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1000); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1000); } const char* bench_mimic_gif_decode_10k_indexed() { CHECK_FOCUS(__func__); - return do_bench_gif_decode(mimic_gif_decode, 0, "test/data/hat.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, - 100); + return do_bench_gif_decode( + mimic_gif_decode, 0, "test/data/hat.gif", + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 100); } const char* bench_mimic_gif_decode_20k() { CHECK_FOCUS(__func__); - return do_bench_gif_decode(mimic_gif_decode, 0, "test/data/bricks-gray.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, - 50); + return do_bench_gif_decode( + mimic_gif_decode, 0, "test/data/bricks-gray.gif", + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 50); } const char* bench_mimic_gif_decode_100k_artificial() { CHECK_FOCUS(__func__); return do_bench_gif_decode( mimic_gif_decode, 0, "test/data/hibiscus.primitive.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 15); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 15); } const char* bench_mimic_gif_decode_100k_realistic() { CHECK_FOCUS(__func__); return do_bench_gif_decode( mimic_gif_decode, 0, "test/data/hibiscus.regular.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 10); + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 10); } const char* bench_mimic_gif_decode_1000k() { CHECK_FOCUS(__func__); - return do_bench_gif_decode(mimic_gif_decode, 0, "test/data/harvesters.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1); + return do_bench_gif_decode( + mimic_gif_decode, 0, "test/data/harvesters.gif", + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1); } const char* bench_mimic_gif_decode_anim_screencap() { CHECK_FOCUS(__func__); - return do_bench_gif_decode(mimic_gif_decode, 0, - "test/data/gifplayer-muybridge.gif", - WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY, 1); + return do_bench_gif_decode( + mimic_gif_decode, 0, "test/data/gifplayer-muybridge.gif", + wuffs_base__make_pixel_format( + WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY), + 1); } #endif // WUFFS_MIMIC