mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2025-08-31 02:07:21 +00:00
Curves image adjustment node (#1214)
* Create ValueMapperNode and use it for brightness/contrast * move spline code into seperate module * Add GenerateCurvesNode * add a `LuminanceMut`-trait * add `lerp` to `Channel` * Add frontend code to handle the curves widget's inputs * Rename spline module to curve * Make messages in CurveInput pass * Improve curves widget design and fix sizing issue * Implement proper bezier handling * Use bezier_rs's intersections function instead of own cubic root solver * Debounce CurveInput events and change how debouncer works the first event issued to the debouncer was unneccessarily delayed. Instead now the debouncer fires it instantaneously but blocks events that come in until a timeout was reached. * Make curve editing more user friendly * Change code to use project terminology * sample -> manipulator group or manipulator * marker -> handle * Fix small documentation mistake in bezier-rs * Add find_tvalues_for_x function to bezier-rs also integrate the function into curves node * Add tests for find_tvalues_for_x in bezier-rs * Fix formatting * Revert BrightnessContrastNode changes * Frontend cleanup --------- Co-authored-by: Keavon Chambers <keavon@keavon.com> Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
parent
cfe38c6413
commit
dc4b16aead
29 changed files with 822 additions and 75 deletions
|
@ -476,6 +476,43 @@ fn node_registry() -> HashMap<NodeIdentifier, HashMap<NodeIOTypes, NodeConstruct
|
|||
},
|
||||
NodeIOTypes::new(concrete!(ImageFrame<Color>), concrete!(ImageFrame<Color>), vec![fn_type!(f32), fn_type!(f32), fn_type!(bool)]),
|
||||
)],
|
||||
vec![
|
||||
(
|
||||
NodeIdentifier::new("graphene_core::raster::CurvesNode<_>"),
|
||||
|args| {
|
||||
use graphene_core::raster::{curve::Curve, GenerateCurvesNode};
|
||||
let curve: DowncastBothNode<(), Curve> = DowncastBothNode::new(args[0].clone());
|
||||
Box::pin(async move {
|
||||
let curve = ClonedNode::new(curve.eval(()).await);
|
||||
|
||||
let generate_curves_node = GenerateCurvesNode::<f32, _>::new(curve);
|
||||
let map_image_frame_node = graphene_std::raster::MapImageNode::new(ValueNode::new(generate_curves_node.eval(())));
|
||||
let map_image_frame_node = FutureWrapperNode::new(map_image_frame_node);
|
||||
let any: DynAnyNode<ImageFrame<Luma>, _, _> = graphene_std::any::DynAnyNode::new(map_image_frame_node);
|
||||
any.into_type_erased()
|
||||
})
|
||||
},
|
||||
NodeIOTypes::new(concrete!(ImageFrame<Luma>), concrete!(ImageFrame<Luma>), vec![fn_type!(graphene_core::raster::curve::Curve)]),
|
||||
),
|
||||
// TODO: Use channel split and merge for this instead of using LuminanceMut for the whole color.
|
||||
(
|
||||
NodeIdentifier::new("graphene_core::raster::CurvesNode<_>"),
|
||||
|args| {
|
||||
use graphene_core::raster::{curve::Curve, GenerateCurvesNode};
|
||||
let curve: DowncastBothNode<(), Curve> = DowncastBothNode::new(args[0].clone());
|
||||
Box::pin(async move {
|
||||
let curve = ClonedNode::new(curve.eval(()).await);
|
||||
|
||||
let generate_curves_node = GenerateCurvesNode::<f32, _>::new(curve);
|
||||
let map_image_frame_node = graphene_std::raster::MapImageNode::new(ValueNode::new(generate_curves_node.eval(())));
|
||||
let map_image_frame_node = FutureWrapperNode::new(map_image_frame_node);
|
||||
let any: DynAnyNode<ImageFrame<Color>, _, _> = graphene_std::any::DynAnyNode::new(map_image_frame_node);
|
||||
any.into_type_erased()
|
||||
})
|
||||
},
|
||||
NodeIOTypes::new(concrete!(ImageFrame<Color>), concrete!(ImageFrame<Color>), vec![fn_type!(graphene_core::raster::curve::Curve)]),
|
||||
),
|
||||
],
|
||||
raster_node!(graphene_core::raster::OpacityNode<_>, params: [f32]),
|
||||
raster_node!(graphene_core::raster::PosterizeNode<_>, params: [f32]),
|
||||
raster_node!(graphene_core::raster::ExposureNode<_, _, _>, params: [f32, f32, f32]),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue