Fix a few more cases in which bKGD wasn't properly applied.

This commit is contained in:
Jeroen van Rijn
2021-05-01 16:05:13 +02:00
parent c2603297ee
commit db1ef078ff

View File

@@ -886,9 +886,25 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
}
case 2:
// Gray with alpha, we shouldn't have a tRNS chunk.
bg := f32(0.0);
if seen_bkgd {
bg = f32(img.background.([3]u16)[0]);
}
for len(p16) > 0 {
r := p16[0];
if premultiply {
if seen_bkgd {
alpha := f32(p16[1]) / f32(65535);
c := u16(f32(r) * alpha + (1.0 - alpha) * bg);
o16[0] = c;
o16[1] = c;
o16[2] = c;
/*
After BG blending, the pixel is now fully opaque.
Update the value we'll write to the output alpha.
*/
p16[1] = 65535;
} else if premultiply {
alpha := p16[1];
c := u16(f32(r) * f32(alpha) / f32(65535));
o16[0] = c;
@@ -900,7 +916,7 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
o16[2] = r;
}
if .alpha_drop_if_present not_in options {
if out_image_channels == 4 {
o16[3] = p16[1];
}
@@ -963,7 +979,22 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
b := p16[2];
a := p16[3];
if premultiply {
if seen_bkgd {
alpha := f32(a) / 65535.0;
c := img.background.([3]u16);
rb := f32(c[0]) * (1.0 - alpha);
gb := f32(c[1]) * (1.0 - alpha);
bb := f32(c[2]) * (1.0 - alpha);
o16[0] = u16(f32(r) * alpha + rb);
o16[1] = u16(f32(g) * alpha + gb);
o16[2] = u16(f32(b) * alpha + bb);
/*
After BG blending, the pixel is now fully opaque.
Update the value we'll write to the output alpha.
*/
a = 65535;
} else if premultiply {
alpha := f32(a) / 65535.0;
o16[0] = u16(f32(r) * alpha);
o16[1] = u16(f32(g) * alpha);
@@ -974,7 +1005,7 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
o16[2] = b;
}
if .alpha_drop_if_present not_in options {
if out_image_channels == 4 {
o16[3] = a;
}
@@ -992,7 +1023,7 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
// Check if we need to do something.
if raw_image_channels == out_image_channels {
// If we have 3 in and 3 out, or 4 in and 4 out without premultiplication...
if raw_image_channels == 4 && .alpha_premultiply not_in options {
if !premultiply {
// Then we're done.
return img, E_General.OK;
}
@@ -1050,9 +1081,25 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
}
case 2:
// Gray with alpha, we shouldn't have a tRNS chunk.
bg := f32(0.0);
if seen_bkgd {
bg = f32(img.background.([3]u16)[0]);
}
for len(p) > 0 {
r := p[0];
if .alpha_premultiply in options {
if seen_bkgd {
alpha := f32(p[1]) / f32(255);
c := u8(f32(r) * alpha + (1.0 - alpha) * bg);
o[0] = c;
o[1] = c;
o[2] = c;
/*
After BG blending, the pixel is now fully opaque.
Update the value we'll write to the output alpha.
*/
p[1] = 255;
} else if .alpha_premultiply in options {
alpha := p[1];
c := u8(f32(r) * f32(alpha) / f32(255));
o[0] = c;
@@ -1064,7 +1111,7 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
o[2] = r;
}
if .alpha_drop_if_present not_in options {
if out_image_channels == 4 {
o[3] = p[1];
}
@@ -1088,7 +1135,6 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
alpha := u8(1); // Default to full opaque
// TODO: Combine the seen_trns cases.
if seen_trns {
if r == key[0] && g == key[1] && b == key[2] {
if seen_bkgd {
@@ -1126,8 +1172,22 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
g := p[1];
b := p[2];
a := p[3];
if seen_bkgd {
alpha := f32(a) / 255.0;
c := img.background.([3]u16);
rb := f32(c[0]) * (1.0 - alpha);
gb := f32(c[1]) * (1.0 - alpha);
bb := f32(c[2]) * (1.0 - alpha);
if .alpha_premultiply in options {
o[0] = u8(f32(r) * alpha + rb);
o[1] = u8(f32(g) * alpha + gb);
o[2] = u8(f32(b) * alpha + bb);
/*
After BG blending, the pixel is now fully opaque.
Update the value we'll write to the output alpha.
*/
a = 255;
} else if premultiply {
alpha := f32(a) / 255.0;
o[0] = u8(f32(r) * alpha);
o[1] = u8(f32(g) * alpha);
@@ -1138,7 +1198,7 @@ load_from_stream :: proc(stream: io.Stream, options := Options{}, allocator := c
o[2] = b;
}
if .alpha_drop_if_present not_in options {
if out_image_channels == 4 {
o[3] = a;
}
@@ -1207,7 +1267,6 @@ defilter_8 :: proc(params: ^Filter_Params) -> (ok: bool) {
nk := row_stride - channels;
filter := Row_Filter(src[0]); src = src[1:];
// fmt.printf("Row: %v | Filter: %v\n", y, filter);
switch(filter) {
case .None:
copy(dest, src[:row_stride]);