diff options
| author | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-06-09 16:10:06 +0200 |
|---|---|---|
| committer | Jeroen van Rijn <Kelimion@users.noreply.github.com> | 2024-06-09 16:10:06 +0200 |
| commit | d2a2c1e74e62ab3fdb11d93f4ef8f74e4727bcda (patch) | |
| tree | deaab08106ec3128a7d5decd8d64cef8a750ae8f /core/image | |
| parent | 8fcfd8c506752d3e0d65e4d9ef7856486a65ca5f (diff) | |
Image: Add improved blending method and test it.
Diffstat (limited to 'core/image')
| -rw-r--r-- | core/image/common.odin | 17 | ||||
| -rw-r--r-- | core/image/png/png.odin | 20 |
2 files changed, 26 insertions, 11 deletions
diff --git a/core/image/common.odin b/core/image/common.odin index fe75371b3..15c5bbbce 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -42,6 +42,23 @@ GA_Pixel :: [2]u8 G_Pixel_16 :: [1]u16 GA_Pixel_16 :: [2]u16 +blend_single_channel :: #force_inline proc(fg, alpha, bg: $T) -> (res: T) where T == u8 || T == u16 { + MAX :: 256 when T == u8 else 65536 + + c := u32(fg) * (MAX - u32(alpha)) + u32(bg) * (1 + u32(alpha)) + return T(c & (MAX - 1)) +} + +blend_pixel :: #force_inline proc(fg: [$N]$T, alpha: T, bg: [N]T) -> (res: [N]T) where (T == u8 || T == u16), N >= 1 && N <= 4 { + MAX :: 256 when T == u8 else 65536 + + r_a := u32(fg) * (MAX - u32(alpha)) + u32(bg) * (1 + u32(alpha)) + + return +} + +blend :: proc{blend_single_channel, blend_pixel} + Image :: struct { width: int, height: int, diff --git a/core/image/png/png.odin b/core/image/png/png.odin index 4bb070da8..9a91575a8 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -597,7 +597,7 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a dsc := depth_scale_table scale := dsc[info.header.bit_depth] if scale != 1 { - key := mem.slice_data_cast([]u16be, c.data)[0] * u16be(scale) + key := (^u16be)(raw_data(c.data))^ * u16be(scale) c.data = []u8{0, u8(key & 255)} } } @@ -762,19 +762,18 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a for w := 0; w < int(img.width); w += 1 { index := temp.buf[i] - c := _plte.entries[index] - a := int(index) < len(trns.data) ? trns.data[index] : 255 - alpha := f32(a) / 255.0 + c := _plte.entries[index] + a := int(index) < len(trns.data) ? trns.data[index] : 255 if blend_background { - c.r = u8((1.0 - alpha) * bg[0] + f32(c.r) * alpha) - c.g = u8((1.0 - alpha) * bg[1] + f32(c.g) * alpha) - c.b = u8((1.0 - alpha) * bg[2] + f32(c.b) * alpha) + c.r = image.blend(c.r, a, u8(u32(bg.r))) + c.g = image.blend(c.g, a, u8(u32(bg.g))) + c.b = image.blend(c.b, a, u8(u32(bg.b))) a = 255 } else if premultiply { - c.r = u8(f32(c.r) * alpha) - c.g = u8(f32(c.g) * alpha) - c.b = u8(f32(c.b) * alpha) + c.r = image.blend(u8(0), a, c.r) + c.g = image.blend(u8(0), a, c.g) + c.b = image.blend(u8(0), a, c.b) } t.buf[j ] = c.r @@ -1627,7 +1626,6 @@ defilter :: proc(img: ^Image, filter_bytes: ^bytes.Buffer, header: ^image.PNG_IH return nil } - @(init, private) _register :: proc() { image.register(.PNG, load_from_bytes, destroy) |