From 63824b8305f929fdbca1775e606e130d1b04247c Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Sat, 19 Aug 2023 01:05:03 +0530 Subject: [PATCH 01/19] [wip]feat: implement Color Overlay node's base logic --- .../document_node_types.rs | 49 +++++++++++++++++++ .../node_properties.rs | 8 +++ 2 files changed, 57 insertions(+) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 66487425374..2c0b3fcbd7e 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2214,6 +2214,55 @@ fn static_nodes() -> Vec { properties: node_properties::index_node_properties, ..Default::default() }, + DocumentNodeType { + name: "Color Overlay", + category: "Image Adjustments", + identifier: NodeImplementation::DocumentNode(NodeNetwork { + inputs: vec![0, 1, 2, 3], // todo: pass equal no. of inputs to node and inner network + outputs: vec![NodeOutput::new(1, 0)], // todo: figure out what this value should be + nodes: [ + DocumentNode { + name: "Identity".to_string(), + inputs: vec![NodeInput::Network(concrete!(ImageFrame))], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")), + ..Default::default() + }, + DocumentNode { + name: "Color".to_string(), + inputs: vec![NodeInput::Network(concrete!(ImageFrame))], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")), + ..Default::default() + }, + DocumentNode { + name: "Blend".to_string(), + inputs: vec![NodeInput::Network(concrete!(ImageFrame))], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::BlendNode")), + ..Default::default() + }, + DocumentNode { + name: "Opacity".to_string(), + inputs: vec![NodeInput::Network(concrete!(ImageFrame))], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::OpacityNode")), + ..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), + DocumentInputType::value("Color", TaggedValue::OptionalColor(Some(Color::BLACK)), false), + DocumentInputType::value("Blend Mode", TaggedValue::BlendMode(BlendMode::Normal), false), + DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), + ], + outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], + properties: node_properties::color_overlay, + ..Default::default() + }, ] } diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index ed30ca2d389..5fb2b8a782f 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1938,3 +1938,11 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte }; vec![location, dimensions, background, clip] } + +pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); + let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); + let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); + + vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] +} From f374de0eb9223fcec9a340b7f6d3fc5a62d15c86 Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Sat, 19 Aug 2023 23:53:22 +0530 Subject: [PATCH 02/19] [wip]feat: attempt implementing node --- .../document_node_types.rs | 14 +++++++++----- .../node_graph_message_handler/node_properties.rs | 15 ++++++++++++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 2c0b3fcbd7e..448bbd9247b 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2218,8 +2218,8 @@ fn static_nodes() -> Vec { name: "Color Overlay", category: "Image Adjustments", identifier: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 1, 2, 3], // todo: pass equal no. of inputs to node and inner network - outputs: vec![NodeOutput::new(1, 0)], // todo: figure out what this value should be + inputs: vec![0, 1], + outputs: vec![NodeOutput::new(0, 0), NodeOutput::new(0, 0)], nodes: [ DocumentNode { name: "Identity".to_string(), @@ -2245,6 +2245,12 @@ fn static_nodes() -> Vec { implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::OpacityNode")), ..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() @@ -2254,10 +2260,8 @@ fn static_nodes() -> Vec { ..Default::default() }), inputs: vec![ - DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true), + DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false), DocumentInputType::value("Color", TaggedValue::OptionalColor(Some(Color::BLACK)), false), - DocumentInputType::value("Blend Mode", TaggedValue::BlendMode(BlendMode::Normal), false), - DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), ], outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], properties: node_properties::color_overlay, diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 5fb2b8a782f..9a9cf6a8f46 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1939,10 +1939,19 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte vec![location, dimensions, background, clip] } +// pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { +// let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); +// let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); +// let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); + +// vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] +// } + pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); - let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); - let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); + // let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); + // let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); - vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] + // vec![] + vec![color] } From 4ee8829fb457fd62558e2d5364d17656240a142f Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Sun, 20 Aug 2023 22:18:47 +0530 Subject: [PATCH 03/19] feat: implement naive node logic - this needs to accommodate coloring the image --- .../document_node_types.rs | 32 +++++++++---------- .../node_properties.rs | 15 ++------- 2 files changed, 18 insertions(+), 29 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 448bbd9247b..3895af4bf7c 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2218,8 +2218,10 @@ fn static_nodes() -> Vec { name: "Color Overlay", category: "Image Adjustments", identifier: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 1], - outputs: vec![NodeOutput::new(0, 0), NodeOutput::new(0, 0)], + // this maps node inputs to the document nodes that will consume them + inputs: vec![0, 1, 2, 2, 2], + // this maps to the outputs from the document nodes + outputs: vec![NodeOutput::new(2, 0)], nodes: [ DocumentNode { name: "Identity".to_string(), @@ -2229,28 +2231,21 @@ fn static_nodes() -> Vec { }, DocumentNode { name: "Color".to_string(), - inputs: vec![NodeInput::Network(concrete!(ImageFrame))], + inputs: vec![NodeInput::Network(concrete!(Color))], implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")), ..Default::default() }, DocumentNode { name: "Blend".to_string(), - inputs: vec![NodeInput::Network(concrete!(ImageFrame))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::BlendNode")), - ..Default::default() - }, - DocumentNode { - name: "Opacity".to_string(), - inputs: vec![NodeInput::Network(concrete!(ImageFrame))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::OpacityNode")), + inputs: vec![ + NodeInput::node(0, 0), + NodeInput::Network(concrete!(ImageFrame)), + NodeInput::Network(concrete!(BlendMode)), + NodeInput::Network(concrete!(f32)), + ], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>")), ..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() @@ -2262,6 +2257,9 @@ fn static_nodes() -> Vec { inputs: vec![ DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false), DocumentInputType::value("Color", TaggedValue::OptionalColor(Some(Color::BLACK)), false), + DocumentInputType::value("Second", TaggedValue::ImageFrame(ImageFrame::empty()), true), + DocumentInputType::value("Blend Mode", TaggedValue::BlendMode(BlendMode::Normal), false), + DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), ], outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], properties: node_properties::color_overlay, diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 9a9cf6a8f46..773f8e3d2fd 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1939,19 +1939,10 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte vec![location, dimensions, background, clip] } -// pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { -// let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); -// let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); -// let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); - -// vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] -// } - pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); - // let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); - // let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); + let blend_mode = blend_mode(document_node, node_id, 3, "Blend Mode", true); + let opacity = number_widget(document_node, node_id, 4, "Opacity", NumberInput::default().percentage(), true); - // vec![] - vec![color] + vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] } From 153220ec7b777ddbba7bfbe920472cba349dabd8 Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Mon, 21 Aug 2023 23:09:31 +0530 Subject: [PATCH 04/19] [wip]feat: attempt implementing ColorFillNode --- .../document_node_types.rs | 38 ++++++++++++++++ .../node_properties.rs | 5 +++ node-graph/gcore/src/raster/adjustments.rs | 44 ++++++++++++++++++- .../interpreted-executor/src/node_registry.rs | 1 + 4 files changed, 87 insertions(+), 1 deletion(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 3895af4bf7c..ee1bd0e8196 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2214,7 +2214,45 @@ fn static_nodes() -> Vec { properties: node_properties::index_node_properties, ..Default::default() }, + // applies the given color to each pixel of an image DocumentNodeType { + name: "ColorFillNode", + category: "Image Adjustments", + // identifier: NodeImplementation::proto("graphene_core::raster::adjustments::ColorFillNode<_>"), + identifier: NodeImplementation::DocumentNode(NodeNetwork { + inputs: vec![0, 1], + outputs: vec![NodeOutput::new(1, 0)], + nodes: [ + DocumentNode { + name: "Identity".to_string(), + inputs: vec![NodeInput::Network(concrete!(ImageFrame))], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")), + ..Default::default() + }, + DocumentNode { + name: "ColorFillNode".to_string(), + // NodeInput::node(1, 0) + inputs: vec![NodeInput::Network(concrete!(ImageFrame)), NodeInput::Network(concrete!(Color))], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::raster::adjustments::ColorFillNode<_>")), + ..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), + DocumentInputType::value("Solid Color", TaggedValue::Color(Color::BLACK), false), + ], + outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], + properties: node_properties::color_fill_node, + ..Default::default() + }, + DocumentNodeType { + // TODO: add the colorfill node implementation to the network and feed it the image from the network name: "Color Overlay", category: "Image Adjustments", identifier: NodeImplementation::DocumentNode(NodeNetwork { diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 773f8e3d2fd..3943df55527 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1946,3 +1946,8 @@ pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &m vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] } + +pub fn color_fill_node(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); + vec![color] +} diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 5f424536dc1..c06cfeb066a 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -1,7 +1,9 @@ #![allow(clippy::too_many_arguments)] use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode}; -use super::{Channel, Color, Node}; +use super::{Channel, Color, Image, ImageFrame, Node, Pixel}; + +use std::marker::PhantomData; use bezier_rs::{Bezier, TValue}; use dyn_any::{DynAny, StaticType}; @@ -926,6 +928,46 @@ fn generate_curves<_Channel: Channel + super::Linear>(_primary: (), curve: Curve ValueMapperNode::new(lut) } +#[derive(Debug, Clone)] +pub struct ColorFillNode { + // * main input (core generic type input for the node might need to be an ImageFrame<_p>) + color: C, +} + +#[node_macro::node_fn(ColorFillNode)] +pub fn color_fill_node(mut image_frame: ImageFrame, color: Color) -> ImageFrame { + // let mut image = &image_frame.image; + // let v = &image.data; + + // warn!("color vec len: {}", &v.len()); + // warn!("image h: {}, w: {}", &image.height, &image.width); + + // for mut data in &image.data { + // data = &color.clone() + // } + + let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize); + let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize); + + let mut image = Image { + width: target_width as u32, + height: target_height as u32, + data: Vec::with_capacity(target_width * target_height), + }; + + // let color_pixel = color.to_bytes(); + + // for x in 0..target_height { + // for y in 0..target_width { + // // image.data.push(color.clone()) + // } + // } + + image_frame.image = image; + image_frame + // image_frame +} + #[cfg(feature = "alloc")] pub use index_node::IndexNode; diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index 484568c6cd1..8f139a78353 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -428,6 +428,7 @@ fn node_registry() -> HashMap, params: [f32, f32, f32, f32, f32]), register_node!(graphene_std::image_segmentation::ImageSegmentationNode<_>, input: ImageFrame, params: [ImageFrame]), register_node!(graphene_core::raster::IndexNode<_>, input: Vec>, params: [u32]), + register_node!(graphene_core::raster::adjustments::ColorFillNode<_>, input: ImageFrame, params: [Color]), vec![( NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>"), |args| { From 5ae7abc2fb904ff44a6d8611b2b8cc9cd0ff504f Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Tue, 22 Aug 2023 14:20:51 +0530 Subject: [PATCH 05/19] fix: color fill node implementation path --- .../node_graph_message_handler/document_node_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index ee1bd0e8196..faefc38ed11 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2233,7 +2233,7 @@ fn static_nodes() -> Vec { name: "ColorFillNode".to_string(), // NodeInput::node(1, 0) inputs: vec![NodeInput::Network(concrete!(ImageFrame)), NodeInput::Network(concrete!(Color))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_std::raster::adjustments::ColorFillNode<_>")), + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::adjustments::ColorFillNode<_>")), ..Default::default() }, ] From de8d8d1cf194813b9aad1f9cfc8b08a72c872766 Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Tue, 22 Aug 2023 11:46:37 +0200 Subject: [PATCH 06/19] Simplify document node definition --- .../document_node_types.rs | 26 +------------------ 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index faefc38ed11..fb9c417fe55 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2218,31 +2218,7 @@ fn static_nodes() -> Vec { DocumentNodeType { name: "ColorFillNode", category: "Image Adjustments", - // identifier: NodeImplementation::proto("graphene_core::raster::adjustments::ColorFillNode<_>"), - identifier: NodeImplementation::DocumentNode(NodeNetwork { - inputs: vec![0, 1], - outputs: vec![NodeOutput::new(1, 0)], - nodes: [ - DocumentNode { - name: "Identity".to_string(), - inputs: vec![NodeInput::Network(concrete!(ImageFrame))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")), - ..Default::default() - }, - DocumentNode { - name: "ColorFillNode".to_string(), - // NodeInput::node(1, 0) - inputs: vec![NodeInput::Network(concrete!(ImageFrame)), NodeInput::Network(concrete!(Color))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::adjustments::ColorFillNode<_>")), - ..Default::default() - }, - ] - .into_iter() - .enumerate() - .map(|(id, node)| (id as NodeId, node)) - .collect(), - ..Default::default() - }), + identifier: NodeImplementation::proto("graphene_core::raster::adjustments::ColorFillNode<_>"), inputs: vec![ DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true), DocumentInputType::value("Solid Color", TaggedValue::Color(Color::BLACK), false), From 9c0479c3a176269f60bd0eb1150dd3be741ad8dd Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Tue, 22 Aug 2023 22:46:00 +0530 Subject: [PATCH 07/19] [wip]feat: implement ColorFillNode - correct the node implementation logic -[wip]use node in Color Overlay node network --- .../document_node_types.rs | 11 +++--- node-graph/gcore/src/raster/adjustments.rs | 34 +++++++------------ 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index fb9c417fe55..950aeac0abd 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2228,7 +2228,6 @@ fn static_nodes() -> Vec { ..Default::default() }, DocumentNodeType { - // TODO: add the colorfill node implementation to the network and feed it the image from the network name: "Color Overlay", category: "Image Adjustments", identifier: NodeImplementation::DocumentNode(NodeNetwork { @@ -2244,15 +2243,15 @@ fn static_nodes() -> Vec { ..Default::default() }, DocumentNode { - name: "Color".to_string(), - inputs: vec![NodeInput::Network(concrete!(Color))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")), + name: "ColorFillNode".to_string(), + inputs: vec![NodeInput::node(0, 0), NodeInput::Network(concrete!(Color))], + implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::adjustments::ColorFillNode<_>")), ..Default::default() }, DocumentNode { name: "Blend".to_string(), inputs: vec![ - NodeInput::node(0, 0), + NodeInput::node(1, 0), NodeInput::Network(concrete!(ImageFrame)), NodeInput::Network(concrete!(BlendMode)), NodeInput::Network(concrete!(f32)), @@ -2270,7 +2269,7 @@ fn static_nodes() -> Vec { }), inputs: vec![ DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false), - DocumentInputType::value("Color", TaggedValue::OptionalColor(Some(Color::BLACK)), false), + DocumentInputType::value("Color", TaggedValue::Color(Color::BLACK), true), DocumentInputType::value("Second", TaggedValue::ImageFrame(ImageFrame::empty()), true), DocumentInputType::value("Blend Mode", TaggedValue::BlendMode(BlendMode::Normal), false), DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index c06cfeb066a..696dacb244b 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -935,37 +935,29 @@ pub struct ColorFillNode { } #[node_macro::node_fn(ColorFillNode)] -pub fn color_fill_node(mut image_frame: ImageFrame, color: Color) -> ImageFrame { - // let mut image = &image_frame.image; - // let v = &image.data; - - // warn!("color vec len: {}", &v.len()); - // warn!("image h: {}, w: {}", &image.height, &image.width); - - // for mut data in &image.data { - // data = &color.clone() - // } - +pub fn color_fill_node(image_frame: ImageFrame, color: Color) -> ImageFrame { let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize); let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize); + warn!("h: {}, w: {}", target_height, target_width); + warn!("img pixel count: {}", target_height * target_width); + let mut image = Image { width: target_width as u32, height: target_height as u32, data: Vec::with_capacity(target_width * target_height), }; - // let color_pixel = color.to_bytes(); - - // for x in 0..target_height { - // for y in 0..target_width { - // // image.data.push(color.clone()) - // } - // } + for x in 0..target_height { + for y in 0..target_width { + image.data.push(color.clone()) + } + } - image_frame.image = image; - image_frame - // image_frame + ImageFrame { + transform: image_frame.transform, + image, + } } #[cfg(feature = "alloc")] From b48b8dda3612e4bfc9f945e962c65c3f6c53c3dd Mon Sep 17 00:00:00 2001 From: Dennis Kobert Date: Wed, 23 Aug 2023 09:37:33 +0200 Subject: [PATCH 08/19] Remove secondary image input --- .../node_graph_message_handler/document_node_types.rs | 7 +++---- .../node_graph_message_handler/node_properties.rs | 4 ++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 950aeac0abd..5b1cc9f22b6 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2232,7 +2232,7 @@ fn static_nodes() -> Vec { category: "Image Adjustments", identifier: NodeImplementation::DocumentNode(NodeNetwork { // this maps node inputs to the document nodes that will consume them - inputs: vec![0, 1, 2, 2, 2], + inputs: vec![0, 1, 2, 2], // this maps to the outputs from the document nodes outputs: vec![NodeOutput::new(2, 0)], nodes: [ @@ -2252,7 +2252,7 @@ fn static_nodes() -> Vec { name: "Blend".to_string(), inputs: vec![ NodeInput::node(1, 0), - NodeInput::Network(concrete!(ImageFrame)), + NodeInput::node(0, 0), NodeInput::Network(concrete!(BlendMode)), NodeInput::Network(concrete!(f32)), ], @@ -2268,9 +2268,8 @@ fn static_nodes() -> Vec { ..Default::default() }), inputs: vec![ - DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false), + DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true), DocumentInputType::value("Color", TaggedValue::Color(Color::BLACK), true), - DocumentInputType::value("Second", TaggedValue::ImageFrame(ImageFrame::empty()), true), DocumentInputType::value("Blend Mode", TaggedValue::BlendMode(BlendMode::Normal), false), DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), ], diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 3943df55527..302e9a45bda 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1941,8 +1941,8 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); - let blend_mode = blend_mode(document_node, node_id, 3, "Blend Mode", true); - let opacity = number_widget(document_node, node_id, 4, "Opacity", NumberInput::default().percentage(), true); + let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); + let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] } From ff8580a730bca536ab088decdc0d1ac146c0fb1b Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Wed, 23 Aug 2023 19:08:57 +0530 Subject: [PATCH 09/19] chore: perform cleanup and minor optimization - rename ColorFillNode node to Color Fill - remove unneeded clone method call --- .../node_graph_message_handler/document_node_types.rs | 4 ++-- .../node_graph_message_handler/node_properties.rs | 10 +++++----- node-graph/gcore/src/raster/adjustments.rs | 10 ++-------- 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 5b1cc9f22b6..2f5c6f092c1 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2216,7 +2216,7 @@ fn static_nodes() -> Vec { }, // applies the given color to each pixel of an image DocumentNodeType { - name: "ColorFillNode", + name: "Color Fill", category: "Image Adjustments", identifier: NodeImplementation::proto("graphene_core::raster::adjustments::ColorFillNode<_>"), inputs: vec![ @@ -2243,7 +2243,7 @@ fn static_nodes() -> Vec { ..Default::default() }, DocumentNode { - name: "ColorFillNode".to_string(), + name: "Color Fill".to_string(), inputs: vec![NodeInput::node(0, 0), NodeInput::Network(concrete!(Color))], implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::adjustments::ColorFillNode<_>")), ..Default::default() diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 302e9a45bda..979763f8e41 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1939,6 +1939,11 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte vec![location, dimensions, background, clip] } +pub fn color_fill_node(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { + let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); + vec![color] +} + pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); @@ -1946,8 +1951,3 @@ pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &m vec![color, blend_mode, LayoutGroup::Row { widgets: opacity }] } - -pub fn color_fill_node(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { - let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); - vec![color] -} diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 696dacb244b..32c8c61d151 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -1,9 +1,7 @@ #![allow(clippy::too_many_arguments)] use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode}; -use super::{Channel, Color, Image, ImageFrame, Node, Pixel}; - -use std::marker::PhantomData; +use super::{Channel, Color, Image, ImageFrame, Node}; use bezier_rs::{Bezier, TValue}; use dyn_any::{DynAny, StaticType}; @@ -930,7 +928,6 @@ fn generate_curves<_Channel: Channel + super::Linear>(_primary: (), curve: Curve #[derive(Debug, Clone)] pub struct ColorFillNode { - // * main input (core generic type input for the node might need to be an ImageFrame<_p>) color: C, } @@ -939,9 +936,6 @@ pub fn color_fill_node(image_frame: ImageFrame, color: Color) -> ImageFra let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize); let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize); - warn!("h: {}, w: {}", target_height, target_width); - warn!("img pixel count: {}", target_height * target_width); - let mut image = Image { width: target_width as u32, height: target_height as u32, @@ -950,7 +944,7 @@ pub fn color_fill_node(image_frame: ImageFrame, color: Color) -> ImageFra for x in 0..target_height { for y in 0..target_width { - image.data.push(color.clone()) + image.data.push(color) } } From 394dc4044cce74040355689643e3d6fcdb11591c Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Thu, 24 Aug 2023 23:02:42 +0530 Subject: [PATCH 10/19] refactor: optimize node logic and hide optional params --- .../document_node_types.rs | 6 +++--- node-graph/gcore/src/raster/adjustments.rs | 16 ++++------------ 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 2f5c6f092c1..4763ae76f91 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2251,8 +2251,8 @@ fn static_nodes() -> Vec { DocumentNode { name: "Blend".to_string(), inputs: vec![ - NodeInput::node(1, 0), NodeInput::node(0, 0), + NodeInput::node(1, 0), NodeInput::Network(concrete!(BlendMode)), NodeInput::Network(concrete!(f32)), ], @@ -2268,8 +2268,8 @@ fn static_nodes() -> Vec { ..Default::default() }), inputs: vec![ - DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true), - DocumentInputType::value("Color", TaggedValue::Color(Color::BLACK), true), + DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false), + DocumentInputType::value("Color", TaggedValue::Color(Color::BLACK), false), DocumentInputType::value("Blend Mode", TaggedValue::BlendMode(BlendMode::Normal), false), DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), ], diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 32c8c61d151..1a9e907bdf9 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -1,7 +1,7 @@ #![allow(clippy::too_many_arguments)] use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode}; -use super::{Channel, Color, Image, ImageFrame, Node}; +use super::{Channel, Color, ImageFrame, Node}; use bezier_rs::{Bezier, TValue}; use dyn_any::{DynAny, StaticType}; @@ -936,21 +936,13 @@ pub fn color_fill_node(image_frame: ImageFrame, color: Color) -> ImageFra let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize); let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize); - let mut image = Image { - width: target_width as u32, - height: target_height as u32, - data: Vec::with_capacity(target_width * target_height), - }; - - for x in 0..target_height { - for y in 0..target_width { - image.data.push(color) - } + for mut pixel in &image_frame.image.data { + pixel = &color; } ImageFrame { transform: image_frame.transform, - image, + image: image_frame.image, } } From 412cc7e10e7b36125909d332a7cc8f281771e19e Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Fri, 25 Aug 2023 01:32:37 +0530 Subject: [PATCH 11/19] fix: color fill implementation - fix broken color fill implementation logic - add alpha multiplication data to the image --- node-graph/gcore/src/raster/adjustments.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 1a9e907bdf9..aa5bb888211 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -1,7 +1,7 @@ #![allow(clippy::too_many_arguments)] use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode}; -use super::{Channel, Color, ImageFrame, Node}; +use super::{Channel, Color, ImageFrame, Node, RGBMut}; use bezier_rs::{Bezier, TValue}; use dyn_any::{DynAny, StaticType}; @@ -11,6 +11,7 @@ use core::fmt::Debug; use serde::{Deserialize, Serialize}; #[cfg(target_arch = "spirv")] use spirv_std::num_traits::float::Float; +use std::collections::HashSet; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "std", derive(specta::Type))] @@ -932,12 +933,15 @@ pub struct ColorFillNode { } #[node_macro::node_fn(ColorFillNode)] -pub fn color_fill_node(image_frame: ImageFrame, color: Color) -> ImageFrame { +pub fn color_fill_node(mut image_frame: ImageFrame, color: Color) -> ImageFrame { let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize); let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize); - for mut pixel in &image_frame.image.data { - pixel = &color; + for pixel in &mut image_frame.image.data { + pixel.set_red(color.r()); + pixel.set_blue(color.b()); + pixel.set_green(color.g()); + pixel.alpha_multiply(color); } ImageFrame { From 0b8f663b6b17fa65a5fb9f1790f9c7f65471941c Mon Sep 17 00:00:00 2001 From: 0hypercube <0hypercube@gmail.com> Date: Fri, 25 Aug 2023 08:58:31 +0100 Subject: [PATCH 12/19] Fix colour overlay node --- .../document_node_types.rs | 40 +------------------ node-graph/gcore/src/raster/adjustments.rs | 39 +++++++++++++----- .../interpreted-executor/src/node_registry.rs | 1 + 3 files changed, 32 insertions(+), 48 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 4763ae76f91..3d4d20a1674 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2230,45 +2230,9 @@ fn static_nodes() -> Vec { DocumentNodeType { name: "Color Overlay", category: "Image Adjustments", - identifier: NodeImplementation::DocumentNode(NodeNetwork { - // this maps node inputs to the document nodes that will consume them - inputs: vec![0, 1, 2, 2], - // this maps to the outputs from the document nodes - outputs: vec![NodeOutput::new(2, 0)], - nodes: [ - DocumentNode { - name: "Identity".to_string(), - inputs: vec![NodeInput::Network(concrete!(ImageFrame))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::ops::IdNode")), - ..Default::default() - }, - DocumentNode { - name: "Color Fill".to_string(), - inputs: vec![NodeInput::node(0, 0), NodeInput::Network(concrete!(Color))], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::adjustments::ColorFillNode<_>")), - ..Default::default() - }, - DocumentNode { - name: "Blend".to_string(), - inputs: vec![ - NodeInput::node(0, 0), - NodeInput::node(1, 0), - NodeInput::Network(concrete!(BlendMode)), - NodeInput::Network(concrete!(f32)), - ], - implementation: DocumentNodeImplementation::Unresolved(NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>")), - ..Default::default() - }, - ] - .into_iter() - .enumerate() - .map(|(id, node)| (id as NodeId, node)) - .collect(), - - ..Default::default() - }), + identifier: NodeImplementation::proto("graphene_core::raster::adjustments::ColorOverlayNode<_, _, _>"), inputs: vec![ - DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), false), + DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true), DocumentInputType::value("Color", TaggedValue::Color(Color::BLACK), false), DocumentInputType::value("Blend Mode", TaggedValue::BlendMode(BlendMode::Normal), false), DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index aa5bb888211..34155fb25f2 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -416,9 +416,8 @@ fn blend_node(input: (Color, Color), blend_mode: BlendMode, opacity: f32) -> Col blend_colors(input.0, input.1, blend_mode, opacity / 100.) } -#[inline(always)] -pub fn blend_colors(foreground: Color, background: Color, blend_mode: BlendMode, opacity: f32) -> Color { - let target_color = match blend_mode { +pub fn apply_blend_mode(foreground: Color, background: Color, blend_mode: BlendMode) -> Color { + match blend_mode { // Normal group BlendMode::Normal => background.blend_rgb(foreground, Color::blend_normal), // Darken group @@ -451,10 +450,19 @@ pub fn blend_colors(foreground: Color, background: Color, blend_mode: BlendMode, BlendMode::Saturation => background.blend_saturation(foreground), BlendMode::Color => background.blend_color(foreground), BlendMode::Luminosity => background.blend_luminosity(foreground), - // Other utility blend modes (hidden from the normal list) + // Other utility blend modes (hidden from the normal list) - do not have alpha blend + _ => panic!("Used blend mode without alpha blend"), + } +} + +#[inline(always)] +pub fn blend_colors(foreground: Color, background: Color, blend_mode: BlendMode, opacity: f32) -> Color { + let target_color = match blend_mode { + // Other utility blend modes (hidden from the normal list) - do not have alpha blend BlendMode::Erase => return background.alpha_subtract(foreground), BlendMode::Restore => return background.alpha_add(foreground), BlendMode::MultiplyAlpha => return background.alpha_multiply(foreground), + blend_mode => apply_blend_mode(foreground, background, blend_mode), }; background.alpha_blend(target_color.to_associated_alpha(opacity)) @@ -934,9 +942,6 @@ pub struct ColorFillNode { #[node_macro::node_fn(ColorFillNode)] pub fn color_fill_node(mut image_frame: ImageFrame, color: Color) -> ImageFrame { - let target_width = (image_frame.transform.transform_vector2((1., 0.).into()).length() as usize).min(image_frame.image.width as usize); - let target_height = (image_frame.transform.transform_vector2((0., 1.).into()).length() as usize).min(image_frame.image.height as usize); - for pixel in &mut image_frame.image.data { pixel.set_red(color.r()); pixel.set_blue(color.b()); @@ -944,10 +949,24 @@ pub fn color_fill_node(mut image_frame: ImageFrame, color: Color) -> Imag pixel.alpha_multiply(color); } - ImageFrame { - transform: image_frame.transform, - image: image_frame.image, + image_frame +} + +pub struct ColorOverlayNode { + color: Color, + blend_mode: BlendMode, + opacity: Opacity, +} + +#[node_macro::node_fn(ColorOverlayNode)] +pub fn color_overlay_node(mut image: ImageFrame, color: Color, blend_mode: BlendMode, opacity: f32) -> ImageFrame { + let opacity = (opacity / 100.).clamp(0., 1.); + for pixel in &mut image.image.data { + let image = pixel.map_rgb(|channel| channel * (1. - opacity)); + let overlay = color.map_rgb(|channel| channel * opacity); + *pixel = Color::from_rgbaf32(image.r() + overlay.r(), image.g() + overlay.g(), image.b() + overlay.b(), pixel.a()).unwrap(); } + image } #[cfg(feature = "alloc")] diff --git a/node-graph/interpreted-executor/src/node_registry.rs b/node-graph/interpreted-executor/src/node_registry.rs index 8f139a78353..2b98b02705c 100644 --- a/node-graph/interpreted-executor/src/node_registry.rs +++ b/node-graph/interpreted-executor/src/node_registry.rs @@ -429,6 +429,7 @@ fn node_registry() -> HashMap, input: ImageFrame, params: [ImageFrame]), register_node!(graphene_core::raster::IndexNode<_>, input: Vec>, params: [u32]), register_node!(graphene_core::raster::adjustments::ColorFillNode<_>, input: ImageFrame, params: [Color]), + register_node!(graphene_core::raster::adjustments::ColorOverlayNode<_, _, _>, input: ImageFrame, params: [Color, BlendMode, f32]), vec![( NodeIdentifier::new("graphene_core::raster::BlendNode<_, _, _, _>"), |args| { From 4a4459836130c0e31e5066615588d16aaffb24ca Mon Sep 17 00:00:00 2001 From: 0hypercube <0hypercube@gmail.com> Date: Fri, 25 Aug 2023 10:02:52 +0100 Subject: [PATCH 13/19] Blend mode --- node-graph/gcore/src/raster/adjustments.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 34155fb25f2..fe4faa45418 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -963,7 +963,7 @@ pub fn color_overlay_node(mut image: ImageFrame, color: Color, blend_mode let opacity = (opacity / 100.).clamp(0., 1.); for pixel in &mut image.image.data { let image = pixel.map_rgb(|channel| channel * (1. - opacity)); - let overlay = color.map_rgb(|channel| channel * opacity); + let overlay = apply_blend_mode(color, *pixel, blend_mode).map_rgb(|channel| channel * opacity); *pixel = Color::from_rgbaf32(image.r() + overlay.r(), image.g() + overlay.g(), image.b() + overlay.b(), pixel.a()).unwrap(); } image From bc7f069cdfd63ac7eb633af86fff52a86e9216a8 Mon Sep 17 00:00:00 2001 From: Dhruv Ahuja Date: Sun, 27 Aug 2023 18:34:02 +0530 Subject: [PATCH 14/19] chore: remove unused import --- node-graph/gcore/src/raster/adjustments.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index fe4faa45418..0a6e3585760 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -11,7 +11,6 @@ use core::fmt::Debug; use serde::{Deserialize, Serialize}; #[cfg(target_arch = "spirv")] use spirv_std::num_traits::float::Float; -use std::collections::HashSet; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[cfg_attr(feature = "std", derive(specta::Type))] From 106790ec612e9788c7ff8aa4fc06afa6c4676864 Mon Sep 17 00:00:00 2001 From: 0hypercube <0hypercube@gmail.com> Date: Mon, 28 Aug 2023 18:00:01 +0100 Subject: [PATCH 15/19] Debug logging for overlay --- .../document/document_message_handler.rs | 8 +++ .../src/components/panels/Document.svelte | 8 +++ node-graph/gcore/Cargo.toml | 1 + node-graph/gcore/src/raster/adjustments.rs | 49 ++++++++++++++++++- node-graph/gcore/src/raster/image.rs | 11 +++++ 5 files changed, 75 insertions(+), 2 deletions(-) diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index cbb97587cbf..a79bff6a7c0 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -591,6 +591,14 @@ impl MessageHandler { let image_size = DVec2::new(image.width as f64, image.height as f64); + // Log a pixel of the pasted image after it has been converted to 0..=1 and linear by `Color::from_rgba8_srgb` + use graphene_core::raster::Raster; + info!( + "Paste image {image_size} pixel[200,200] after Color::from_rgba8_srgb = {:?} (between 0-255 = {:?})", + image.get_pixel(200, 200), + image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) + ); + let Some(image_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Image") else { warn!("Image node should be in registry"); return; diff --git a/frontend/src/components/panels/Document.svelte b/frontend/src/components/panels/Document.svelte index 47236f69677..e3f8564f95e 100644 --- a/frontend/src/components/panels/Document.svelte +++ b/frontend/src/components/panels/Document.svelte @@ -92,6 +92,14 @@ if (file?.type.startsWith("image")) { const imageData = await extractPixelData(file); + // Debug log some of the pixel values from the canvas (each 4 bytes is one pixel, each row is encoded from top to bottom) + //for (let y = 0; y < imageData.height; y += 20) { + //for (let x = 0; x < imageData.width; x += 20) { + const x = 200; + const y = 200; + console.info(`[${x}, ${y}] = (${imageData.data.slice((y * imageData.width + x) * 4, (y * imageData.width + x) * 4 + 4)}) after js rasterise on canvas pixel`); + + editor.instance.pasteImage(new Uint8Array(imageData.data), imageData.width, imageData.height, e.clientX, e.clientY); } }); diff --git a/node-graph/gcore/Cargo.toml b/node-graph/gcore/Cargo.toml index 020c12483e7..f08c8eae9cc 100644 --- a/node-graph/gcore/Cargo.toml +++ b/node-graph/gcore/Cargo.toml @@ -31,6 +31,7 @@ bytemuck = { version = "1.8", features = ["derive"] } async-trait = { version = "0.1", optional = true } serde = { version = "1.0", features = [ "derive", + "rc" ], optional = true, default-features = false } log = { version = "0.4", optional = true } diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 0a6e3585760..a9f8581a232 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -1,7 +1,7 @@ #![allow(clippy::too_many_arguments)] use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode}; -use super::{Channel, Color, ImageFrame, Node, RGBMut}; +use super::{Channel, Color, ImageFrame, Node, RGBMut, Raster}; use bezier_rs::{Bezier, TValue}; use dyn_any::{DynAny, StaticType}; @@ -959,15 +959,60 @@ pub struct ColorOverlayNode { #[node_macro::node_fn(ColorOverlayNode)] pub fn color_overlay_node(mut image: ImageFrame, color: Color, blend_mode: BlendMode, opacity: f32) -> ImageFrame { + info!( + "Before colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", + image.get_pixel(200, 200), + image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) + ); + let opacity = (opacity / 100.).clamp(0., 1.); for pixel in &mut image.image.data { let image = pixel.map_rgb(|channel| channel * (1. - opacity)); - let overlay = apply_blend_mode(color, *pixel, blend_mode).map_rgb(|channel| channel * opacity); + + // The apply blend mode function divides rgb by the alpha channel for the background. This undoes that. + let associated_pixel = Color::from_rgbaf32_unchecked(pixel.r() * pixel.a(), pixel.g() * pixel.a(), pixel.b() * pixel.a(), pixel.a()); + let overlay = apply_blend_mode(color, associated_pixel, blend_mode).map_rgb(|channel| channel * opacity); + *pixel = Color::from_rgbaf32(image.r() + overlay.r(), image.g() + overlay.g(), image.b() + overlay.b(), pixel.a()).unwrap(); } + + info!( + "After colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", + image.get_pixel(200, 200), + image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) + ); + image } +#[test] +fn color_overlay_multiply() { + use crate::raster::Image; + use crate::value::ClonedNode; + + let image_color = Color::from_rgbaf32_unchecked(0.7, 0.6, 0.5, 0.4); + let image = ImageFrame { + image: Image::new(1, 1, image_color), + ..Default::default() + }; + + // Color { red: 0., green: 1., blue: 0., alpha: 1. } + let overlay_color = Color::GREEN; + + // 100% of the output should come from the multiplied value + let opacity = 100_f32; + + let result = ColorOverlayNode { + color: ClonedNode(overlay_color), + blend_mode: ClonedNode(BlendMode::Multiply), + opacity: ClonedNode(opacity), + } + .eval(image); + + // The output should just be the original green and alpha channels (as we multiply them by 1 and other channels by 0) + assert_eq!(result.image.data[0], Color::from_rgbaf32_unchecked(0., image_color.g(), 0., image_color.a())); +} + #[cfg(feature = "alloc")] pub use index_node::IndexNode; diff --git a/node-graph/gcore/src/raster/image.rs b/node-graph/gcore/src/raster/image.rs index 7cd9a9dbea7..abd67b1f491 100644 --- a/node-graph/gcore/src/raster/image.rs +++ b/node-graph/gcore/src/raster/image.rs @@ -185,6 +185,17 @@ where result[i + 1] = last_g_srgb; result[i + 2] = last_b_srgb; result[i + 3] = (a * 255. + 0.5) as u8; + + if i == (200 * width as usize + 200) * 4 { + info!( + "Encoding pixel[200,200].\nValue = {:?} (0-255 {:?})\ndivide by alpha = {:?} (0-255 = {:?})\nfloat_to_srgb_u8 = {:?}", + (color.r().to_f32(), color.g().to_f32(), color.b().to_f32(), color.a().to_f32()), + (color.r().to_f32() * 255., color.g().to_f32() * 255., color.b().to_f32() * 255., color.a().to_f32() * 255.), + (r, g, b, a), + (r * 255., g * 255., b * 255., a * 255.), + (last_r_srgb, last_g_srgb, last_b_srgb, (a * 255. + 0.5) as u8) + ) + } } i += 4; From 9195e87052a15ae1d1be26e12211452b83553e1d Mon Sep 17 00:00:00 2001 From: 0hypercube <0hypercube@gmail.com> Date: Tue, 29 Aug 2023 21:44:54 +0100 Subject: [PATCH 16/19] Use premultiplied alpha --- node-graph/gcore/src/raster/color.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/node-graph/gcore/src/raster/color.rs b/node-graph/gcore/src/raster/color.rs index 4abc15ce895..f4df08d11aa 100644 --- a/node-graph/gcore/src/raster/color.rs +++ b/node-graph/gcore/src/raster/color.rs @@ -336,14 +336,16 @@ impl Color { /// ``` #[inline(always)] pub fn from_rgba8_srgb(red: u8, green: u8, blue: u8, alpha: u8) -> Color { + let alpha = alpha as f32 / 255.; let map_range = |int_color| int_color as f32 / 255.0; Color { red: map_range(red), green: map_range(green), blue: map_range(blue), - alpha: map_range(alpha), + alpha, } .to_linear_srgb() + .map_rgb(|channel| channel * alpha) } /// Create a [Color] from a hue, saturation, lightness and alpha (all between 0 and 1) From 0e59b8a81aafd90275966a02d82759552fd92680 Mon Sep 17 00:00:00 2001 From: 0hypercube <0hypercube@gmail.com> Date: Wed, 30 Aug 2023 09:57:42 +0100 Subject: [PATCH 17/19] Comment out logging --- .../document/document_message_handler.rs | 15 +++++++------ .../src/components/panels/Document.svelte | 10 ++++----- node-graph/gcore/src/raster/adjustments.rs | 22 ++++++++++--------- node-graph/gcore/src/raster/image.rs | 21 +++++++++--------- 4 files changed, 36 insertions(+), 32 deletions(-) diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index a79bff6a7c0..5165426d3e0 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -591,13 +591,14 @@ impl MessageHandler { let image_size = DVec2::new(image.width as f64, image.height as f64); - // Log a pixel of the pasted image after it has been converted to 0..=1 and linear by `Color::from_rgba8_srgb` - use graphene_core::raster::Raster; - info!( - "Paste image {image_size} pixel[200,200] after Color::from_rgba8_srgb = {:?} (between 0-255 = {:?})", - image.get_pixel(200, 200), - image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) - ); + // All the image's pixels have been converted to 0..=1, linear and premultiplied by `Color::from_rgba8_srgb` + // Log a pixels + // use graphene_core::raster::Raster; + // info!( + // "Paste image {image_size} pixel[200,200] after Color::from_rgba8_srgb = {:?} (between 0-255 = {:?})", + // image.get_pixel(200, 200), + // image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) + // ); let Some(image_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Image") else { warn!("Image node should be in registry"); diff --git a/frontend/src/components/panels/Document.svelte b/frontend/src/components/panels/Document.svelte index e3f8564f95e..c358888765a 100644 --- a/frontend/src/components/panels/Document.svelte +++ b/frontend/src/components/panels/Document.svelte @@ -93,11 +93,11 @@ const imageData = await extractPixelData(file); // Debug log some of the pixel values from the canvas (each 4 bytes is one pixel, each row is encoded from top to bottom) - //for (let y = 0; y < imageData.height; y += 20) { - //for (let x = 0; x < imageData.width; x += 20) { - const x = 200; - const y = 200; - console.info(`[${x}, ${y}] = (${imageData.data.slice((y * imageData.width + x) * 4, (y * imageData.width + x) * 4 + 4)}) after js rasterise on canvas pixel`); + // for (let y = 0; y < imageData.height; y += 20) { + // for (let x = 0; x < imageData.width; x += 20) { + // const x = 200;R + // const y = 200; + // console.info(`[${x}, ${y}] = (${imageData.data.slice((y * imageData.width + x) * 4, (y * imageData.width + x) * 4 + 4)}) after js rasterise on canvas pixel`); editor.instance.pasteImage(new Uint8Array(imageData.data), imageData.width, imageData.height, e.clientX, e.clientY); diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index a9f8581a232..87cabfdc622 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -959,11 +959,12 @@ pub struct ColorOverlayNode { #[node_macro::node_fn(ColorOverlayNode)] pub fn color_overlay_node(mut image: ImageFrame, color: Color, blend_mode: BlendMode, opacity: f32) -> ImageFrame { - info!( - "Before colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", - image.get_pixel(200, 200), - image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) - ); + // Log the colour + // info!( + // "Before colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", + // image.get_pixel(200, 200), + // image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) + // ); let opacity = (opacity / 100.).clamp(0., 1.); for pixel in &mut image.image.data { @@ -976,11 +977,12 @@ pub fn color_overlay_node(mut image: ImageFrame, color: Color, blend_mode *pixel = Color::from_rgbaf32(image.r() + overlay.r(), image.g() + overlay.g(), image.b() + overlay.b(), pixel.a()).unwrap(); } - info!( - "After colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", - image.get_pixel(200, 200), - image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) - ); + // Log the colour + // info!( + // "After colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", + // image.get_pixel(200, 200), + // image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) + // ); image } diff --git a/node-graph/gcore/src/raster/image.rs b/node-graph/gcore/src/raster/image.rs index abd67b1f491..225f96f924e 100644 --- a/node-graph/gcore/src/raster/image.rs +++ b/node-graph/gcore/src/raster/image.rs @@ -186,16 +186,17 @@ where result[i + 2] = last_b_srgb; result[i + 3] = (a * 255. + 0.5) as u8; - if i == (200 * width as usize + 200) * 4 { - info!( - "Encoding pixel[200,200].\nValue = {:?} (0-255 {:?})\ndivide by alpha = {:?} (0-255 = {:?})\nfloat_to_srgb_u8 = {:?}", - (color.r().to_f32(), color.g().to_f32(), color.b().to_f32(), color.a().to_f32()), - (color.r().to_f32() * 255., color.g().to_f32() * 255., color.b().to_f32() * 255., color.a().to_f32() * 255.), - (r, g, b, a), - (r * 255., g * 255., b * 255., a * 255.), - (last_r_srgb, last_g_srgb, last_b_srgb, (a * 255. + 0.5) as u8) - ) - } + // Log a pixel as it is exported + // if i == (200 * width as usize + 200) * 4 { + // info!( + // "Encoding pixel[200,200].\nValue = {:?} (0-255 {:?})\ndivide by alpha = {:?} (0-255 = {:?})\nfloat_to_srgb_u8 = {:?}", + // (color.r().to_f32(), color.g().to_f32(), color.b().to_f32(), color.a().to_f32()), + // (color.r().to_f32() * 255., color.g().to_f32() * 255., color.b().to_f32() * 255., color.a().to_f32() * 255.), + // (r, g, b, a), + // (r * 255., g * 255., b * 255., a * 255.), + // (last_r_srgb, last_g_srgb, last_b_srgb, (a * 255. + 0.5) as u8) + // ); + // } } i += 4; From 629a257d94dccea3472d2c1bf4a2bc6d768dd4ed Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Sat, 2 Sep 2023 02:13:38 -0700 Subject: [PATCH 18/19] Code review nits --- .../node_graph_message_handler/document_node_types.rs | 10 +++++----- .../node_graph_message_handler/node_properties.rs | 6 +++--- node-graph/gcore/src/raster/adjustments.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs index 3d4d20a1674..58df47a10e7 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/document_node_types.rs @@ -2211,20 +2211,20 @@ fn static_nodes() -> Vec { DocumentInputType::value("Index", TaggedValue::U32(0), false), ], outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], - properties: node_properties::index_node_properties, + properties: node_properties::index_properties, ..Default::default() }, - // applies the given color to each pixel of an image + // Applies the given color to each pixel of an image but maintains the alpha value DocumentNodeType { name: "Color Fill", category: "Image Adjustments", identifier: NodeImplementation::proto("graphene_core::raster::adjustments::ColorFillNode<_>"), inputs: vec![ DocumentInputType::value("Image", TaggedValue::ImageFrame(ImageFrame::empty()), true), - DocumentInputType::value("Solid Color", TaggedValue::Color(Color::BLACK), false), + DocumentInputType::value("Color", TaggedValue::Color(Color::BLACK), false), ], outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], - properties: node_properties::color_fill_node, + properties: node_properties::color_fill_properties, ..Default::default() }, DocumentNodeType { @@ -2238,7 +2238,7 @@ fn static_nodes() -> Vec { DocumentInputType::value("Opacity", TaggedValue::F32(100.), false), ], outputs: vec![DocumentOutputType::new("Image", FrontendGraphDataType::Raster)], - properties: node_properties::color_overlay, + properties: node_properties::color_overlay_properties, ..Default::default() }, ] diff --git a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs index 979763f8e41..0b094942c02 100644 --- a/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs +++ b/editor/src/messages/portfolio/document/node_graph/node_graph_message_handler/node_properties.rs @@ -1810,7 +1810,7 @@ pub fn no_properties(_document_node: &DocumentNode, _node_id: NodeId, _context: string_properties("Node has no properties") } -pub fn index_node_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { +pub fn index_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let index = number_widget(document_node, node_id, 1, "Index", NumberInput::default().min(0.), true); vec![LayoutGroup::Row { widgets: index }] @@ -1939,12 +1939,12 @@ pub fn artboard_properties(document_node: &DocumentNode, node_id: NodeId, _conte vec![location, dimensions, background, clip] } -pub fn color_fill_node(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { +pub fn color_fill_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); vec![color] } -pub fn color_overlay(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { +pub fn color_overlay_properties(document_node: &DocumentNode, node_id: NodeId, _context: &mut NodePropertiesContext) -> Vec { let color = color_widget(document_node, node_id, 1, "Color", ColorInput::default(), true); let blend_mode = blend_mode(document_node, node_id, 2, "Blend Mode", true); let opacity = number_widget(document_node, node_id, 3, "Opacity", NumberInput::default().percentage(), true); diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 87cabfdc622..03cf5ffcc6f 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -1,7 +1,7 @@ #![allow(clippy::too_many_arguments)] use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode}; -use super::{Channel, Color, ImageFrame, Node, RGBMut, Raster}; +use super::{Channel, Color, ImageFrame, Node, RGBMut}; use bezier_rs::{Bezier, TValue}; use dyn_any::{DynAny, StaticType}; @@ -922,7 +922,7 @@ fn generate_curves<_Channel: Channel + super::Linear>(_primary: (), curve: Curve bezier.find_tvalues_for_x(x) .next() .map(|t| bezier.evaluate(TValue::Parametric(t.clamp(0., 1.))).y) - // a very bad approximation if bezier_rs failes + // Fall back to a very bad approximation if Bezier-rs fails .unwrap_or_else(|| (x - x0) / (x3 - x0) * (y3 - y0) + y0) }; lut[index] = _Channel::from_f64(y); From 3545623f2a1ba36bb93e5342405e1fbc847c62c2 Mon Sep 17 00:00:00 2001 From: Keavon Chambers Date: Sat, 2 Sep 2023 02:13:50 -0700 Subject: [PATCH 19/19] Remove color debug logging --- .../portfolio/document/document_message_handler.rs | 11 ++--------- frontend/src/components/panels/Document.svelte | 8 -------- node-graph/gcore/Cargo.toml | 1 - node-graph/gcore/src/raster/adjustments.rs | 14 -------------- node-graph/gcore/src/raster/image.rs | 12 ------------ 5 files changed, 2 insertions(+), 44 deletions(-) diff --git a/editor/src/messages/portfolio/document/document_message_handler.rs b/editor/src/messages/portfolio/document/document_message_handler.rs index 5165426d3e0..38d21345c1c 100644 --- a/editor/src/messages/portfolio/document/document_message_handler.rs +++ b/editor/src/messages/portfolio/document/document_message_handler.rs @@ -589,16 +589,9 @@ impl MessageHandler { - let image_size = DVec2::new(image.width as f64, image.height as f64); + // All the image's pixels have been converted to 0..=1, linear, and premultiplied by `Color::from_rgba8_srgb` - // All the image's pixels have been converted to 0..=1, linear and premultiplied by `Color::from_rgba8_srgb` - // Log a pixels - // use graphene_core::raster::Raster; - // info!( - // "Paste image {image_size} pixel[200,200] after Color::from_rgba8_srgb = {:?} (between 0-255 = {:?})", - // image.get_pixel(200, 200), - // image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) - // ); + let image_size = DVec2::new(image.width as f64, image.height as f64); let Some(image_node_type) = crate::messages::portfolio::document::node_graph::resolve_document_node_type("Image") else { warn!("Image node should be in registry"); diff --git a/frontend/src/components/panels/Document.svelte b/frontend/src/components/panels/Document.svelte index c358888765a..47236f69677 100644 --- a/frontend/src/components/panels/Document.svelte +++ b/frontend/src/components/panels/Document.svelte @@ -92,14 +92,6 @@ if (file?.type.startsWith("image")) { const imageData = await extractPixelData(file); - // Debug log some of the pixel values from the canvas (each 4 bytes is one pixel, each row is encoded from top to bottom) - // for (let y = 0; y < imageData.height; y += 20) { - // for (let x = 0; x < imageData.width; x += 20) { - // const x = 200;R - // const y = 200; - // console.info(`[${x}, ${y}] = (${imageData.data.slice((y * imageData.width + x) * 4, (y * imageData.width + x) * 4 + 4)}) after js rasterise on canvas pixel`); - - editor.instance.pasteImage(new Uint8Array(imageData.data), imageData.width, imageData.height, e.clientX, e.clientY); } }); diff --git a/node-graph/gcore/Cargo.toml b/node-graph/gcore/Cargo.toml index f08c8eae9cc..020c12483e7 100644 --- a/node-graph/gcore/Cargo.toml +++ b/node-graph/gcore/Cargo.toml @@ -31,7 +31,6 @@ bytemuck = { version = "1.8", features = ["derive"] } async-trait = { version = "0.1", optional = true } serde = { version = "1.0", features = [ "derive", - "rc" ], optional = true, default-features = false } log = { version = "0.4", optional = true } diff --git a/node-graph/gcore/src/raster/adjustments.rs b/node-graph/gcore/src/raster/adjustments.rs index 03cf5ffcc6f..54f9cbb7912 100644 --- a/node-graph/gcore/src/raster/adjustments.rs +++ b/node-graph/gcore/src/raster/adjustments.rs @@ -959,13 +959,6 @@ pub struct ColorOverlayNode { #[node_macro::node_fn(ColorOverlayNode)] pub fn color_overlay_node(mut image: ImageFrame, color: Color, blend_mode: BlendMode, opacity: f32) -> ImageFrame { - // Log the colour - // info!( - // "Before colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", - // image.get_pixel(200, 200), - // image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) - // ); - let opacity = (opacity / 100.).clamp(0., 1.); for pixel in &mut image.image.data { let image = pixel.map_rgb(|channel| channel * (1. - opacity)); @@ -977,13 +970,6 @@ pub fn color_overlay_node(mut image: ImageFrame, color: Color, blend_mode *pixel = Color::from_rgbaf32(image.r() + overlay.r(), image.g() + overlay.g(), image.b() + overlay.b(), pixel.a()).unwrap(); } - // Log the colour - // info!( - // "After colour overlay pixel[200,200] = {:?} (between 0-255 = {:?})", - // image.get_pixel(200, 200), - // image.get_pixel(200, 200).map(|color| (color.r() * 255., color.g() * 255., color.b() * 255., color.a() * 255.)) - // ); - image } diff --git a/node-graph/gcore/src/raster/image.rs b/node-graph/gcore/src/raster/image.rs index 225f96f924e..7cd9a9dbea7 100644 --- a/node-graph/gcore/src/raster/image.rs +++ b/node-graph/gcore/src/raster/image.rs @@ -185,18 +185,6 @@ where result[i + 1] = last_g_srgb; result[i + 2] = last_b_srgb; result[i + 3] = (a * 255. + 0.5) as u8; - - // Log a pixel as it is exported - // if i == (200 * width as usize + 200) * 4 { - // info!( - // "Encoding pixel[200,200].\nValue = {:?} (0-255 {:?})\ndivide by alpha = {:?} (0-255 = {:?})\nfloat_to_srgb_u8 = {:?}", - // (color.r().to_f32(), color.g().to_f32(), color.b().to_f32(), color.a().to_f32()), - // (color.r().to_f32() * 255., color.g().to_f32() * 255., color.b().to_f32() * 255., color.a().to_f32() * 255.), - // (r, g, b, a), - // (r * 255., g * 255., b * 255., a * 255.), - // (last_r_srgb, last_g_srgb, last_b_srgb, (a * 255. + 0.5) as u8) - // ); - // } } i += 4;