Browse Source

Use new blend helper

Jeroen van Rijn 1 year ago
parent
commit
6b88d0a820
2 changed files with 41 additions and 28 deletions
  1. 35 18
      core/image/common.odin
  2. 6 10
      core/image/png/png.odin

+ 35 - 18
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
-}
+}

+ 6 - 10
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: