Move more base funcs to the pixconv sub-module
$ ls -l gen/lib/c/*/{lib*,*base*} | awk '{print $5 " " $9}'
Before:
167976 gen/lib/c/clang-5.0-dynamic/libwuffs.so
13944 gen/lib/c/clang-5.0-dynamic/wuffs-base-core.lo
11640 gen/lib/c/clang-5.0-dynamic/wuffs-base-pixconv.lo
207150 gen/lib/c/clang-5.0-static/libwuffs.a
14240 gen/lib/c/clang-5.0-static/wuffs-base-core.o
12096 gen/lib/c/clang-5.0-static/wuffs-base-pixconv.o
188088 gen/lib/c/gcc-dynamic/libwuffs.so
13296 gen/lib/c/gcc-dynamic/wuffs-base-core.lo
27232 gen/lib/c/gcc-dynamic/wuffs-base-pixconv.lo
234766 gen/lib/c/gcc-static/libwuffs.a
13432 gen/lib/c/gcc-static/wuffs-base-core.o
27216 gen/lib/c/gcc-static/wuffs-base-pixconv.o
After:
167976 gen/lib/c/clang-5.0-dynamic/libwuffs.so
11376 gen/lib/c/clang-5.0-dynamic/wuffs-base-core.lo
14328 gen/lib/c/clang-5.0-dynamic/wuffs-base-pixconv.lo
207270 gen/lib/c/clang-5.0-static/libwuffs.a
11696 gen/lib/c/clang-5.0-static/wuffs-base-core.o
14760 gen/lib/c/clang-5.0-static/wuffs-base-pixconv.o
188088 gen/lib/c/gcc-dynamic/libwuffs.so
10680 gen/lib/c/gcc-dynamic/wuffs-base-core.lo
29968 gen/lib/c/gcc-dynamic/wuffs-base-pixconv.lo
234886 gen/lib/c/gcc-static/libwuffs.a
10856 gen/lib/c/gcc-static/wuffs-base-core.o
29912 gen/lib/c/gcc-static/wuffs-base-pixconv.o
diff --git a/internal/cgen/base/all-impl.c b/internal/cgen/base/all-impl.c
index 2bb67b1..f65f3ad 100644
--- a/internal/cgen/base/all-impl.c
+++ b/internal/cgen/base/all-impl.c
@@ -108,12 +108,15 @@
0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
};
+const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,
+};
+
// !! INSERT wuffs_base__status strings.
// !! INSERT vtable names.
-// !! INSERT base/image-impl.c.
-
// !! INSERT base/strconv-impl.c.
#endif // !defined(WUFFS_CONFIG__MODULES) ||
diff --git a/internal/cgen/base/image-impl.c b/internal/cgen/base/image-impl.c
deleted file mode 100644
index 59b53e7..0000000
--- a/internal/cgen/base/image-impl.c
+++ /dev/null
@@ -1,258 +0,0 @@
-// After editing this file, run "go generate" in the parent directory.
-
-// Copyright 2017 The Wuffs Authors.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// ---------------- Images
-
-const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,
-};
-
-// --------
-
-static inline uint32_t //
-wuffs_base__swap_u32_argb_abgr(uint32_t u) {
- uint32_t o = u & 0xFF00FF00;
- uint32_t r = u & 0x00FF0000;
- uint32_t b = u & 0x000000FF;
- return o | (r >> 16) | (b << 16);
-}
-
-// --------
-
-WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
-wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
- uint32_t x,
- uint32_t y) {
- if (!pb || (x >= pb->pixcfg.private_impl.width) ||
- (y >= pb->pixcfg.private_impl.height)) {
- return 0;
- }
-
- if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
- // TODO: support planar formats.
- return 0;
- }
-
- size_t stride = pb->private_impl.planes[0].stride;
- uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
-
- switch (pb->pixcfg.private_impl.pixfmt.repr) {
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
- return wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
-
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
- uint8_t* palette = pb->private_impl.planes[3].ptr;
- return wuffs_base__load_u32le__no_bounds_check(palette +
- (4 * ((size_t)row[x])));
- }
-
- // Common formats above. Rarer formats below.
-
- case WUFFS_BASE__PIXEL_FORMAT__Y:
- return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));
-
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {
- uint8_t* palette = pb->private_impl.planes[3].ptr;
- return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
- wuffs_base__load_u32le__no_bounds_check(palette +
- (4 * ((size_t)row[x]))));
- }
-
- case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
- return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
- wuffs_base__load_u16le__no_bounds_check(row + (2 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__BGR:
- return 0xFF000000 |
- wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x)));
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
- return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__BGRX:
- return 0xFF000000 |
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
-
- case WUFFS_BASE__PIXEL_FORMAT__RGB:
- return wuffs_base__swap_u32_argb_abgr(
- 0xFF000000 |
- wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
- return wuffs_base__swap_u32_argb_abgr(
- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
- wuffs_base__load_u32le__no_bounds_check(row +
- (4 * ((size_t)x)))));
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
- return wuffs_base__swap_u32_argb_abgr(
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__RGBX:
- return wuffs_base__swap_u32_argb_abgr(
- 0xFF000000 |
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
-
- default:
- // TODO: support more formats.
- break;
- }
-
- return 0;
-}
-
-WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
-wuffs_base__pixel_buffer__set_color_u32_at(
- wuffs_base__pixel_buffer* pb,
- uint32_t x,
- uint32_t y,
- wuffs_base__color_u32_argb_premul color) {
- if (!pb) {
- return wuffs_base__make_status(wuffs_base__error__bad_receiver);
- }
- if ((x >= pb->pixcfg.private_impl.width) ||
- (y >= pb->pixcfg.private_impl.height)) {
- return wuffs_base__make_status(wuffs_base__error__bad_argument);
- }
-
- if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
- // TODO: support planar formats.
- return wuffs_base__make_status(wuffs_base__error__unsupported_option);
- }
-
- size_t stride = pb->private_impl.planes[0].stride;
- uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
-
- switch (pb->pixcfg.private_impl.pixfmt.repr) {
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__BGRX:
- wuffs_base__store_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);
- break;
-
- // Common formats above. Rarer formats below.
-
- case WUFFS_BASE__PIXEL_FORMAT__Y:
- wuffs_base__store_u8__no_bounds_check(
- row + ((size_t)x),
- wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));
- break;
-
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
- wuffs_base__store_u8__no_bounds_check(
- row + ((size_t)x), wuffs_base__pixel_palette__closest_element(
- wuffs_base__pixel_buffer__palette(pb),
- pb->pixcfg.private_impl.pixfmt, color));
- break;
-
- case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
- wuffs_base__store_u16le__no_bounds_check(
- row + (2 * ((size_t)x)),
- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
- break;
- case WUFFS_BASE__PIXEL_FORMAT__BGR:
- wuffs_base__store_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);
- break;
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
- wuffs_base__store_u32le__no_bounds_check(
- row + (4 * ((size_t)x)),
- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
- color));
- break;
-
- case WUFFS_BASE__PIXEL_FORMAT__RGB:
- wuffs_base__store_u24le__no_bounds_check(
- row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
- break;
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
- wuffs_base__store_u32le__no_bounds_check(
- row + (4 * ((size_t)x)),
- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
- wuffs_base__swap_u32_argb_abgr(color)));
- break;
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__RGBX:
- wuffs_base__store_u32le__no_bounds_check(
- row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
- break;
-
- default:
- // TODO: support more formats.
- return wuffs_base__make_status(wuffs_base__error__unsupported_option);
- }
-
- return wuffs_base__make_status(NULL);
-}
-
-// --------
-
-WUFFS_BASE__MAYBE_STATIC uint8_t //
-wuffs_base__pixel_palette__closest_element(
- wuffs_base__slice_u8 palette_slice,
- wuffs_base__pixel_format palette_format,
- wuffs_base__color_u32_argb_premul c) {
- size_t n = palette_slice.len / 4;
- if (n > 256) {
- n = 256;
- }
- size_t best_index = 0;
- uint64_t best_score = 0xFFFFFFFFFFFFFFFF;
-
- // Work in 16-bit color.
- uint32_t ca = 0x101 * (0xFF & (c >> 24));
- uint32_t cr = 0x101 * (0xFF & (c >> 16));
- uint32_t cg = 0x101 * (0xFF & (c >> 8));
- uint32_t cb = 0x101 * (0xFF & (c >> 0));
-
- switch (palette_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: {
- bool nonpremul = palette_format.repr ==
- WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;
-
- size_t i;
- for (i = 0; i < n; i++) {
- // Work in 16-bit color.
- uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0]));
- uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));
- uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));
- uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));
-
- // Convert to premultiplied alpha.
- if (nonpremul && (pa != 0xFFFF)) {
- pb = (pb * pa) / 0xFFFF;
- pg = (pg * pa) / 0xFFFF;
- pr = (pr * pa) / 0xFFFF;
- }
-
- // These deltas are conceptually int32_t (signed) but after squaring,
- // it's equivalent to work in uint32_t (unsigned).
- pb -= cb;
- pg -= cg;
- pr -= cr;
- pa -= ca;
- uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +
- ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));
- if (best_score > score) {
- best_score = score;
- best_index = i;
- }
- }
- break;
- }
- }
-
- return (uint8_t)best_index;
-}
diff --git a/internal/cgen/base/pixconv-submodule.c b/internal/cgen/base/pixconv-submodule.c
index 630fdfd..e041e5c 100644
--- a/internal/cgen/base/pixconv-submodule.c
+++ b/internal/cgen/base/pixconv-submodule.c
@@ -17,6 +17,242 @@
// ---------------- Pixel Swizzler
static inline uint32_t //
+wuffs_base__swap_u32_argb_abgr(uint32_t u) {
+ uint32_t o = u & 0xFF00FF00;
+ uint32_t r = u & 0x00FF0000;
+ uint32_t b = u & 0x000000FF;
+ return o | (r >> 16) | (b << 16);
+}
+
+// --------
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
+wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
+ uint32_t x,
+ uint32_t y) {
+ if (!pb || (x >= pb->pixcfg.private_impl.width) ||
+ (y >= pb->pixcfg.private_impl.height)) {
+ return 0;
+ }
+
+ if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
+ // TODO: support planar formats.
+ return 0;
+ }
+
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
+
+ switch (pb->pixcfg.private_impl.pixfmt.repr) {
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
+ return wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
+
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
+ uint8_t* palette = pb->private_impl.planes[3].ptr;
+ return wuffs_base__load_u32le__no_bounds_check(palette +
+ (4 * ((size_t)row[x])));
+ }
+
+ // Common formats above. Rarer formats below.
+
+ case WUFFS_BASE__PIXEL_FORMAT__Y:
+ return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));
+
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {
+ uint8_t* palette = pb->private_impl.planes[3].ptr;
+ return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
+ wuffs_base__load_u32le__no_bounds_check(palette +
+ (4 * ((size_t)row[x]))));
+ }
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
+ return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
+ wuffs_base__load_u16le__no_bounds_check(row + (2 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ return 0xFF000000 |
+ wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x)));
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
+ return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__BGRX:
+ return 0xFF000000 |
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
+
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ return wuffs_base__swap_u32_argb_abgr(
+ 0xFF000000 |
+ wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
+ return wuffs_base__swap_u32_argb_abgr(
+ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
+ wuffs_base__load_u32le__no_bounds_check(row +
+ (4 * ((size_t)x)))));
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
+ return wuffs_base__swap_u32_argb_abgr(
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__RGBX:
+ return wuffs_base__swap_u32_argb_abgr(
+ 0xFF000000 |
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
+
+ default:
+ // TODO: support more formats.
+ break;
+ }
+
+ return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__pixel_buffer__set_color_u32_at(
+ wuffs_base__pixel_buffer* pb,
+ uint32_t x,
+ uint32_t y,
+ wuffs_base__color_u32_argb_premul color) {
+ if (!pb) {
+ return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+ }
+ if ((x >= pb->pixcfg.private_impl.width) ||
+ (y >= pb->pixcfg.private_impl.height)) {
+ return wuffs_base__make_status(wuffs_base__error__bad_argument);
+ }
+
+ if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
+ // TODO: support planar formats.
+ return wuffs_base__make_status(wuffs_base__error__unsupported_option);
+ }
+
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
+
+ switch (pb->pixcfg.private_impl.pixfmt.repr) {
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__BGRX:
+ wuffs_base__store_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);
+ break;
+
+ // Common formats above. Rarer formats below.
+
+ case WUFFS_BASE__PIXEL_FORMAT__Y:
+ wuffs_base__store_u8__no_bounds_check(
+ row + ((size_t)x),
+ wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));
+ break;
+
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
+ wuffs_base__store_u8__no_bounds_check(
+ row + ((size_t)x), wuffs_base__pixel_palette__closest_element(
+ wuffs_base__pixel_buffer__palette(pb),
+ pb->pixcfg.private_impl.pixfmt, color));
+ break;
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
+ wuffs_base__store_u16le__no_bounds_check(
+ row + (2 * ((size_t)x)),
+ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ wuffs_base__store_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
+ wuffs_base__store_u32le__no_bounds_check(
+ row + (4 * ((size_t)x)),
+ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
+ color));
+ break;
+
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ wuffs_base__store_u24le__no_bounds_check(
+ row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
+ wuffs_base__store_u32le__no_bounds_check(
+ row + (4 * ((size_t)x)),
+ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
+ wuffs_base__swap_u32_argb_abgr(color)));
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__RGBX:
+ wuffs_base__store_u32le__no_bounds_check(
+ row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
+ break;
+
+ default:
+ // TODO: support more formats.
+ return wuffs_base__make_status(wuffs_base__error__unsupported_option);
+ }
+
+ return wuffs_base__make_status(NULL);
+}
+
+// --------
+
+WUFFS_BASE__MAYBE_STATIC uint8_t //
+wuffs_base__pixel_palette__closest_element(
+ wuffs_base__slice_u8 palette_slice,
+ wuffs_base__pixel_format palette_format,
+ wuffs_base__color_u32_argb_premul c) {
+ size_t n = palette_slice.len / 4;
+ if (n > 256) {
+ n = 256;
+ }
+ size_t best_index = 0;
+ uint64_t best_score = 0xFFFFFFFFFFFFFFFF;
+
+ // Work in 16-bit color.
+ uint32_t ca = 0x101 * (0xFF & (c >> 24));
+ uint32_t cr = 0x101 * (0xFF & (c >> 16));
+ uint32_t cg = 0x101 * (0xFF & (c >> 8));
+ uint32_t cb = 0x101 * (0xFF & (c >> 0));
+
+ switch (palette_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: {
+ bool nonpremul = palette_format.repr ==
+ WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;
+
+ size_t i;
+ for (i = 0; i < n; i++) {
+ // Work in 16-bit color.
+ uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0]));
+ uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));
+ uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));
+ uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));
+
+ // Convert to premultiplied alpha.
+ if (nonpremul && (pa != 0xFFFF)) {
+ pb = (pb * pa) / 0xFFFF;
+ pg = (pg * pa) / 0xFFFF;
+ pr = (pr * pa) / 0xFFFF;
+ }
+
+ // These deltas are conceptually int32_t (signed) but after squaring,
+ // it's equivalent to work in uint32_t (unsigned).
+ pb -= cb;
+ pg -= cg;
+ pr -= cr;
+ pa -= ca;
+ uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +
+ ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));
+ if (best_score > score) {
+ best_score = score;
+ best_index = i;
+ }
+ }
+ break;
+ }
+ }
+
+ return (uint8_t)best_index;
+}
+
+// --------
+
+static inline uint32_t //
wuffs_base__composite_nonpremul_nonpremul_u32_axxx(uint32_t dst_nonpremul,
uint32_t src_nonpremul) {
// Convert from 8-bit color to 16-bit color.
diff --git a/internal/cgen/cgen.go b/internal/cgen/cgen.go
index 313959f..bf9fb32 100644
--- a/internal/cgen/cgen.go
+++ b/internal/cgen/cgen.go
@@ -131,7 +131,6 @@
"// !! INSERT base/all-public.h.\n": insertBaseAllPublicH,
"// !! INSERT base/copyright\n": insertBaseCopyright,
"// !! INSERT base/f64conv-submodule.c.\n": insertBaseF64ConvSubmoduleC,
- "// !! INSERT base/image-impl.c.\n": insertBaseImageImplC,
"// !! INSERT base/pixconv-submodule.c.\n": insertBasePixConvSubmoduleC,
"// !! INSERT base/strconv-impl.c.\n": insertBaseStrConvImplC,
"// !! INSERT vtable names.\n": func(b *buffer) error {
@@ -352,12 +351,6 @@
return nil
}
-func insertBaseImageImplC(buf *buffer) error {
- buf.writes(baseImageImplC)
- buf.writeb('\n')
- return nil
-}
-
func insertBasePixConvSubmoduleC(buf *buffer) error {
buf.writes(basePixConvSubmoduleC)
buf.writeb('\n')
diff --git a/internal/cgen/data.go b/internal/cgen/data.go
index cf32c5c..d40a125 100644
--- a/internal/cgen/data.go
+++ b/internal/cgen/data.go
@@ -23,25 +23,8 @@
"" +
"// ----------------\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \\\n defined(WUFFS_CONFIG__MODULE__BASE__CORE)\n\nconst uint8_t wuffs_base__low_bits_mask__u8[9] = {\n 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF,\n};\n\nconst uint16_t wuffs_base__low_bits_mask__u16[17] = {\n 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF,\n 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF,\n};\n\nconst uint32_t wuffs_base__low_bits_mask__u32[33] = {\n 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, 0x0000001F,\n 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, 0x000003FF, 0x000007FF,\n 0x00000FFF, 0x00001FFF, 0x00003FFF, 0x00007FFF, 0x0000FFFF, 0x0001FFFF,\n 0x0003FFFF, 0x0007FFFF, 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF,\n 0x00FFFFFF, 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF,\n 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF,\n};\n\nconst uint64_t wuffs_base__low_bits_mask__u64[65] = {\n 0x0000000000000000, 0x000" +
"0000000000001, 0x0000000000000003,\n 0x0000000000000007, 0x000000000000000F, 0x000000000000001F,\n 0x000000000000003F, 0x000000000000007F, 0x00000000000000FF,\n 0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF,\n 0x0000000000000FFF, 0x0000000000001FFF, 0x0000000000003FFF,\n 0x0000000000007FFF, 0x000000000000FFFF, 0x000000000001FFFF,\n 0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF,\n 0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF,\n 0x0000000000FFFFFF, 0x0000000001FFFFFF, 0x0000000003FFFFFF,\n 0x0000000007FFFFFF, 0x000000000FFFFFFF, 0x000000001FFFFFFF,\n 0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF,\n 0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF,\n 0x0000000FFFFFFFFF, 0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF,\n 0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF, 0x000001FFFFFFFFFF,\n 0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF,\n 0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF,\n 0x0000FFFFFFFFFFFF, 0x000" +
- "1FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF,\n 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x001FFFFFFFFFFFFF,\n 0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF,\n 0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF,\n 0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF,\n 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,\n};\n\n// !! INSERT wuffs_base__status strings.\n\n// !! INSERT vtable names.\n\n// !! INSERT base/image-impl.c.\n\n// !! INSERT base/strconv-impl.c.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__CORE)\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \\\n defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)\n\n// !! INSERT InterfaceDefinitions.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BA" +
- "SE) || \\\n defined(WUFFS_CONFIG__MODULE__BASE__F64CONV)\n\n// !! INSERT base/f64conv-submodule.c.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__F64CONV)\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \\\n defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)\n\n// !! INSERT base/pixconv-submodule.c.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // WUFFS_IMPLEMENTATION\n\n// !! WUFFS MONOLITHIC RELEASE DISCARDS EVERYTHING BELOW.\n\n#endif // WUFFS_INCLUDE_GUARD__BASE\n" +
- ""
-
-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\n" +
- "" +
- "// --------\n\nstatic inline uint32_t //\nwuffs_base__swap_u32_argb_abgr(uint32_t u) {\n uint32_t o = u & 0xFF00FF00;\n uint32_t r = u & 0x00FF0000;\n uint32_t b = u & 0x000000FF;\n return o | (r >> 16) | (b << 16);\n}\n\n" +
- "" +
- "// --------\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //\nwuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,\n uint32_t x,\n uint32_t y) {\n if (!pb || (x >= pb->pixcfg.private_impl.width) ||\n (y >= pb->pixcfg.private_impl.height)) {\n return 0;\n }\n\n if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {\n // TODO: support planar formats.\n return 0;\n }\n\n size_t stride = pb->private_impl.planes[0].stride;\n uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));\n\n switch (pb->pixcfg.private_impl.pixfmt.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:\n return wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));\n\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {\n uint8_t* palette = pb->private_impl.plane" +
- "s[3].ptr;\n return wuffs_base__load_u32le__no_bounds_check(palette +\n (4 * ((size_t)row[x])));\n }\n\n // Common formats above. Rarer formats below.\n\n case WUFFS_BASE__PIXEL_FORMAT__Y:\n return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));\n\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {\n uint8_t* palette = pb->private_impl.planes[3].ptr;\n return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(\n wuffs_base__load_u32le__no_bounds_check(palette +\n (4 * ((size_t)row[x]))));\n }\n\n case WUFFS_BASE__PIXEL_FORMAT__BGR_565:\n return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(\n wuffs_base__load_u16le__no_bounds_check(row + (2 * ((size_t)x))));\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n return 0xFF000000 |\n wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x)));\n case WUFFS_BASE__PIXEL_FORMAT_" +
- "_BGRA_NONPREMUL:\n return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));\n case WUFFS_BASE__PIXEL_FORMAT__BGRX:\n return 0xFF000000 |\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));\n\n case WUFFS_BASE__PIXEL_FORMAT__RGB:\n return wuffs_base__swap_u32_argb_abgr(\n 0xFF000000 |\n wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x))));\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n return wuffs_base__swap_u32_argb_abgr(\n wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(\n wuffs_base__load_u32le__no_bounds_check(row +\n (4 * ((size_t)x)))));\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:\n return wuffs_base__swap_u32_argb_abgr(\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)" +
- ")));\n case WUFFS_BASE__PIXEL_FORMAT__RGBX:\n return wuffs_base__swap_u32_argb_abgr(\n 0xFF000000 |\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));\n\n default:\n // TODO: support more formats.\n break;\n }\n\n return 0;\n}\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__status //\nwuffs_base__pixel_buffer__set_color_u32_at(\n wuffs_base__pixel_buffer* pb,\n uint32_t x,\n uint32_t y,\n wuffs_base__color_u32_argb_premul color) {\n if (!pb) {\n return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n }\n if ((x >= pb->pixcfg.private_impl.width) ||\n (y >= pb->pixcfg.private_impl.height)) {\n return wuffs_base__make_status(wuffs_base__error__bad_argument);\n }\n\n if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {\n // TODO: support planar formats.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n\n size_t stride = pb->private_impl.planes[0].stride;\n uint8_t* row = pb->private_impl.planes[0]" +
- ".ptr + (stride * ((size_t)y));\n\n switch (pb->pixcfg.private_impl.pixfmt.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRX:\n wuffs_base__store_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);\n break;\n\n // Common formats above. Rarer formats below.\n\n case WUFFS_BASE__PIXEL_FORMAT__Y:\n wuffs_base__store_u8__no_bounds_check(\n row + ((size_t)x),\n wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n wuffs_base__store_u8__no_bounds_check(\n row + ((size_t)x), wuffs_base__pixel_palette__closest_element(\n wuffs_base__pixel_buffer__palette(pb),\n pb->pixcfg.private_impl.pixfmt, color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__BGR_565:\n wuffs_base__store_u16le__no_bounds_check(\n row + (2 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as" +
- "__color_u16_rgb_565(color));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n wuffs_base__store_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n wuffs_base__store_u32le__no_bounds_check(\n row + (4 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__RGB:\n wuffs_base__store_u24le__no_bounds_check(\n row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n wuffs_base__store_u32le__no_bounds_check(\n row + (4 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n wuffs_base__swap_u32_argb_abgr(color)));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBX:\n wuffs_base__store_u32le__no_bounds_check(\n row" +
- " + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));\n break;\n\n default:\n // TODO: support more formats.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n\n return wuffs_base__make_status(NULL);\n}\n\n" +
- "" +
- "// --------\n\nWUFFS_BASE__MAYBE_STATIC uint8_t //\nwuffs_base__pixel_palette__closest_element(\n wuffs_base__slice_u8 palette_slice,\n wuffs_base__pixel_format palette_format,\n wuffs_base__color_u32_argb_premul c) {\n size_t n = palette_slice.len / 4;\n if (n > 256) {\n n = 256;\n }\n size_t best_index = 0;\n uint64_t best_score = 0xFFFFFFFFFFFFFFFF;\n\n // Work in 16-bit color.\n uint32_t ca = 0x101 * (0xFF & (c >> 24));\n uint32_t cr = 0x101 * (0xFF & (c >> 16));\n uint32_t cg = 0x101 * (0xFF & (c >> 8));\n uint32_t cb = 0x101 * (0xFF & (c >> 0));\n\n switch (palette_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 bool nonpremul = palette_format.repr ==\n WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;\n\n size_t i;\n for (i = 0; i < n; i++) {\n // Work in 16-bit color.\n uint32_t pb = 0x101 * ((uint32_t)(palette" +
- "_slice.ptr[(4 * i) + 0]));\n uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));\n uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));\n uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));\n\n // Convert to premultiplied alpha.\n if (nonpremul && (pa != 0xFFFF)) {\n pb = (pb * pa) / 0xFFFF;\n pg = (pg * pa) / 0xFFFF;\n pr = (pr * pa) / 0xFFFF;\n }\n\n // These deltas are conceptually int32_t (signed) but after squaring,\n // it's equivalent to work in uint32_t (unsigned).\n pb -= cb;\n pg -= cg;\n pr -= cr;\n pa -= ca;\n uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +\n ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));\n if (best_score > score) {\n best_score = score;\n best_index = i;\n }\n }\n break;\n }\n }\n\n return (uint8_t)best_index;\n}\n" +
+ "1FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF,\n 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF, 0x001FFFFFFFFFFFFF,\n 0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF,\n 0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF,\n 0x0FFFFFFFFFFFFFFF, 0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF,\n 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,\n};\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\n// !! INSERT wuffs_base__status strings.\n\n// !! INSERT vtable names.\n\n// !! INSERT base/strconv-impl.c.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__CORE)\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \\\n defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)\n\n// !! INSERT InterfaceDefinitions.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE_" +
+ "_BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__INTERFACES)\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \\\n defined(WUFFS_CONFIG__MODULE__BASE__F64CONV)\n\n// !! INSERT base/f64conv-submodule.c.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__F64CONV)\n\n#if !defined(WUFFS_CONFIG__MODULES) || defined(WUFFS_CONFIG__MODULE__BASE) || \\\n defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)\n\n// !! INSERT base/pixconv-submodule.c.\n\n#endif // !defined(WUFFS_CONFIG__MODULES) ||\n // defined(WUFFS_CONFIG__MODULE__BASE) ||\n // defined(WUFFS_CONFIG__MODULE__BASE__PIXCONV)\n\n#ifdef __cplusplus\n} // extern \"C\"\n#endif\n\n#endif // WUFFS_IMPLEMENTATION\n\n// !! WUFFS MONOLITHIC RELEASE DISCARDS EVERYTHING BELOW.\n\n#endif // WUFFS_INCLUDE_GUARD__BASE\n" +
""
const baseStrConvImplC = "" +
@@ -130,12 +113,24 @@
""
const basePixConvSubmoduleC = "" +
- "// ---------------- Pixel Swizzler\n\nstatic inline uint32_t //\nwuffs_base__composite_nonpremul_nonpremul_u32_axxx(uint32_t dst_nonpremul,\n uint32_t src_nonpremul) {\n // Convert from 8-bit color to 16-bit color.\n uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));\n uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8));\n uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));\n\n // Convert dst from nonpremul to premul.\n dr = (dr * da) / 0xFFFF;\n dg = (dg * da) / 0xFFFF;\n db = (db * da) / 0xFFFF;\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (nonpremul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr" +
- " = ((sr * sa) + (dr * ia)) / 0xFFFF;\n dg = ((sg * sa) + (dg * ia)) / 0xFFFF;\n db = ((sb * sa) + (db * ia)) / 0xFFFF;\n\n // Convert dst from premul to nonpremul.\n if (da != 0) {\n dr = (dr * 0xFFFF) / da;\n dg = (dg * 0xFFFF) / da;\n db = (db * 0xFFFF) / da;\n }\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}\n\nstatic inline uint32_t //\nwuffs_base__composite_nonpremul_premul_u32_axxx(uint32_t dst_nonpremul,\n uint32_t src_premul) {\n // Convert from 8-bit color to 16-bit color.\n uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));\n uint32_t dg = 0x101 * (0xFF " +
- "& (dst_nonpremul >> 8));\n uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));\n\n // Convert dst from nonpremul to premul.\n dr = (dr * da) / 0xFFFF;\n dg = (dg * da) / 0xFFFF;\n db = (db * da) / 0xFFFF;\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (premul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr = sr + ((dr * ia) / 0xFFFF);\n dg = sg + ((dg * ia) / 0xFFFF);\n db = sb + ((db * ia) / 0xFFFF);\n\n // Convert dst from premul to nonpremul.\n if (da != 0) {\n dr = (dr * 0xFFFF) / da;\n dg = (dg * 0xFFFF) / da;\n db = (db * 0xFFFF) / da;\n }\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}\n\nstatic inline uint32_t //\nwuffs_base__composite_premul_nonpremul_u32_axxx(uint32_t dst_premul,\n uint32_t src_nonpremul) {\n // Convert from 8-bit c" +
- "olor to 16-bit color.\n uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));\n uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));\n uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (nonpremul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr = ((sr * sa) + (dr * ia)) / 0xFFFF;\n dg = ((sg * sa) + (dg * ia)) / 0xFFFF;\n db = ((sb * sa) + (db * ia)) / 0xFFFF;\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}\n\nstatic inline uint32_t //\nwuffs_base__composite_premul_premul_u32_axxx(ui" +
- "nt32_t dst_premul,\n uint32_t src_premul) {\n // Convert from 8-bit color to 16-bit color.\n uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));\n uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));\n uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (premul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr = sr + ((dr * ia) / 0xFFFF);\n dg = sg + ((dg * ia) / 0xFFFF);\n db = sb + ((db * ia) / 0xFFFF);\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}" +
- "\n\n" +
+ "// ---------------- Pixel Swizzler\n\nstatic inline uint32_t //\nwuffs_base__swap_u32_argb_abgr(uint32_t u) {\n uint32_t o = u & 0xFF00FF00;\n uint32_t r = u & 0x00FF0000;\n uint32_t b = u & 0x000000FF;\n return o | (r >> 16) | (b << 16);\n}\n\n" +
+ "" +
+ "// --------\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //\nwuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,\n uint32_t x,\n uint32_t y) {\n if (!pb || (x >= pb->pixcfg.private_impl.width) ||\n (y >= pb->pixcfg.private_impl.height)) {\n return 0;\n }\n\n if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {\n // TODO: support planar formats.\n return 0;\n }\n\n size_t stride = pb->private_impl.planes[0].stride;\n uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));\n\n switch (pb->pixcfg.private_impl.pixfmt.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:\n return wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));\n\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {\n uint8_t* palette = pb->private_impl.plane" +
+ "s[3].ptr;\n return wuffs_base__load_u32le__no_bounds_check(palette +\n (4 * ((size_t)row[x])));\n }\n\n // Common formats above. Rarer formats below.\n\n case WUFFS_BASE__PIXEL_FORMAT__Y:\n return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));\n\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {\n uint8_t* palette = pb->private_impl.planes[3].ptr;\n return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(\n wuffs_base__load_u32le__no_bounds_check(palette +\n (4 * ((size_t)row[x]))));\n }\n\n case WUFFS_BASE__PIXEL_FORMAT__BGR_565:\n return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(\n wuffs_base__load_u16le__no_bounds_check(row + (2 * ((size_t)x))));\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n return 0xFF000000 |\n wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x)));\n case WUFFS_BASE__PIXEL_FORMAT_" +
+ "_BGRA_NONPREMUL:\n return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));\n case WUFFS_BASE__PIXEL_FORMAT__BGRX:\n return 0xFF000000 |\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));\n\n case WUFFS_BASE__PIXEL_FORMAT__RGB:\n return wuffs_base__swap_u32_argb_abgr(\n 0xFF000000 |\n wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x))));\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n return wuffs_base__swap_u32_argb_abgr(\n wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(\n wuffs_base__load_u32le__no_bounds_check(row +\n (4 * ((size_t)x)))));\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:\n return wuffs_base__swap_u32_argb_abgr(\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)" +
+ ")));\n case WUFFS_BASE__PIXEL_FORMAT__RGBX:\n return wuffs_base__swap_u32_argb_abgr(\n 0xFF000000 |\n wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));\n\n default:\n // TODO: support more formats.\n break;\n }\n\n return 0;\n}\n\nWUFFS_BASE__MAYBE_STATIC wuffs_base__status //\nwuffs_base__pixel_buffer__set_color_u32_at(\n wuffs_base__pixel_buffer* pb,\n uint32_t x,\n uint32_t y,\n wuffs_base__color_u32_argb_premul color) {\n if (!pb) {\n return wuffs_base__make_status(wuffs_base__error__bad_receiver);\n }\n if ((x >= pb->pixcfg.private_impl.width) ||\n (y >= pb->pixcfg.private_impl.height)) {\n return wuffs_base__make_status(wuffs_base__error__bad_argument);\n }\n\n if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {\n // TODO: support planar formats.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n\n size_t stride = pb->private_impl.planes[0].stride;\n uint8_t* row = pb->private_impl.planes[0]" +
+ ".ptr + (stride * ((size_t)y));\n\n switch (pb->pixcfg.private_impl.pixfmt.repr) {\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__BGRX:\n wuffs_base__store_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);\n break;\n\n // Common formats above. Rarer formats below.\n\n case WUFFS_BASE__PIXEL_FORMAT__Y:\n wuffs_base__store_u8__no_bounds_check(\n row + ((size_t)x),\n wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:\n wuffs_base__store_u8__no_bounds_check(\n row + ((size_t)x), wuffs_base__pixel_palette__closest_element(\n wuffs_base__pixel_buffer__palette(pb),\n pb->pixcfg.private_impl.pixfmt, color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__BGR_565:\n wuffs_base__store_u16le__no_bounds_check(\n row + (2 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as" +
+ "__color_u16_rgb_565(color));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGR:\n wuffs_base__store_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);\n break;\n case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:\n wuffs_base__store_u32le__no_bounds_check(\n row + (4 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n color));\n break;\n\n case WUFFS_BASE__PIXEL_FORMAT__RGB:\n wuffs_base__store_u24le__no_bounds_check(\n row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:\n wuffs_base__store_u32le__no_bounds_check(\n row + (4 * ((size_t)x)),\n wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(\n wuffs_base__swap_u32_argb_abgr(color)));\n break;\n case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:\n case WUFFS_BASE__PIXEL_FORMAT__RGBX:\n wuffs_base__store_u32le__no_bounds_check(\n row" +
+ " + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));\n break;\n\n default:\n // TODO: support more formats.\n return wuffs_base__make_status(wuffs_base__error__unsupported_option);\n }\n\n return wuffs_base__make_status(NULL);\n}\n\n" +
+ "" +
+ "// --------\n\nWUFFS_BASE__MAYBE_STATIC uint8_t //\nwuffs_base__pixel_palette__closest_element(\n wuffs_base__slice_u8 palette_slice,\n wuffs_base__pixel_format palette_format,\n wuffs_base__color_u32_argb_premul c) {\n size_t n = palette_slice.len / 4;\n if (n > 256) {\n n = 256;\n }\n size_t best_index = 0;\n uint64_t best_score = 0xFFFFFFFFFFFFFFFF;\n\n // Work in 16-bit color.\n uint32_t ca = 0x101 * (0xFF & (c >> 24));\n uint32_t cr = 0x101 * (0xFF & (c >> 16));\n uint32_t cg = 0x101 * (0xFF & (c >> 8));\n uint32_t cb = 0x101 * (0xFF & (c >> 0));\n\n switch (palette_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 bool nonpremul = palette_format.repr ==\n WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;\n\n size_t i;\n for (i = 0; i < n; i++) {\n // Work in 16-bit color.\n uint32_t pb = 0x101 * ((uint32_t)(palette" +
+ "_slice.ptr[(4 * i) + 0]));\n uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));\n uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));\n uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));\n\n // Convert to premultiplied alpha.\n if (nonpremul && (pa != 0xFFFF)) {\n pb = (pb * pa) / 0xFFFF;\n pg = (pg * pa) / 0xFFFF;\n pr = (pr * pa) / 0xFFFF;\n }\n\n // These deltas are conceptually int32_t (signed) but after squaring,\n // it's equivalent to work in uint32_t (unsigned).\n pb -= cb;\n pg -= cg;\n pr -= cr;\n pa -= ca;\n uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +\n ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));\n if (best_score > score) {\n best_score = score;\n best_index = i;\n }\n }\n break;\n }\n }\n\n return (uint8_t)best_index;\n}\n\n" +
+ "" +
+ "// --------\n\nstatic inline uint32_t //\nwuffs_base__composite_nonpremul_nonpremul_u32_axxx(uint32_t dst_nonpremul,\n uint32_t src_nonpremul) {\n // Convert from 8-bit color to 16-bit color.\n uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));\n uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8));\n uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));\n\n // Convert dst from nonpremul to premul.\n dr = (dr * da) / 0xFFFF;\n dg = (dg * da) / 0xFFFF;\n db = (db * da) / 0xFFFF;\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (nonpremul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr = ((sr * sa) + (dr * i" +
+ "a)) / 0xFFFF;\n dg = ((sg * sa) + (dg * ia)) / 0xFFFF;\n db = ((sb * sa) + (db * ia)) / 0xFFFF;\n\n // Convert dst from premul to nonpremul.\n if (da != 0) {\n dr = (dr * 0xFFFF) / da;\n dg = (dg * 0xFFFF) / da;\n db = (db * 0xFFFF) / da;\n }\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}\n\nstatic inline uint32_t //\nwuffs_base__composite_nonpremul_premul_u32_axxx(uint32_t dst_nonpremul,\n uint32_t src_premul) {\n // Convert from 8-bit color to 16-bit color.\n uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_nonpremul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_nonpremul >> 16));\n uint32_t dg = 0x101 * (0xFF & (dst_nonpremul >> 8))" +
+ ";\n uint32_t db = 0x101 * (0xFF & (dst_nonpremul >> 0));\n\n // Convert dst from nonpremul to premul.\n dr = (dr * da) / 0xFFFF;\n dg = (dg * da) / 0xFFFF;\n db = (db * da) / 0xFFFF;\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (premul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr = sr + ((dr * ia) / 0xFFFF);\n dg = sg + ((dg * ia) / 0xFFFF);\n db = sb + ((db * ia) / 0xFFFF);\n\n // Convert dst from premul to nonpremul.\n if (da != 0) {\n dr = (dr * 0xFFFF) / da;\n dg = (dg * 0xFFFF) / da;\n db = (db * 0xFFFF) / da;\n }\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}\n\nstatic inline uint32_t //\nwuffs_base__composite_premul_nonpremul_u32_axxx(uint32_t dst_premul,\n uint32_t src_nonpremul) {\n // Convert from 8-bit color to 16-bit color.\n " +
+ " uint32_t sa = 0x101 * (0xFF & (src_nonpremul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_nonpremul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_nonpremul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_nonpremul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));\n uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));\n uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (nonpremul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr = ((sr * sa) + (dr * ia)) / 0xFFFF;\n dg = ((sg * sa) + (dg * ia)) / 0xFFFF;\n db = ((sb * sa) + (db * ia)) / 0xFFFF;\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}\n\nstatic inline uint32_t //\nwuffs_base__composite_premul_premul_u32_axxx(uint32_t dst_premul,\n " +
+ " uint32_t src_premul) {\n // Convert from 8-bit color to 16-bit color.\n uint32_t sa = 0x101 * (0xFF & (src_premul >> 24));\n uint32_t sr = 0x101 * (0xFF & (src_premul >> 16));\n uint32_t sg = 0x101 * (0xFF & (src_premul >> 8));\n uint32_t sb = 0x101 * (0xFF & (src_premul >> 0));\n uint32_t da = 0x101 * (0xFF & (dst_premul >> 24));\n uint32_t dr = 0x101 * (0xFF & (dst_premul >> 16));\n uint32_t dg = 0x101 * (0xFF & (dst_premul >> 8));\n uint32_t db = 0x101 * (0xFF & (dst_premul >> 0));\n\n // Calculate the inverse of the src-alpha: how much of the dst to keep.\n uint32_t ia = 0xFFFF - sa;\n\n // Composite src (premul) over dst (premul).\n da = sa + ((da * ia) / 0xFFFF);\n dr = sr + ((dr * ia) / 0xFFFF);\n dg = sg + ((dg * ia) / 0xFFFF);\n db = sb + ((db * ia) / 0xFFFF);\n\n // Convert from 16-bit color to 8-bit color and combine the components.\n da >>= 8;\n dr >>= 8;\n dg >>= 8;\n db >>= 8;\n return (db << 0) | (dg << 8) | (dr << 16) | (da << 24);\n}\n\n" +
"" +
"// --------\n\nstatic uint64_t //\nwuffs_base__pixel_swizzler__squash_bgr_565_888(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 uint32_t argb = wuffs_base__load_u32le__no_bounds_check(s);\n uint32_t b5 = 0x1F & (argb >> (8 - 5));\n uint32_t g6 = 0x3F & (argb >> (16 - 6));\n uint32_t r5 = 0x1F & (argb >> (24 - 5));\n uint32_t alpha = argb & 0xFF000000;\n wuffs_base__store_u32le__no_bounds_check(\n d, alpha | (r5 << 11) | (g6 << 5) | (b5 << 0));\n s += 4;\n d += 4;\n }\n return len4 * 4;\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\n" +
diff --git a/internal/cgen/gen.go b/internal/cgen/gen.go
index b946828..8ce09e0 100644
--- a/internal/cgen/gen.go
+++ b/internal/cgen/gen.go
@@ -74,7 +74,6 @@
filename, varname string
}{
{"base/all-impl.c", "baseAllImplC"},
- {"base/image-impl.c", "baseImageImplC"},
{"base/strconv-impl.c", "baseStrConvImplC"},
{"base/f64conv-submodule.c", "baseF64ConvSubmoduleC"},
diff --git a/release/c/wuffs-unsupported-snapshot.c b/release/c/wuffs-unsupported-snapshot.c
index cba1b02..ca40912 100644
--- a/release/c/wuffs-unsupported-snapshot.c
+++ b/release/c/wuffs-unsupported-snapshot.c
@@ -7917,6 +7917,11 @@
0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF,
};
+const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,
+};
+
const char* wuffs_base__note__end_of_data = "@base: end of data";
const char* wuffs_base__note__metadata_reported = "@base: metadata reported";
const char* wuffs_base__suspension__even_more_information =
@@ -7971,249 +7976,6 @@
const char* wuffs_base__token_decoder__vtable_name =
"{vtable}wuffs_base__token_decoder";
-// ---------------- Images
-
-const uint32_t wuffs_base__pixel_format__bits_per_channel[16] = {
- 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x0A, 0x0C, 0x10, 0x18, 0x20, 0x30, 0x40,
-};
-
-// --------
-
-static inline uint32_t //
-wuffs_base__swap_u32_argb_abgr(uint32_t u) {
- uint32_t o = u & 0xFF00FF00;
- uint32_t r = u & 0x00FF0000;
- uint32_t b = u & 0x000000FF;
- return o | (r >> 16) | (b << 16);
-}
-
-// --------
-
-WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
-wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
- uint32_t x,
- uint32_t y) {
- if (!pb || (x >= pb->pixcfg.private_impl.width) ||
- (y >= pb->pixcfg.private_impl.height)) {
- return 0;
- }
-
- if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
- // TODO: support planar formats.
- return 0;
- }
-
- size_t stride = pb->private_impl.planes[0].stride;
- uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
-
- switch (pb->pixcfg.private_impl.pixfmt.repr) {
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
- return wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
-
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
- uint8_t* palette = pb->private_impl.planes[3].ptr;
- return wuffs_base__load_u32le__no_bounds_check(palette +
- (4 * ((size_t)row[x])));
- }
-
- // Common formats above. Rarer formats below.
-
- case WUFFS_BASE__PIXEL_FORMAT__Y:
- return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));
-
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {
- uint8_t* palette = pb->private_impl.planes[3].ptr;
- return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
- wuffs_base__load_u32le__no_bounds_check(palette +
- (4 * ((size_t)row[x]))));
- }
-
- case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
- return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
- wuffs_base__load_u16le__no_bounds_check(row + (2 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__BGR:
- return 0xFF000000 |
- wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x)));
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
- return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__BGRX:
- return 0xFF000000 |
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
-
- case WUFFS_BASE__PIXEL_FORMAT__RGB:
- return wuffs_base__swap_u32_argb_abgr(
- 0xFF000000 |
- wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
- return wuffs_base__swap_u32_argb_abgr(
- wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
- wuffs_base__load_u32le__no_bounds_check(row +
- (4 * ((size_t)x)))));
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
- return wuffs_base__swap_u32_argb_abgr(
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
- case WUFFS_BASE__PIXEL_FORMAT__RGBX:
- return wuffs_base__swap_u32_argb_abgr(
- 0xFF000000 |
- wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
-
- default:
- // TODO: support more formats.
- break;
- }
-
- return 0;
-}
-
-WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
-wuffs_base__pixel_buffer__set_color_u32_at(
- wuffs_base__pixel_buffer* pb,
- uint32_t x,
- uint32_t y,
- wuffs_base__color_u32_argb_premul color) {
- if (!pb) {
- return wuffs_base__make_status(wuffs_base__error__bad_receiver);
- }
- if ((x >= pb->pixcfg.private_impl.width) ||
- (y >= pb->pixcfg.private_impl.height)) {
- return wuffs_base__make_status(wuffs_base__error__bad_argument);
- }
-
- if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
- // TODO: support planar formats.
- return wuffs_base__make_status(wuffs_base__error__unsupported_option);
- }
-
- size_t stride = pb->private_impl.planes[0].stride;
- uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
-
- switch (pb->pixcfg.private_impl.pixfmt.repr) {
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__BGRX:
- wuffs_base__store_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);
- break;
-
- // Common formats above. Rarer formats below.
-
- case WUFFS_BASE__PIXEL_FORMAT__Y:
- wuffs_base__store_u8__no_bounds_check(
- row + ((size_t)x),
- wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));
- break;
-
- case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
- wuffs_base__store_u8__no_bounds_check(
- row + ((size_t)x), wuffs_base__pixel_palette__closest_element(
- wuffs_base__pixel_buffer__palette(pb),
- pb->pixcfg.private_impl.pixfmt, color));
- break;
-
- case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
- wuffs_base__store_u16le__no_bounds_check(
- row + (2 * ((size_t)x)),
- wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
- break;
- case WUFFS_BASE__PIXEL_FORMAT__BGR:
- wuffs_base__store_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);
- break;
- case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
- wuffs_base__store_u32le__no_bounds_check(
- row + (4 * ((size_t)x)),
- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
- color));
- break;
-
- case WUFFS_BASE__PIXEL_FORMAT__RGB:
- wuffs_base__store_u24le__no_bounds_check(
- row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
- break;
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
- wuffs_base__store_u32le__no_bounds_check(
- row + (4 * ((size_t)x)),
- wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
- wuffs_base__swap_u32_argb_abgr(color)));
- break;
- case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
- case WUFFS_BASE__PIXEL_FORMAT__RGBX:
- wuffs_base__store_u32le__no_bounds_check(
- row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
- break;
-
- default:
- // TODO: support more formats.
- return wuffs_base__make_status(wuffs_base__error__unsupported_option);
- }
-
- return wuffs_base__make_status(NULL);
-}
-
-// --------
-
-WUFFS_BASE__MAYBE_STATIC uint8_t //
-wuffs_base__pixel_palette__closest_element(
- wuffs_base__slice_u8 palette_slice,
- wuffs_base__pixel_format palette_format,
- wuffs_base__color_u32_argb_premul c) {
- size_t n = palette_slice.len / 4;
- if (n > 256) {
- n = 256;
- }
- size_t best_index = 0;
- uint64_t best_score = 0xFFFFFFFFFFFFFFFF;
-
- // Work in 16-bit color.
- uint32_t ca = 0x101 * (0xFF & (c >> 24));
- uint32_t cr = 0x101 * (0xFF & (c >> 16));
- uint32_t cg = 0x101 * (0xFF & (c >> 8));
- uint32_t cb = 0x101 * (0xFF & (c >> 0));
-
- switch (palette_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: {
- bool nonpremul = palette_format.repr ==
- WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;
-
- size_t i;
- for (i = 0; i < n; i++) {
- // Work in 16-bit color.
- uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0]));
- uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));
- uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));
- uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));
-
- // Convert to premultiplied alpha.
- if (nonpremul && (pa != 0xFFFF)) {
- pb = (pb * pa) / 0xFFFF;
- pg = (pg * pa) / 0xFFFF;
- pr = (pr * pa) / 0xFFFF;
- }
-
- // These deltas are conceptually int32_t (signed) but after squaring,
- // it's equivalent to work in uint32_t (unsigned).
- pb -= cb;
- pg -= cg;
- pr -= cr;
- pa -= ca;
- uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +
- ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));
- if (best_score > score) {
- best_score = score;
- best_index = i;
- }
- }
- break;
- }
- }
-
- return (uint8_t)best_index;
-}
-
// ---------------- String Conversions
// wuffs_base__parse_number__foo_digits entries are 0x00 for invalid digits,
@@ -10568,6 +10330,242 @@
// ---------------- Pixel Swizzler
static inline uint32_t //
+wuffs_base__swap_u32_argb_abgr(uint32_t u) {
+ uint32_t o = u & 0xFF00FF00;
+ uint32_t r = u & 0x00FF0000;
+ uint32_t b = u & 0x000000FF;
+ return o | (r >> 16) | (b << 16);
+}
+
+// --------
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__color_u32_argb_premul //
+wuffs_base__pixel_buffer__color_u32_at(const wuffs_base__pixel_buffer* pb,
+ uint32_t x,
+ uint32_t y) {
+ if (!pb || (x >= pb->pixcfg.private_impl.width) ||
+ (y >= pb->pixcfg.private_impl.height)) {
+ return 0;
+ }
+
+ if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
+ // TODO: support planar formats.
+ return 0;
+ }
+
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
+
+ switch (pb->pixcfg.private_impl.pixfmt.repr) {
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_BINARY:
+ return wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
+
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY: {
+ uint8_t* palette = pb->private_impl.planes[3].ptr;
+ return wuffs_base__load_u32le__no_bounds_check(palette +
+ (4 * ((size_t)row[x])));
+ }
+
+ // Common formats above. Rarer formats below.
+
+ case WUFFS_BASE__PIXEL_FORMAT__Y:
+ return 0xFF000000 | (0x00010101 * ((uint32_t)(row[x])));
+
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL: {
+ uint8_t* palette = pb->private_impl.planes[3].ptr;
+ return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
+ wuffs_base__load_u32le__no_bounds_check(palette +
+ (4 * ((size_t)row[x]))));
+ }
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
+ return wuffs_base__color_u16_rgb_565__as__color_u32_argb_premul(
+ wuffs_base__load_u16le__no_bounds_check(row + (2 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ return 0xFF000000 |
+ wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x)));
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
+ return wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__BGRX:
+ return 0xFF000000 |
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x)));
+
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ return wuffs_base__swap_u32_argb_abgr(
+ 0xFF000000 |
+ wuffs_base__load_u24le__no_bounds_check(row + (3 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
+ return wuffs_base__swap_u32_argb_abgr(
+ wuffs_base__color_u32_argb_nonpremul__as__color_u32_argb_premul(
+ wuffs_base__load_u32le__no_bounds_check(row +
+ (4 * ((size_t)x)))));
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_BINARY:
+ return wuffs_base__swap_u32_argb_abgr(
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
+ case WUFFS_BASE__PIXEL_FORMAT__RGBX:
+ return wuffs_base__swap_u32_argb_abgr(
+ 0xFF000000 |
+ wuffs_base__load_u32le__no_bounds_check(row + (4 * ((size_t)x))));
+
+ default:
+ // TODO: support more formats.
+ break;
+ }
+
+ return 0;
+}
+
+WUFFS_BASE__MAYBE_STATIC wuffs_base__status //
+wuffs_base__pixel_buffer__set_color_u32_at(
+ wuffs_base__pixel_buffer* pb,
+ uint32_t x,
+ uint32_t y,
+ wuffs_base__color_u32_argb_premul color) {
+ if (!pb) {
+ return wuffs_base__make_status(wuffs_base__error__bad_receiver);
+ }
+ if ((x >= pb->pixcfg.private_impl.width) ||
+ (y >= pb->pixcfg.private_impl.height)) {
+ return wuffs_base__make_status(wuffs_base__error__bad_argument);
+ }
+
+ if (wuffs_base__pixel_format__is_planar(&pb->pixcfg.private_impl.pixfmt)) {
+ // TODO: support planar formats.
+ return wuffs_base__make_status(wuffs_base__error__unsupported_option);
+ }
+
+ size_t stride = pb->private_impl.planes[0].stride;
+ uint8_t* row = pb->private_impl.planes[0].ptr + (stride * ((size_t)y));
+
+ switch (pb->pixcfg.private_impl.pixfmt.repr) {
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__BGRX:
+ wuffs_base__store_u32le__no_bounds_check(row + (4 * ((size_t)x)), color);
+ break;
+
+ // Common formats above. Rarer formats below.
+
+ case WUFFS_BASE__PIXEL_FORMAT__Y:
+ wuffs_base__store_u8__no_bounds_check(
+ row + ((size_t)x),
+ wuffs_base__color_u32_argb_premul__as__color_u8_gray(color));
+ break;
+
+ case WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_BINARY:
+ wuffs_base__store_u8__no_bounds_check(
+ row + ((size_t)x), wuffs_base__pixel_palette__closest_element(
+ wuffs_base__pixel_buffer__palette(pb),
+ pb->pixcfg.private_impl.pixfmt, color));
+ break;
+
+ case WUFFS_BASE__PIXEL_FORMAT__BGR_565:
+ wuffs_base__store_u16le__no_bounds_check(
+ row + (2 * ((size_t)x)),
+ wuffs_base__color_u32_argb_premul__as__color_u16_rgb_565(color));
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGR:
+ wuffs_base__store_u24le__no_bounds_check(row + (3 * ((size_t)x)), color);
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__BGRA_NONPREMUL:
+ wuffs_base__store_u32le__no_bounds_check(
+ row + (4 * ((size_t)x)),
+ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
+ color));
+ break;
+
+ case WUFFS_BASE__PIXEL_FORMAT__RGB:
+ wuffs_base__store_u24le__no_bounds_check(
+ row + (3 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_NONPREMUL:
+ wuffs_base__store_u32le__no_bounds_check(
+ row + (4 * ((size_t)x)),
+ wuffs_base__color_u32_argb_premul__as__color_u32_argb_nonpremul(
+ wuffs_base__swap_u32_argb_abgr(color)));
+ break;
+ case WUFFS_BASE__PIXEL_FORMAT__RGBA_PREMUL:
+ case WUFFS_BASE__PIXEL_FORMAT__RGBX:
+ wuffs_base__store_u32le__no_bounds_check(
+ row + (4 * ((size_t)x)), wuffs_base__swap_u32_argb_abgr(color));
+ break;
+
+ default:
+ // TODO: support more formats.
+ return wuffs_base__make_status(wuffs_base__error__unsupported_option);
+ }
+
+ return wuffs_base__make_status(NULL);
+}
+
+// --------
+
+WUFFS_BASE__MAYBE_STATIC uint8_t //
+wuffs_base__pixel_palette__closest_element(
+ wuffs_base__slice_u8 palette_slice,
+ wuffs_base__pixel_format palette_format,
+ wuffs_base__color_u32_argb_premul c) {
+ size_t n = palette_slice.len / 4;
+ if (n > 256) {
+ n = 256;
+ }
+ size_t best_index = 0;
+ uint64_t best_score = 0xFFFFFFFFFFFFFFFF;
+
+ // Work in 16-bit color.
+ uint32_t ca = 0x101 * (0xFF & (c >> 24));
+ uint32_t cr = 0x101 * (0xFF & (c >> 16));
+ uint32_t cg = 0x101 * (0xFF & (c >> 8));
+ uint32_t cb = 0x101 * (0xFF & (c >> 0));
+
+ switch (palette_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: {
+ bool nonpremul = palette_format.repr ==
+ WUFFS_BASE__PIXEL_FORMAT__INDEXED__BGRA_NONPREMUL;
+
+ size_t i;
+ for (i = 0; i < n; i++) {
+ // Work in 16-bit color.
+ uint32_t pb = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 0]));
+ uint32_t pg = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 1]));
+ uint32_t pr = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 2]));
+ uint32_t pa = 0x101 * ((uint32_t)(palette_slice.ptr[(4 * i) + 3]));
+
+ // Convert to premultiplied alpha.
+ if (nonpremul && (pa != 0xFFFF)) {
+ pb = (pb * pa) / 0xFFFF;
+ pg = (pg * pa) / 0xFFFF;
+ pr = (pr * pa) / 0xFFFF;
+ }
+
+ // These deltas are conceptually int32_t (signed) but after squaring,
+ // it's equivalent to work in uint32_t (unsigned).
+ pb -= cb;
+ pg -= cg;
+ pr -= cr;
+ pa -= ca;
+ uint64_t score = ((uint64_t)(pb * pb)) + ((uint64_t)(pg * pg)) +
+ ((uint64_t)(pr * pr)) + ((uint64_t)(pa * pa));
+ if (best_score > score) {
+ best_score = score;
+ best_index = i;
+ }
+ }
+ break;
+ }
+ }
+
+ return (uint8_t)best_index;
+}
+
+// --------
+
+static inline uint32_t //
wuffs_base__composite_nonpremul_nonpremul_u32_axxx(uint32_t dst_nonpremul,
uint32_t src_nonpremul) {
// Convert from 8-bit color to 16-bit color.