mirror of
https://github.com/Ed94/Odin.git
synced 2026-07-21 00:46:47 +00:00
+35
-1
@@ -1259,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.
|
||||
@@ -1371,4 +1405,4 @@ write_bytes :: proc(buf: ^bytes.Buffer, data: []u8) -> (err: compress.General_Er
|
||||
return .Resize_Failed
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
+28
-40
@@ -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)}
|
||||
}
|
||||
}
|
||||
@@ -735,59 +735,48 @@ load_from_context :: proc(ctx: ^$C, options := Options{}, allocator := context.a
|
||||
return {}, .Unable_To_Allocate_Or_Resize
|
||||
}
|
||||
|
||||
i := 0; j := 0
|
||||
|
||||
// If we don't have transparency or drop it without applying it, we can do this:
|
||||
if (!seen_trns || (seen_trns && .alpha_drop_if_present in options && .alpha_premultiply not_in options)) && .alpha_add_if_missing not_in options {
|
||||
for h := 0; h < int(img.height); h += 1 {
|
||||
for w := 0; w < int(img.width); w += 1 {
|
||||
c := _plte.entries[temp.buf[i]]
|
||||
t.buf[j ] = c.r
|
||||
t.buf[j+1] = c.g
|
||||
t.buf[j+2] = c.b
|
||||
i += 1; j += 3
|
||||
}
|
||||
output := mem.slice_data_cast([]image.RGB_Pixel, t.buf[:])
|
||||
for pal_idx, idx in temp.buf {
|
||||
output[idx] = _plte.entries[pal_idx]
|
||||
}
|
||||
} 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
|
||||
blend_background := seen_bkgd && .blend_background in options
|
||||
|
||||
for h := 0; h < int(img.height); h += 1 {
|
||||
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
|
||||
if no_alpha {
|
||||
output := mem.slice_data_cast([]image.RGB_Pixel, t.buf[:])
|
||||
for orig, idx in temp.buf {
|
||||
c := _plte.entries[orig]
|
||||
a := int(orig) < len(trns.data) ? trns.data[orig] : 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)
|
||||
output[idx] = image.blend(c, a, bg)
|
||||
} else if premultiply {
|
||||
output[idx] = image.blend(PLTE_Entry{}, a, c)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
output := mem.slice_data_cast([]image.RGBA_Pixel, t.buf[:])
|
||||
for orig, idx in temp.buf {
|
||||
c := _plte.entries[orig]
|
||||
a := int(orig) < len(trns.data) ? trns.data[orig] : 255
|
||||
|
||||
if blend_background {
|
||||
c = image.blend(c, a, bg)
|
||||
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 = image.blend(PLTE_Entry{}, a, c)
|
||||
}
|
||||
|
||||
t.buf[j ] = c.r
|
||||
t.buf[j+1] = c.g
|
||||
t.buf[j+2] = c.b
|
||||
i += 1
|
||||
|
||||
if no_alpha {
|
||||
j += 3
|
||||
} else {
|
||||
t.buf[j+3] = u8(a)
|
||||
j += 4
|
||||
}
|
||||
output[idx] = {c.r, c.g, c.b, u8(a)}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -1015,8 +1004,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:
|
||||
@@ -1627,7 +1616,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)
|
||||
|
||||
@@ -1479,7 +1479,6 @@ run_png_suite :: proc(t: ^testing.T, suite: []Test) {
|
||||
|
||||
png_hash := hash.crc32(pixels)
|
||||
testing.expectf(t, test.hash == png_hash, "%v test %v hash is %08x, expected %08x with %v", file.file, count, png_hash, test.hash, test.options)
|
||||
|
||||
passed &= test.hash == png_hash
|
||||
|
||||
if passed {
|
||||
@@ -2358,4 +2357,40 @@ run_bmp_suite :: proc(t: ^testing.T, suite: []Test) {
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@test
|
||||
will_it_blend :: proc(t: ^testing.T) {
|
||||
Pixel :: image.RGB_Pixel
|
||||
Pixel_16 :: image.RGB_Pixel_16
|
||||
|
||||
{
|
||||
bg := Pixel{255, 255, 0}
|
||||
fg := Pixel{ 0, 0, 255}
|
||||
|
||||
for a in 0..=255 {
|
||||
blended := Pixel{
|
||||
image.blend(fg.r, u8(a), bg.r),
|
||||
image.blend(fg.g, u8(a), bg.g),
|
||||
image.blend(fg.b, u8(a), bg.b),
|
||||
}
|
||||
testing.expectf(t, blended.r == bg.r - u8(a), "Expected blend(%v, %3d, %v) = %v, got %v", fg.r, a, bg.r, bg.r - u8(a), blended.r)
|
||||
testing.expectf(t, blended.b == 255 - blended.r, "Expected blend(%v, %3d, %v) = %v, got %v", fg.b, a, bg.b, 255 - blended.r, blended.b)
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
bg := Pixel_16{65535, 65535, 0}
|
||||
fg := Pixel_16{ 0, 0, 65535}
|
||||
|
||||
for a in 0..=65535 {
|
||||
blended := Pixel_16{
|
||||
image.blend(fg.r, u16(a), bg.r),
|
||||
image.blend(fg.g, u16(a), bg.g),
|
||||
image.blend(fg.b, u16(a), bg.b),
|
||||
}
|
||||
testing.expectf(t, blended.r == bg.r - u16(a), "Expected blend(%v, %3d, %v) = %v, got %v", fg.r, a, bg.r, bg.r - u16(a), blended.r)
|
||||
testing.expectf(t, blended.b == 65535 - blended.r, "Expected blend(%v, %3d, %v) = %v, got %v", fg.b, a, bg.b, 65535 - blended.r, blended.b)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,6 @@ download_assets :: proc() {
|
||||
@(require) import "encoding/varint"
|
||||
@(require) import "encoding/xml"
|
||||
@(require) import "fmt"
|
||||
@(require) import "image"
|
||||
@(require) import "math"
|
||||
@(require) import "math/big"
|
||||
@(require) import "math/linalg/glsl"
|
||||
|
||||
@@ -3,3 +3,4 @@ package tests_core
|
||||
|
||||
@(require) import "crypto"
|
||||
@(require) import "hash"
|
||||
@(require) import "image"
|
||||
Reference in New Issue
Block a user