diff --git a/crates/algo/src/art_history.rs b/crates/algo/src/art_history.rs
--- a/crates/algo/src/art_history.rs
+++ b/crates/algo/src/art_history.rs
@@ -333,10 +333,12 @@ struct SrcView<'a> {
     h: usize,
     origin: (i32, i32),
     ch: usize,
+    alpha: Option<usize>,
 }
 
 fn sample_bilinear(src: SrcView<'_>, sx: f32, sy: f32, out: &mut [f32]) -> bool {
     let ch = src.ch;
+    let alpha = src.alpha.filter(|&a| a < ch);
     if ch == 0 || out.len() < ch {
         return false;
     }
@@ -370,12 +372,19 @@ fn sample_bilinear(src: SrcView<'_>, sx: f32, sy: f32, out: &mut [f32]) -> bool
             let (Ok(ux), Ok(uy)) = (usize::try_from(px), usize::try_from(py)) else { continue };
             let Some(base) = pixel_index(ux, uy, src.w, src.h, ch) else { continue };
             let Some(pxs) = src.data.get(base..base.saturating_add(ch)) else { continue };
-            for (d, s) in dst.iter_mut().zip(pxs.iter()) {
-                *d += *s * wt;
+            let coverage = alpha.and_then(|a| pxs.get(a)).copied().unwrap_or(1.0);
+            for (c, (d, s)) in dst.iter_mut().zip(pxs.iter()).enumerate() {
+                *d += *s * wt * if alpha.is_some_and(|a| c < a) { coverage } else { 1.0 };
             }
             any = true;
         }
     }
+    if let Some(a) = alpha {
+        let coverage = dst.get(a).copied().unwrap_or(0.0);
+        for value in dst.iter_mut().take(a) {
+            *value = if coverage > 0.0 { *value / coverage } else { 0.0 };
+        }
+    }
     any
 }
 
@@ -535,7 +544,7 @@ fn stamp_dab_on_rect(p: &mut StampParams<'_>, dab: &Dab, rect: (i32, i32, i32, i
                 continue;
             }
             let (sx, sy) = rotated_source(dab, x, y);
-            if !sample_bilinear(SrcView { data: p.src, w: p.src_w, h: p.src_h, origin: p.src_origin, ch: p.ch }, sx, sy, &mut sampled) {
+            if !sample_bilinear(SrcView { data: p.src, w: p.src_w, h: p.src_h, origin: p.src_origin, ch: p.ch, alpha: p.alpha }, sx, sy, &mut sampled) {
                 continue;
             }
             let Some(li) = pixel_index(lx, ly, tw, th, p.ch) else { continue };
@@ -585,13 +594,16 @@ fn dab_mean_diff(p: &StampParams<'_>, dab: &Dab) -> Option<f32> {
             let Some(di) = origin_index(p.dest_origin, x, y, p.dest_w, p.dest_h, p.ch) else { continue };
             let Some(dst) = p.dest.get(di..di.saturating_add(p.ch)) else { continue };
             let (sx, sy) = rotated_source(dab, x, y);
-            if !sample_bilinear(SrcView { data: p.src, w: p.src_w, h: p.src_h, origin: p.src_origin, ch: p.ch }, sx, sy, &mut sampled) {
+            if !sample_bilinear(SrcView { data: p.src, w: p.src_w, h: p.src_h, origin: p.src_origin, ch: p.ch, alpha: p.alpha }, sx, sy, &mut sampled) {
                 continue;
             }
             let nch = p.ch.min(dst.len()).min(sampled.len());
             if nch == 0 {
                 continue;
             }
+            if p.alpha.is_some_and(|a| sampled.get(a).is_some_and(|&v| v == 0.0)) {
+                continue;
+            }
             let (mut colour, mut colours, mut alpha) = (0.0f32, 0u32, 0.0f32);
             for i in 0..nch {
                 let Some((&s, &d)) = sampled.get(i).zip(dst.get(i)) else { continue };
diff --git a/crates/algo/src/art_history/tests.rs b/crates/algo/src/art_history/tests.rs
--- a/crates/algo/src/art_history/tests.rs
+++ b/crates/algo/src/art_history/tests.rs
@@ -1,5 +1,96 @@
 use super::*;
 
+#[test]
+fn tolerance_ignores_fully_transparent_samples() {
+    for ch in [2, 4, 5] {
+        for hidden in [1.0, 0.0] {
+            let src = fill(2, 1, ch, |x, _, c| {
+                if c + 1 == ch {
+                    if x == 0 { 1.0 } else { 0.0 }
+                } else if x == 0 {
+                    0.4
+                } else {
+                    hidden
+                }
+            });
+            let before = fill(2, 1, ch, |x, _, c| {
+                if c + 1 == ch {
+                    if x == 0 { 1.0 } else { 0.0 }
+                } else if x == 0 {
+                    0.0
+                } else {
+                    hidden
+                }
+            });
+            let dab = Dab { x: 1.0, y: 0.5, theta: 0.0, radius: 2.0, pressure: 1.0 };
+            for tolerance in [0.6, 0.3] {
+                let mut dest = before.clone();
+                let written = stamp(&mut StampParams {
+                    dest: &mut dest,
+                    dest_w: 2,
+                    dest_h: 1,
+                    dest_origin: (0, 0),
+                    src: &src,
+                    src_w: 2,
+                    src_h: 1,
+                    src_origin: (0, 0),
+                    ch,
+                    dabs: std::slice::from_ref(&dab),
+                    hardness: 1.0,
+                    opacity: 1.0,
+                    flow: 1.0,
+                    tolerance,
+                    tile: 0,
+                    selection: None,
+                    lock_transparent: false,
+                    alpha: Some(ch - 1),
+                })
+                .unwrap();
+                if tolerance == 0.6 {
+                    assert_eq!(written, 0, "channels={ch}, hidden={hidden}");
+                    assert_eq!(dest, before);
+                } else {
+                    assert!(written > 0, "channels={ch}, hidden={hidden}");
+                    assert!((dest[0] - 0.4).abs() < 1e-6);
+                    assert_eq!(&dest[ch..], &before[ch..]);
+                }
+            }
+        }
+    }
+}
+
+#[test]
+fn rotated_dabs_preserve_color_at_transparent_edges() {
+    for ch in [2, 4, 5] {
+        for hidden in [0.0, 1.0] {
+            let (w, h) = (4, 4);
+            let src = fill(w, h, ch, |x, _, c| {
+                if c + 1 == ch {
+                    if x < 2 { 1.0 } else { 0.0 }
+                } else if x < 2 {
+                    if c == 0 { 0.8 } else { 0.25 }
+                } else {
+                    hidden
+                }
+            });
+            let mut dest = vec![0.0; w * h * ch];
+            let dab = Dab { x: 2.0, y: 2.0, theta: std::f32::consts::FRAC_PI_4, radius: 4.0, pressure: 1.0 };
+            stamp_run(w, h, ch, &src, &mut dest, &dab, 0);
+            let mut partial = 0;
+            for pixel in dest.chunks_exact(ch) {
+                if pixel[ch - 1] > 0.0 && pixel[ch - 1] < 1.0 {
+                    partial += 1;
+                    for (c, value) in pixel[..ch - 1].iter().enumerate() {
+                        let expected = if c == 0 { 0.8 } else { 0.25 };
+                        assert!((value - expected).abs() < 1e-6, "channels={ch}, hidden={hidden}, pixel={pixel:?}");
+                    }
+                }
+            }
+            assert!(partial > 0);
+        }
+    }
+}
+
 fn fill(w: usize, h: usize, ch: usize, f: impl Fn(i32, i32, usize) -> f32) -> Vec<f32> {
     let mut v = vec![0.0; w * h * ch];
     for y in 0..h {
