Curves: points outside 0..255 are refused, as the message says (#4868)
A point outside 0..255 was moved onto the edge without a word, while the error for bad points says they must be in 0..255; Photoshop refuses them too. The error also named the command twice-quoted (`adjustment `curves``); it is now `curves adjustment`. Fixes #4867
This commit is contained in:
parent
911881880d
commit
0bdaf905cc
|
|
@ -73,7 +73,7 @@ pub fn default_for(kind: &str, mode: ColorMode) -> Result<Adjustment> {
|
|||
/// None or of another kind). `mode` picks the Levels/Curves channel space when neither the params
|
||||
/// nor the base name one.
|
||||
pub fn from_params(kind: &str, p: &Value, base: Option<&Adjustment>, mode: ColorMode) -> Result<Adjustment> {
|
||||
let cmd = format!("adjustment `{kind}`");
|
||||
let cmd = format!("{kind} adjustment");
|
||||
if !p.is_object() && !p.is_null() {
|
||||
return Err(bad(&cmd, "params must be an object"));
|
||||
}
|
||||
|
|
@ -952,8 +952,10 @@ pub fn parse_curve(cmd: &str, key: &str, v: &Value) -> Result<Vec<CurvePoint>> {
|
|||
let mut pts = Vec::with_capacity(a.len());
|
||||
for q in a {
|
||||
let q = q.as_array().filter(|q| q.len() == 2).ok_or_else(err)?;
|
||||
let x = q.first().and_then(Value::as_f64).filter(|x| x.is_finite()).ok_or_else(err)?;
|
||||
let y = q.get(1).and_then(Value::as_f64).filter(|y| y.is_finite()).ok_or_else(err)?;
|
||||
// Like Photoshop, a point outside 0..255 is refused rather than moved onto the edge.
|
||||
let level = |v: Option<&Value>| v.and_then(Value::as_f64).filter(|v| (-1e-6..=255.0 + 1e-6).contains(v));
|
||||
let x = level(q.first()).ok_or_else(err)?;
|
||||
let y = level(q.get(1)).ok_or_else(err)?;
|
||||
pts.push(CurvePoint { input: (x as f32).clamp(0.0, 255.0) / 255.0, output: (y as f32).clamp(0.0, 255.0) / 255.0 });
|
||||
}
|
||||
pts.sort_by(|a, b| a.input.total_cmp(&b.input));
|
||||
|
|
@ -1212,6 +1214,17 @@ mod tests {
|
|||
assert!(matches!(a, Adjustment::Levels { master, .. } if master.in_white > master.in_black));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn curve_points_outside_0_255_are_refused_as_the_message_says() {
|
||||
// Photoshop refuses them too ("the settings in the file are invalid"); they used to be
|
||||
// moved onto the edge silently.
|
||||
for pts in [json!([[0, 0], [300, 255]]), json!([[0, -1], [255, 255]]), json!([[0, 0]])] {
|
||||
let e = from_params("curves", &json!({ "points": pts }), None, ColorMode::Rgb).unwrap_err().to_string();
|
||||
assert!(e.contains("[input, output] pairs in 0..255") && e.contains("`curves adjustment`"), "{e}");
|
||||
}
|
||||
assert!(from_params("curves", &json!({"points": [[0, 0], [128.5, 140], [255, 255]]}), None, ColorMode::Rgb).is_ok());
|
||||
}
|
||||
|
||||
fn curves_parts(a: &Adjustment) -> (&[CurvePoint], &[Vec<CurvePoint>; 3]) {
|
||||
match a {
|
||||
Adjustment::Curves { master, per_channel, .. } => (master, per_channel),
|
||||
|
|
|
|||
Loading…
Reference in New Issue