fix(mode): restore indexed pixels after clearing transparency (#3080) (#3153)

This commit is contained in:
Sir Starch authored and GitHub committed 2026-10-11 16:50:58 -04:00
1 parent a97cfd103e
commit 06dcdc1267
2 files changed
+46 -5

No files matched your search

+17 -5
View File
@@ -325,11 +325,23 @@ fn color_table(s: &mut Session, p: &Value) -> Result<Value> {
let mut data = surf.read_region(r);
for q in data.chunks_exact_mut(n) {
let c = photocraft_raster::to_rgba(&fmt, q);
if c[3] <= 0.0 {
continue;
}
let i = old.nearest([c[0], c[1], c[2]]);
let alpha = if table.transparent == Some(i as u8) { 0.0 } else { c[3] };
let rgb = [c[0], c[1], c[2]];
let i = if c[3] <= 0.0 {
let Some(i) = old.transparent.map(usize::from) else { continue };
if i >= old.colors.len() || old.rgb(i) != rgb {
continue;
}
i
} else {
old.nearest(rgb)
};
let alpha = if table.transparent == Some(i as u8) {
0.0
} else if c[3] <= 0.0 {
1.0
} else {
c[3]
};
let nc = if i < table.colors.len() { table.rgb(i) } else { table.rgb(table.nearest([c[0], c[1], c[2]])) };
let mut enc = [0.0f32; 8];
let m = photocraft_raster::from_rgba_into(&fmt, [nc[0], nc[1], nc[2], alpha], &mut enc);
+29
View File
@@ -192,6 +192,35 @@ fn color_table_presets_and_entries() {
assert!(s.execute("image.mode.colorTable", json!({"entries": {"999": "#000000"}})).is_err());
}
#[test]
fn clearing_color_table_transparency_restores_indexed_pixels() {
let pixel = |s: &mut Session| -> [f32; 4] { serde_json::from_value(s.execute("document.pixel", json!({"x": 5, "y": 8})).unwrap()).unwrap() };
let mut s = Session::new();
s.execute("file.new", json!({"width": 16, "height": 16, "background": "#ff0000"})).unwrap();
s.execute("image.mode.indexedColor", json!({"palette": "exact", "colors": 2, "forced": "none", "dither": "none"})).unwrap();
assert_eq!(doc(&s).color_table.as_ref().unwrap().colors, vec![[255, 0, 0]]);
assert_eq!(pixel(&mut s), [1.0, 0.0, 0.0, 1.0]);
s.execute("image.mode.colorTable", json!({"transparent": 0})).unwrap();
assert_eq!(pixel(&mut s), [0.0; 4]);
s.execute("image.mode.colorTable", json!({"transparent": null})).unwrap();
assert_eq!(doc(&s).layers[0].surface().unwrap().rgba(5, 8), [1.0, 0.0, 0.0, 1.0], "clearing the transparent palette entry should restore the stored pixel");
assert_eq!(pixel(&mut s), [1.0, 0.0, 0.0, 1.0]);
s.execute("image.mode.rgb", json!({})).unwrap();
assert_eq!(pixel(&mut s), [1.0, 0.0, 0.0, 1.0]);
let mut control = Session::new();
control.execute("file.new", json!({"width": 16, "height": 16, "background": "#ff0000"})).unwrap();
control.execute("image.mode.indexedColor", json!({"palette": "exact", "colors": 2, "forced": "none", "dither": "none"})).unwrap();
control.execute("image.mode.colorTable", json!({"entries": {"0": "#0000ff"}})).unwrap();
let blue: [f32; 4] = serde_json::from_value(control.execute("document.pixel", json!({"x": 5, "y": 8})).unwrap()).unwrap();
assert_eq!(blue, [0.0, 0.0, 1.0, 1.0]);
control.execute("image.mode.colorTable", json!({"transparent": 0})).unwrap();
control.execute("edit.undo", json!({})).unwrap();
let restored: [f32; 4] = serde_json::from_value(control.execute("document.pixel", json!({"x": 5, "y": 8})).unwrap()).unwrap();
assert_eq!(restored, [0.0, 0.0, 1.0, 1.0]);
}
#[test]
fn bitmap_methods_need_grayscale() {
let mut s = session(32, 32, 16, "rgb");