diff --git a/core/image/common.odin b/core/image/common.odin index 15c5bbbce..fed2c1470 100644 --- a/core/image/common.odin +++ b/core/image/common.odin @@ -42,23 +42,6 @@ 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, @@ -1276,6 +1259,40 @@ apply_palette_rgba :: proc(img: ^Image, palette: [256]RGBA_Pixel, allocator := c } apply_palette :: proc{apply_palette_rgb, apply_palette_rgba} +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 + + when N == 1 { + r := u32(fg.r) * (MAX - u32(alpha)) + u32(bg.r) * (1 + u32(alpha)) + return {T(r & (MAX - 1))} + } + when N == 2 { + r := u32(fg.r) * (MAX - u32(alpha)) + u32(bg.r) * (1 + u32(alpha)) + g := u32(fg.g) * (MAX - u32(alpha)) + u32(bg.g) * (1 + u32(alpha)) + return {T(r & (MAX - 1)), T(g & (MAX - 1))} + } + when N == 3 || N == 4 { + r := u32(fg.r) * (MAX - u32(alpha)) + u32(bg.r) * (1 + u32(alpha)) + g := u32(fg.g) * (MAX - u32(alpha)) + u32(bg.g) * (1 + u32(alpha)) + b := u32(fg.b) * (MAX - u32(alpha)) + u32(bg.b) * (1 + u32(alpha)) + + when N == 3 { + return {T(r & (MAX - 1)), T(g & (MAX - 1)), T(b & (MAX - 1))} + } else { + return {T(r & (MAX - 1)), T(g & (MAX - 1)), T(b & (MAX - 1)), MAX - 1} + } + } + unreachable() +} +blend :: proc{blend_single_channel, blend_pixel} + // Replicates grayscale values into RGB(A) 8- or 16-bit images as appropriate. // Returns early with `false` if already an RGB(A) image. @@ -1388,4 +1405,4 @@ write_bytes :: proc(buf: ^bytes.Buffer, data: []u8) -> (err: compress.General_Er return .Resize_Failed } return nil -} +} \ No newline at end of file diff --git a/core/image/png/png.odin b/core/image/png/png.odin index 9a91575a8..56a939682 100644 --- a/core/image/png/png.odin +++ b/core/image/png/png.odin @@ -749,10 +749,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a } } } else if add_alpha || .alpha_drop_if_present in options { - bg := [3]f32{0, 0, 0} + bg := PLTE_Entry{0, 0, 0} if premultiply && seen_bkgd { c16 := img.background.([3]u16) - bg = [3]f32{f32(c16.r), f32(c16.g), f32(c16.b)} + bg = {u8(c16.r), u8(c16.g), u8(c16.b)} } no_alpha := (.alpha_drop_if_present in options || premultiply) && .alpha_add_if_missing not_in options @@ -766,14 +766,10 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a a := int(index) < len(trns.data) ? trns.data[index] : 255 if blend_background { - 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))) + c = image.blend(c, a, bg) a = 255 } else if premultiply { - 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) + c = image.blend(PLTE_Entry{}, a, c) } t.buf[j ] = c.r @@ -1014,8 +1010,8 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a return {}, .Unable_To_Allocate_Or_Resize } - p := mem.slice_data_cast([]u8, temp.buf[:]) - o := mem.slice_data_cast([]u8, t.buf[:]) + p := temp.buf[:] + o := t.buf[:] switch raw_image_channels { case 1: