mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-18 07:48:02 +08:00
Introduce Split/Combine Channels nodes (#1153)
* Add Channel Extrataction Node * Add hacky BlendModes for Inserting Color Channels * Fix Channel Exporter * Add Monochrome Option and Multi Output Node * Fix Input Mapping * Fix Formatting * Split Alpha Extraction to seperate node * Remove unnecessary functionality * Add Alpha Channel as an output to the extract channel node * Fix compilation * Add unpolished 'Combine Channels' Node * Fix Rebasing Issues * Add a bit of polish * Fix Rebase Issues * Switch from 'ColorChannel' to 'RedGreenBlue' I initially added an enum to hold color channels called 'ColorChannel', but while implementing the nodes, there somebody allready added a similar enum so I switched to that type * Add correct names * Add Improvement - Some Performance Improvements - Some Formatting Improvements * Add some improvements Most of this stuff was done by TrueDoctor in my Luchbreak :D * Implement IO Improvements - Converted primary output from split node to a dummy output - Removed primary Input from split node * Fix Formatting * Fix Combine RGB Node (hopefully final :D ) * Swap around Inputs and Outputs Move from ARGB -> RGBA * Improve naming * More naming fixes * Fix Replace -> Into * Rename Replacment -> Insertion * Add blank assist area --------- Co-authored-by: Keavon Chambers <keavon@keavon.com> Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
@@ -371,6 +371,35 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
properties: node_properties::mask_properties,
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Insert Channel",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::InsertChannelNode<_, _, _, _>"),
|
||||
inputs: vec![
|
||||
DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
DocumentInputType::value("Insertion", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
DocumentInputType::value("Replace", TaggedValue::RedGreenBlue(RedGreenBlue::Red), false),
|
||||
],
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
properties: node_properties::insert_channel_properties,
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Combine Channels",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_std::raster::CombineChannelsNode"),
|
||||
inputs: vec![
|
||||
DocumentInputType::value("None", TaggedValue::None, false),
|
||||
DocumentInputType::value("Red", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
DocumentInputType::value("Green", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
DocumentInputType::value("Blue", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
DocumentInputType::value("Alpha", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
],
|
||||
outputs: vec![DocumentOutputType {
|
||||
name: "Image",
|
||||
data_type: FrontendGraphDataType::Raster,
|
||||
}],
|
||||
properties: node_properties::no_properties,
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Blend",
|
||||
category: "Image Adjustments",
|
||||
@@ -483,6 +512,86 @@ fn static_nodes() -> Vec<DocumentNodeType> {
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
properties: node_properties::luminance_properties,
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Extract Channel",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_core::raster::ExtractChannelNode<_>"),
|
||||
inputs: vec![
|
||||
DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true),
|
||||
DocumentInputType::value("From", TaggedValue::RedGreenBlue(RedGreenBlue::Red), false),
|
||||
],
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
properties: node_properties::extract_channel_properties,
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Extract Alpha",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::proto("graphene_core::raster::ExtractAlphaNode<>"),
|
||||
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true)],
|
||||
outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)],
|
||||
properties: node_properties::no_properties,
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Split Channels",
|
||||
category: "Image Adjustments",
|
||||
identifier: NodeImplementation::DocumentNode(NodeNetwork {
|
||||
inputs: vec![0],
|
||||
outputs: vec![NodeOutput::new(4, 0), NodeOutput::new(1, 0), NodeOutput::new(2, 0), NodeOutput::new(3, 0), NodeOutput::new(4, 0)],
|
||||
nodes: [
|
||||
DocumentNode {
|
||||
name: "Identity".to_string(),
|
||||
inputs: vec![NodeInput::Network(concrete!(ImageFrame<Color>))],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "RedNode".to_string(),
|
||||
inputs: vec![NodeInput::node(0, 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Red), false)],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "GreenNode".to_string(),
|
||||
inputs: vec![NodeInput::node(0, 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Green), false)],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "BlueNode".to_string(),
|
||||
inputs: vec![NodeInput::node(0, 0), NodeInput::value(TaggedValue::RedGreenBlue(RedGreenBlue::Blue), false)],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::ExtractChannelNode<_>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "AlphaNode".to_string(),
|
||||
inputs: vec![NodeInput::node(0, 0)],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::ExtractAlphaNode<>")),
|
||||
..Default::default()
|
||||
},
|
||||
DocumentNode {
|
||||
name: "EmptyOutput".to_string(),
|
||||
inputs: vec![NodeInput::value(TaggedValue::ImageFrame(ImageFrame::empty()), false)],
|
||||
implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(id, node)| (id as NodeId, node))
|
||||
.collect(),
|
||||
|
||||
..Default::default()
|
||||
}),
|
||||
inputs: vec![DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true)],
|
||||
outputs: vec![
|
||||
DocumentOutputType::new("Empty", FrontendGraphDataType::Raster),
|
||||
DocumentOutputType::new("Red", FrontendGraphDataType::Raster),
|
||||
DocumentOutputType::new("Green", FrontendGraphDataType::Raster),
|
||||
DocumentOutputType::new("Blue", FrontendGraphDataType::Raster),
|
||||
DocumentOutputType::new("Alpha", FrontendGraphDataType::Raster),
|
||||
],
|
||||
properties: node_properties::no_properties,
|
||||
},
|
||||
DocumentNodeType {
|
||||
name: "Gaussian Blur",
|
||||
category: "Image Filters",
|
||||
|
||||
@@ -231,6 +231,26 @@ fn number_widget(document_node: &DocumentNode, node_id: NodeId, index: usize, na
|
||||
widgets
|
||||
}
|
||||
|
||||
//TODO Use generalized Version of this as soon as it's available
|
||||
fn color_channel(document_node: &DocumentNode, node_id: u64, 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::RedGreenBlue(mode),
|
||||
exposed: false,
|
||||
} = &document_node.inputs[index]
|
||||
{
|
||||
let calculation_modes = [RedGreenBlue::Red, RedGreenBlue::Green, RedGreenBlue::Blue];
|
||||
let mut entries = Vec::with_capacity(calculation_modes.len());
|
||||
for method in calculation_modes {
|
||||
entries.push(DropdownEntryData::new(method.to_string()).on_update(update_value(move |_| TaggedValue::RedGreenBlue(method), node_id, index)));
|
||||
}
|
||||
let entries = vec![entries];
|
||||
|
||||
widgets.extend_from_slice(&[WidgetHolder::unrelated_separator(), DropdownInput::new(entries).selected_index(Some(mode as u32)).widget_holder()]);
|
||||
}
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Color Channel")
|
||||
}
|
||||
|
||||
//TODO Use generalized Version of this as soon as it's available
|
||||
fn blend_mode(document_node: &DocumentNode, node_id: u64, index: usize, name: &str, blank_assist: bool) -> LayoutGroup {
|
||||
let mut widgets = start_widgets(document_node, node_id, index, name, FrontendGraphDataType::General, blank_assist);
|
||||
@@ -251,7 +271,7 @@ fn blend_mode(document_node: &DocumentNode, node_id: u64, index: usize, name: &s
|
||||
LayoutGroup::Row { widgets }.with_tooltip("Formula used for blending")
|
||||
}
|
||||
|
||||
// TODO: Generalize this for all dropdowns ( also see blend_mode )
|
||||
// TODO: Generalize this for all dropdowns ( also see blend_mode and channel_extration )
|
||||
fn luminance_calculation(document_node: &DocumentNode, node_id: u64, 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 {
|
||||
@@ -590,6 +610,18 @@ pub fn luminance_properties(document_node: &DocumentNode, node_id: NodeId, _cont
|
||||
vec![luminance_calc]
|
||||
}
|
||||
|
||||
pub fn insert_channel_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let color_channel = color_channel(document_node, node_id, 2, "Into", true);
|
||||
|
||||
vec![color_channel]
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
vec![color_channel]
|
||||
}
|
||||
|
||||
pub fn adjust_hsl_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec<LayoutGroup> {
|
||||
let hue_shift = number_widget(document_node, node_id, 1, "Hue Shift", NumberInput::default().min(-180.).max(180.).unit("°"), true);
|
||||
let saturation_shift = number_widget(document_node, node_id, 2, "Saturation Shift", NumberInput::default().min(-100.).max(100.).unit("%"), true);
|
||||
|
||||
Reference in New Issue
Block a user