aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fastiv-io.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/fastiv-io.c b/fastiv-io.c
index 67041d3..33ff9b8 100644
--- a/fastiv-io.c
+++ b/fastiv-io.c
@@ -162,6 +162,9 @@ try_append_page(cairo_surface_t *surface, cairo_surface_t **result,
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+// From libwebp, verified to exactly match [x * a / 255].
+#define PREMULTIPLY8(a, x) (((uint32_t) (x) * (uint32_t) (a) * 32897U) >> 23)
+
static bool
pull_passthrough(const wuffs_base__more_information *minfo,
wuffs_base__io_buffer *src, wuffs_base__io_buffer *dst, GError **error)
@@ -1375,12 +1378,11 @@ load_libheif_image(struct heif_image_handle *handle, GError **error)
for (int y = 0; y < h; y++) {
uint32_t *dstp = (uint32_t *) (dst + dst_stride * y);
for (int x = 0; x < w; x++) {
- uint32_t pixel = dstp[x], a = pixel >> 24;
- uint8_t r = pixel >> 16;
- uint8_t g = pixel >> 8;
- uint8_t b = pixel;
+ uint32_t argb = dstp[x], a = argb >> 24;
dstp[x] = a << 24 |
- (r * a / 255) << 16 | (g * a / 255) << 8 | (b * a / 255);
+ PREMULTIPLY8(a, 0xFF & (argb >> 16)) << 16 |
+ PREMULTIPLY8(a, 0xFF & (argb >> 8)) << 8 |
+ PREMULTIPLY8(a, 0xFF & argb);
}
}
}
@@ -2361,9 +2363,9 @@ read_spng_thumbnail(
for (size_t i = size / sizeof *data; i--; ) {
const uint8_t *unit = (const uint8_t *) &data[i];
uint32_t a = unit[3],
- b = unit[2] * a / 255,
- g = unit[1] * a / 255,
- r = unit[0] * a / 255;
+ b = PREMULTIPLY8(a, unit[2]),
+ g = PREMULTIPLY8(a, unit[1]),
+ r = PREMULTIPLY8(a, unit[0]);
data[i] = a << 24 | r << 16 | g << 8 | b;
}
} else {