mirror of
https://github.com/storytold/photocraft.git
synced 2026-10-14 19:26:51 -04:00
* Color Picker: CMYK foreground fills a CMYK document with the picked inks (#4196) The tool colours are stored as sRGB, so a colour picked as CMYK 100/0/0/0 (outside sRGB) came back as 100/28/0/17 when a CMYK document was filled. tools.setColors now takes foregroundCmyk/backgroundCmyk, the picker sends the entered inks, and Edit > Fill (and the fill keys) write them as they are into a CMYK target. Fill also enters the document's CMYK profile. Co-Authored-By: Claude Opus 5.5 <[email protected]> * Brush and Pencil paint a CMYK foreground with the picked inks in a CMYK document (#4344) Co-Authored-By: Claude Sonnet 5.5 <[email protected]> --------- Co-authored-by: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
f48a72cbe3
commit
46740ad4bc
4 files changed
+33
-1
No files matched your search
@@ -204,6 +204,7 @@ pub fn resolve_brush(s: &Session, p: &Value, cmd: &str) -> Result<BrushSettings>
|
||||
b.smoothing.amount = v.clamp(0.0, 1.0);
|
||||
}
|
||||
b.color = color(p.get("color"), s.tools.foreground);
|
||||
b.color_cmyk = s.tools.picked_cmyk([b.color[0], b.color[1], b.color[2]]).map(|k| ([b.color[0], b.color[1], b.color[2]], k));
|
||||
b.background = s.tools.background;
|
||||
b.erase = flag(p, "erase", false);
|
||||
b.seed = match p.get("seed").and_then(Value::as_u64) {
|
||||
@@ -367,6 +368,7 @@ fn block_brush(b: BrushSettings, p: &Value) -> Result<BrushSettings> {
|
||||
pressure_opacity: false,
|
||||
spacing: 0.25,
|
||||
color: b.color,
|
||||
color_cmyk: b.color_cmyk,
|
||||
background: b.background,
|
||||
erase: b.erase,
|
||||
smoothing: b.smoothing,
|
||||
|
||||
@@ -883,3 +883,21 @@ fn clear_mode_erases_with_the_brush_or_pencil() {
|
||||
assert_eq!(s.active().unwrap().history.undo_label(), Some(label), "{cmd}");
|
||||
}
|
||||
}
|
||||
|
||||
/// #4344: a foreground picked as CMYK 100/0/0/0 is painted into a CMYK document as those inks by
|
||||
/// the Brush and the Pencil, not as whatever its sRGB stand-in converts back to (100/28/0/17).
|
||||
#[test]
|
||||
fn brush_and_pencil_paint_a_cmyk_pick_with_the_picked_inks() {
|
||||
let cyan = [1.0f32, 0.0, 0.0, 0.0];
|
||||
for cmd in ["paint.stroke", "paint.pencil"] {
|
||||
let mut s = session(16, 16);
|
||||
s.execute("image.mode.cmyk", json!({})).unwrap();
|
||||
let rgb = photocraft_color::convert::cmyk_to_rgb(cyan).map(|c| c.clamp(0.0, 1.0));
|
||||
s.execute("tools.setColors", json!({"foreground": rgb, "foregroundCmyk": cyan})).unwrap();
|
||||
s.execute(cmd, json!({"points": [[8.0, 8.0]], "size": 6.0, "hardness": 1.0})).unwrap();
|
||||
let st = s.active().unwrap();
|
||||
let surf = st.doc.layer(st.active_layer.unwrap()).unwrap().surface().unwrap();
|
||||
let got: Vec<f32> = surf.read_region(Rect::new(8, 8, 9, 9)).into_iter().take(4).collect();
|
||||
assert!(got.iter().zip(cyan).all(|(a, b)| (a - b).abs() < 0.02), "{cmd}: {got:?}");
|
||||
}
|
||||
}
|
||||
@@ -486,6 +486,11 @@ pub struct BrushSettings {
|
||||
pub pressure_opacity: bool,
|
||||
/// Straight RGBA colour (display RGB). Commands fill it from the foreground colour.
|
||||
pub color: [f32; 4],
|
||||
/// The inks `color` was picked as (its sRGB colour, the CMYK values), for a CMYK target: the
|
||||
/// stroke paints exactly these, since an sRGB round trip does not give them back (#4344).
|
||||
/// Only valid while `color` is that sRGB colour; ignored with Color Dynamics.
|
||||
#[serde(skip)]
|
||||
pub color_cmyk: Option<([f32; 3], [f32; 4])>,
|
||||
/// Background colour for Color Dynamics' foreground/background jitter.
|
||||
pub background: [f32; 4],
|
||||
/// Erase instead of paint.
|
||||
@@ -545,6 +550,7 @@ impl Default for BrushSettings {
|
||||
pressure_size: true,
|
||||
pressure_opacity: false,
|
||||
color: [0.0, 0.0, 0.0, 1.0],
|
||||
color_cmyk: None,
|
||||
background: [1.0, 1.0, 1.0, 1.0],
|
||||
erase: false,
|
||||
mode: BlendMode::Normal,
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::sync::Arc;
|
||||
|
||||
use photocraft_color::{BlendMode, PixelFormat, SampleType};
|
||||
use photocraft_color::{BlendMode, ColorMode, PixelFormat, SampleType};
|
||||
use photocraft_geom::Rect;
|
||||
use photocraft_raster::{Surface, from_rgba_into, to_rgba};
|
||||
|
||||
@@ -966,6 +966,12 @@ impl StrokeRenderer {
|
||||
let opacity = b.opacity.clamp(0.0, 1.0);
|
||||
let mut src = [0.0f32; 8];
|
||||
from_rgba_into(&fmt, b.color, &mut src);
|
||||
// A colour picked as CMYK paints its inks as they are in a CMYK target (#4344).
|
||||
if let (ColorMode::Cmyk, Some((rgb, inks))) = (fmt.mode, b.color_cmyk)
|
||||
&& rgb == [b.color[0], b.color[1], b.color[2]]
|
||||
{
|
||||
src[..4].copy_from_slice(&inks);
|
||||
}
|
||||
if let Some(a) = a_idx {
|
||||
src[a] = b.color[3];
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user