mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-12-23 10:11:54 +00:00
Add alpha to Extract Channel node and remove Extract Alpha node (#1731)
* add `TaggedValue::RedGreenBlueAlpha` * add alpha to `ExtractChannelNode` * remove `ExtractAlphaNode` from `Split Channels` * remove `ExtractAlphaNode`
This commit is contained in:
parent
438c45eb80
commit
3019cc7253
5 changed files with 70 additions and 33 deletions
|
|
@ -14,7 +14,7 @@ use graph_craft::imaginate_input::ImaginateSamplingMethod;
|
|||
use graph_craft::ProtoNodeIdentifier;
|
||||
use graphene_core::raster::brush_cache::BrushCache;
|
||||
use graphene_core::raster::{
|
||||
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, Image, ImageFrame, LuminanceCalculation, NoiseType, RedGreenBlue, RelativeAbsolute,
|
||||
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, Image, ImageFrame, LuminanceCalculation, NoiseType, RedGreenBlue, RedGreenBlueAlpha, RelativeAbsolute,
|
||||
SelectiveColorChoice,
|
||||
};
|
||||
use graphene_core::text::Font;
|
||||
|
|
@ -867,20 +867,12 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
implementation: DocumentNodeImplementation::proto("graphene_core::raster::ExtractChannelNode<_>"),
|
||||
inputs: vec![
|
||||
DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
DocumentInputType::value("From", TaggedValue::RedGreenBlue(RedGreenBlue::Red), false),
|
||||
DocumentInputType::value("From", TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Red), false),
|
||||
],
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
properties: node_properties::extract_channel_properties,
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
name: "Extract Alpha",
|
||||
category: "Image Adjustments",
|
||||
implementation: DocumentNodeImplementation::proto("graphene_core::raster::ExtractAlphaNode<>"),
|
||||
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true)],
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNodeDefinition {
|
||||
name: "Extract Opaque",
|
||||
category: "Image Adjustments",
|
||||
|
|
@ -912,26 +904,26 @@ fn static_nodes() -> Vec<DocumentNodeDefinition> {
|
|||
},
|
||||
DocumentNode {
|
||||
name: "RedNode".to_string(),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Red), false)],
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Red), false)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "GreenNode".to_string(),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Green), false)],
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Green), false)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "BlueNode".to_string(),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Blue), false)],
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Blue), false)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "AlphaNode".to_string(),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::raster::ExtractAlphaNode<>")),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::value(TaggedValue::RedGreenBlueAlpha(RedGreenBlueAlpha::Alpha), false)],
|
||||
implementation: DocumentNodeImplementation::ProtoNode(ProtoNodeIdentifier::new("graphene_core::raster::ExtractChannelNode<>")),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ use graph_craft::document::{DocumentNode, NodeId, NodeInput};
|
|||
use graph_craft::imaginate_input::{ImaginateSamplingMethod, ImaginateServerStatus, ImaginateStatus};
|
||||
use graphene_core::memo::IORecord;
|
||||
use graphene_core::raster::{
|
||||
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, ImageFrame, LuminanceCalculation, NoiseType, RedGreenBlue, RelativeAbsolute, SelectiveColorChoice,
|
||||
BlendMode, CellularDistanceFunction, CellularReturnType, Color, DomainWarpType, FractalType, ImageFrame, LuminanceCalculation, NoiseType, RedGreenBlue, RedGreenBlueAlpha, RelativeAbsolute,
|
||||
SelectiveColorChoice,
|
||||
};
|
||||
use graphene_core::text::Font;
|
||||
use graphene_core::vector::style::{FillType, GradientType, LineCap, LineJoin};
|
||||
|
|
@ -400,6 +401,33 @@ fn color_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, na
|
|||
LayoutGroup::Row { widgets }.with_tooltip("Color Channel")
|
||||
}
|
||||
|
||||
fn rgba_channel(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
|
||||
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
|
||||
if let &NodeInput::Value {
|
||||
tagged_value: TaggedValue::RedGreenBlueAlpha(mode),
|
||||
exposed: false,
|
||||
} = &document_node.inputs[index]
|
||||
{
|
||||
let calculation_modes = [RedGreenBlueAlpha::Red, RedGreenBlueAlpha::Green, RedGreenBlueAlpha::Blue, RedGreenBlueAlpha::Alpha];
|
||||
let mut entries = Vec::with_capacity(calculation_modes.len());
|
||||
for method in calculation_modes {
|
||||
entries.push(
|
||||
MenuListEntry::new(format!("{method:?}"))
|
||||
.label(method.to_string())
|
||||
.on_update(update_value(move |_| TaggedValue::RedGreenBlueAlpha(method), node_id, index))
|
||||
.on_commit(commit_value),
|
||||
);
|
||||
}
|
||||
let entries = vec![entries];
|
||||
|
||||
widgets.extend_from_slice(&[
|
||||
Separator::new(SeparatorType::Unrelated).widget_holder(),
|
||||
DropdownInput::new(entries).selected_index(Some(mode as u32)).widget_holder(),
|
||||
]);
|
||||
}
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Color Channel")
|
||||
}
|
||||
|
||||
// TODO Generalize this instead of using a separate function per dropdown menu enum
|
||||
fn noise_type(document_node: &DocumentNode, node_id: NodeId, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
|
||||
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
|
||||
|
|
@ -971,7 +999,7 @@ pub fn insert_channel_properties(document_node: &DocumentNode, node_id: NodeId,
|
|||
}
|
||||
|
||||
pub fn extract_channel_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let color_channel = color_channel(document_node, node_id, 1, "From", true);
|
||||
let color_channel = rgba_channel(document_node, node_id, 1, "From", true);
|
||||
|
||||
vec![color_channel]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -256,22 +256,14 @@ pub struct ExtractChannelNode<TargetChannel> {
|
|||
}
|
||||
|
||||
#[node_macro::node_fn(ExtractChannelNode)]
|
||||
fn extract_channel_node(color: Color, channel: RedGreenBlue) -> Color {
|
||||
fn extract_channel_node(color: Color, channel: RedGreenBlueAlpha) -> Color {
|
||||
let extracted_value = match channel {
|
||||
RedGreenBlue::Red => color.r(),
|
||||
RedGreenBlue::Green => color.g(),
|
||||
RedGreenBlue::Blue => color.b(),
|
||||
RedGreenBlueAlpha::Red => color.r(),
|
||||
RedGreenBlueAlpha::Green => color.g(),
|
||||
RedGreenBlueAlpha::Blue => color.b(),
|
||||
RedGreenBlueAlpha::Alpha => color.a(),
|
||||
};
|
||||
color.map_rgb(|_| extracted_value)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
pub struct ExtractAlphaNode;
|
||||
|
||||
#[node_macro::node_fn(ExtractAlphaNode)]
|
||||
fn extract_alpha_node(color: Color) -> Color {
|
||||
let alpha = color.a();
|
||||
Color::from_rgbaf32(alpha, alpha, alpha, 1.).unwrap()
|
||||
color.map_rgba(|_| extracted_value)
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Default)]
|
||||
|
|
@ -606,6 +598,27 @@ impl core::fmt::Display for RedGreenBlue {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, DynAny)]
|
||||
pub enum RedGreenBlueAlpha {
|
||||
Red,
|
||||
Green,
|
||||
Blue,
|
||||
Alpha,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for RedGreenBlueAlpha {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
RedGreenBlueAlpha::Red => write!(f, "Red"),
|
||||
RedGreenBlueAlpha::Green => write!(f, "Green"),
|
||||
RedGreenBlueAlpha::Blue => write!(f, "Blue"),
|
||||
RedGreenBlueAlpha::Alpha => write!(f, "Alpha"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[cfg_attr(feature = "std", derive(specta::Type))]
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, DynAny)]
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ pub enum TaggedValue {
|
|||
VecF64(Vec<f64>),
|
||||
VecDVec2(Vec<DVec2>),
|
||||
RedGreenBlue(graphene_core::raster::RedGreenBlue),
|
||||
RedGreenBlueAlpha(graphene_core::raster::RedGreenBlueAlpha),
|
||||
NoiseType(graphene_core::raster::NoiseType),
|
||||
FractalType(graphene_core::raster::FractalType),
|
||||
CellularDistanceFunction(graphene_core::raster::CellularDistanceFunction),
|
||||
|
|
@ -114,6 +115,7 @@ impl Hash for TaggedValue {
|
|||
Self::VecF64(x) => x.iter().for_each(|val| val.to_bits().hash(state)),
|
||||
Self::VecDVec2(x) => x.iter().for_each(|val| val.to_array().iter().for_each(|x| x.to_bits().hash(state))),
|
||||
Self::RedGreenBlue(x) => x.hash(state),
|
||||
Self::RedGreenBlueAlpha(x) => x.hash(state),
|
||||
Self::NoiseType(x) => x.hash(state),
|
||||
Self::FractalType(x) => x.hash(state),
|
||||
Self::CellularDistanceFunction(x) => x.hash(state),
|
||||
|
|
@ -189,6 +191,7 @@ impl<'a> TaggedValue {
|
|||
TaggedValue::VecF64(x) => Box::new(x),
|
||||
TaggedValue::VecDVec2(x) => Box::new(x),
|
||||
TaggedValue::RedGreenBlue(x) => Box::new(x),
|
||||
TaggedValue::RedGreenBlueAlpha(x) => Box::new(x),
|
||||
TaggedValue::NoiseType(x) => Box::new(x),
|
||||
TaggedValue::FractalType(x) => Box::new(x),
|
||||
TaggedValue::CellularDistanceFunction(x) => Box::new(x),
|
||||
|
|
@ -266,6 +269,7 @@ impl<'a> TaggedValue {
|
|||
TaggedValue::VecF64(_) => concrete!(Vec<f64>),
|
||||
TaggedValue::VecDVec2(_) => concrete!(Vec<DVec2>),
|
||||
TaggedValue::RedGreenBlue(_) => concrete!(graphene_core::raster::RedGreenBlue),
|
||||
TaggedValue::RedGreenBlueAlpha(_) => concrete!(graphene_core::raster::RedGreenBlueAlpha),
|
||||
TaggedValue::NoiseType(_) => concrete!(graphene_core::raster::NoiseType),
|
||||
TaggedValue::FractalType(_) => concrete!(graphene_core::raster::FractalType),
|
||||
TaggedValue::CellularDistanceFunction(_) => concrete!(graphene_core::raster::CellularDistanceFunction),
|
||||
|
|
@ -330,6 +334,7 @@ impl<'a> TaggedValue {
|
|||
x if x == TypeId::of::<Vec<f64>>() => Ok(TaggedValue::VecF64(*downcast(input).unwrap())),
|
||||
x if x == TypeId::of::<Vec<DVec2>>() => Ok(TaggedValue::VecDVec2(*downcast(input).unwrap())),
|
||||
x if x == TypeId::of::<graphene_core::raster::RedGreenBlue>() => Ok(TaggedValue::RedGreenBlue(*downcast(input).unwrap())),
|
||||
x if x == TypeId::of::<graphene_core::raster::RedGreenBlueAlpha>() => Ok(TaggedValue::RedGreenBlueAlpha(*downcast(input).unwrap())),
|
||||
x if x == TypeId::of::<graphene_core::raster::NoiseType>() => Ok(TaggedValue::NoiseType(*downcast(input).unwrap())),
|
||||
x if x == TypeId::of::<graphene_core::raster::FractalType>() => Ok(TaggedValue::FractalType(*downcast(input).unwrap())),
|
||||
x if x == TypeId::of::<graphene_core::raster::CellularDistanceFunction>() => Ok(TaggedValue::CellularDistanceFunction(*downcast(input).unwrap())),
|
||||
|
|
|
|||
|
|
@ -451,8 +451,7 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, HashMap<NodeIOTypes, NodeCons
|
|||
async_node!(graphene_std::brush::BrushNode<_, _, _>, input: ImageFrame<Color>, output: ImageFrame<Color>, params: [ImageFrame<Color>, Vec<BrushStroke>, BrushCache]),
|
||||
// Filters
|
||||
raster_node!(graphene_core::raster::LuminanceNode<_>, params: [LuminanceCalculation]),
|
||||
raster_node!(graphene_core::raster::ExtractChannelNode<_>, params: [RedGreenBlue]),
|
||||
raster_node!(graphene_core::raster::ExtractAlphaNode<>, params: []),
|
||||
raster_node!(graphene_core::raster::ExtractChannelNode<_>, params: [RedGreenBlueAlpha]),
|
||||
raster_node!(graphene_core::raster::ExtractOpaqueNode<>, params: []),
|
||||
raster_node!(graphene_core::raster::LevelsNode<_, _, _, _, _>, params: [f64, f64, f64, f64, f64]),
|
||||
register_node!(graphene_std::image_segmentation::ImageSegmentationNode<_>, input: ImageFrame<Color>, params: [ImageFrame<Color>]),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue