Skip to content

Commit 50e6253

Browse files
committed
graster-nodes: move black_and_white to separate mod due to needing Table<Color>
1 parent bfe7cd4 commit 50e6253

4 files changed

Lines changed: 96 additions & 83 deletions

File tree

editor/src/messages/portfolio/document_migration.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -330,8 +330,12 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
330330
aliases: &["graphene_core::raster::adjustments::LevelsNode", "graphene_core::raster::LevelsNode"],
331331
},
332332
NodeReplacement {
333-
node: graphene_std::raster_nodes::adjustments::black_and_white::IDENTIFIER,
334-
aliases: &["graphene_core::raster::adjustments::BlackAndWhiteNode", "graphene_core::raster::BlackAndWhiteNode"],
333+
node: graphene_std::raster_nodes::black_and_white::black_and_white::IDENTIFIER,
334+
aliases: &[
335+
"graphene_raster_nodes::adjustments::black_and_white::IDENTIFIER",
336+
"graphene_core::raster::adjustments::BlackAndWhiteNode",
337+
"graphene_core::raster::BlackAndWhiteNode",
338+
],
335339
},
336340
NodeReplacement {
337341
node: graphene_std::raster_nodes::adjustments::hue_saturation::IDENTIFIER,

node-graph/graster-nodes/src/adjustments.rs

Lines changed: 0 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -297,87 +297,6 @@ fn levels<T: Adjust<Color>>(
297297
image
298298
}
299299

300-
// Aims for interoperable compatibility with:
301-
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27blwh%27%20%3D%20Black%20and%20White
302-
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Black%20White%20(Photoshop%20CS3)
303-
//
304-
// Algorithm from:
305-
// https://stackoverflow.com/a/55233732/775283
306-
// Works the same for gamma and linear color
307-
#[node_macro::node(name("Black & White"), category("Raster: Adjustment"), shader_node(PerPixelAdjust))]
308-
fn black_and_white<T: Adjust<Color>>(
309-
_: impl Ctx,
310-
#[implementations(
311-
Table<Raster<CPU>>,
312-
Table<Color>,
313-
Table<GradientStops>,
314-
GradientStops,
315-
)]
316-
#[gpu_image]
317-
mut image: T,
318-
#[default(Color::BLACK)] tint: Table<Color>,
319-
#[default(40.)]
320-
#[range((-200., 300.))]
321-
reds: PercentageF32,
322-
#[default(60.)]
323-
#[range((-200., 300.))]
324-
yellows: PercentageF32,
325-
#[default(40.)]
326-
#[range((-200., 300.))]
327-
greens: PercentageF32,
328-
#[default(60.)]
329-
#[range((-200., 300.))]
330-
cyans: PercentageF32,
331-
#[default(20.)]
332-
#[range((-200., 300.))]
333-
blues: PercentageF32,
334-
#[default(80.)]
335-
#[range((-200., 300.))]
336-
magentas: PercentageF32,
337-
) -> T {
338-
let tint: Option<Color> = tint.into();
339-
let tint = tint.unwrap_or(Color::BLACK);
340-
341-
image.adjust(|color| {
342-
let color = color.to_gamma_srgb();
343-
344-
let reds = reds as f32 / 100.;
345-
let yellows = yellows as f32 / 100.;
346-
let greens = greens as f32 / 100.;
347-
let cyans = cyans as f32 / 100.;
348-
let blues = blues as f32 / 100.;
349-
let magentas = magentas as f32 / 100.;
350-
351-
let gray_base = color.r().min(color.g()).min(color.b());
352-
353-
let red_part = color.r() - gray_base;
354-
let green_part = color.g() - gray_base;
355-
let blue_part = color.b() - gray_base;
356-
let alpha_part = color.a();
357-
358-
let additional = if red_part == 0. {
359-
let cyan_part = green_part.min(blue_part);
360-
cyan_part * cyans + (green_part - cyan_part) * greens + (blue_part - cyan_part) * blues
361-
} else if green_part == 0. {
362-
let magenta_part = red_part.min(blue_part);
363-
magenta_part * magentas + (red_part - magenta_part) * reds + (blue_part - magenta_part) * blues
364-
} else {
365-
let yellow_part = red_part.min(green_part);
366-
yellow_part * yellows + (red_part - yellow_part) * reds + (green_part - yellow_part) * greens
367-
};
368-
369-
let luminance = gray_base + additional;
370-
371-
// TODO: Fix "Color" blend mode implementation so it matches the expected behavior perfectly (it's currently close)
372-
let color = tint.with_luminance(luminance);
373-
374-
let color = Color::from_rgbaf32_unchecked(color.r(), color.g(), color.b(), alpha_part);
375-
376-
color.to_linear_srgb()
377-
});
378-
image
379-
}
380-
381300
// Aims for interoperable compatibility with:
382301
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27hue%20%27%20%3D%20Old,saturation%2C%20Photoshop%205.0
383302
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=0%20%3D%20Use%20other.-,Hue/Saturation,-Hue/Saturation%20settings
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
use crate::adjust::Adjust;
2+
use graphene_core::gradient::GradientStops;
3+
use graphene_core::raster_types::{CPU, Raster};
4+
use graphene_core::table::Table;
5+
use graphene_core_shaders::Ctx;
6+
use graphene_core_shaders::color::Color;
7+
use graphene_core_shaders::registry::types::PercentageF32;
8+
9+
// Aims for interoperable compatibility with:
10+
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=%27blwh%27%20%3D%20Black%20and%20White
11+
// https://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#:~:text=Black%20White%20(Photoshop%20CS3)
12+
//
13+
// Algorithm from:
14+
// https://stackoverflow.com/a/55233732/775283
15+
// Works the same for gamma and linear color
16+
#[node_macro::node(name("Black & White"), category("Raster: Adjustment"))]
17+
fn black_and_white<T: Adjust<Color>>(
18+
_: impl Ctx,
19+
#[implementations(
20+
Table<Raster<CPU>>,
21+
Table<Color>,
22+
Table<GradientStops>,
23+
GradientStops,
24+
)]
25+
#[gpu_image]
26+
mut image: T,
27+
#[default(Color::BLACK)] tint: Table<Color>,
28+
#[default(40.)]
29+
#[range((-200., 300.))]
30+
reds: PercentageF32,
31+
#[default(60.)]
32+
#[range((-200., 300.))]
33+
yellows: PercentageF32,
34+
#[default(40.)]
35+
#[range((-200., 300.))]
36+
greens: PercentageF32,
37+
#[default(60.)]
38+
#[range((-200., 300.))]
39+
cyans: PercentageF32,
40+
#[default(20.)]
41+
#[range((-200., 300.))]
42+
blues: PercentageF32,
43+
#[default(80.)]
44+
#[range((-200., 300.))]
45+
magentas: PercentageF32,
46+
) -> T {
47+
let tint: Option<Color> = tint.into();
48+
let tint = tint.unwrap_or(Color::BLACK);
49+
50+
image.adjust(|color| {
51+
let color = color.to_gamma_srgb();
52+
53+
let reds = reds as f32 / 100.;
54+
let yellows = yellows as f32 / 100.;
55+
let greens = greens as f32 / 100.;
56+
let cyans = cyans as f32 / 100.;
57+
let blues = blues as f32 / 100.;
58+
let magentas = magentas as f32 / 100.;
59+
60+
let gray_base = color.r().min(color.g()).min(color.b());
61+
62+
let red_part = color.r() - gray_base;
63+
let green_part = color.g() - gray_base;
64+
let blue_part = color.b() - gray_base;
65+
let alpha_part = color.a();
66+
67+
let additional = if red_part == 0. {
68+
let cyan_part = green_part.min(blue_part);
69+
cyan_part * cyans + (green_part - cyan_part) * greens + (blue_part - cyan_part) * blues
70+
} else if green_part == 0. {
71+
let magenta_part = red_part.min(blue_part);
72+
magenta_part * magentas + (red_part - magenta_part) * reds + (blue_part - magenta_part) * blues
73+
} else {
74+
let yellow_part = red_part.min(green_part);
75+
yellow_part * yellows + (red_part - yellow_part) * reds + (green_part - yellow_part) * greens
76+
};
77+
78+
let luminance = gray_base + additional;
79+
80+
// TODO: Fix "Color" blend mode implementation so it matches the expected behavior perfectly (it's currently close)
81+
let color = tint.with_luminance(luminance);
82+
83+
let color = Color::from_rgbaf32_unchecked(color.r(), color.g(), color.b(), alpha_part);
84+
85+
color.to_linear_srgb()
86+
});
87+
image
88+
}

node-graph/graster-nodes/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ pub use graphene_core_shaders::glam;
55

66
pub mod adjust;
77
pub mod adjustments;
8+
#[cfg(feature = "std")]
9+
pub mod black_and_white;
810
pub mod blending_nodes;
911
pub mod cubic_spline;
1012

0 commit comments

Comments
 (0)