Improve naming of nodes and 'add' menu styling

This commit is contained in:
Keavon Chambers 2022-12-03 23:29:55 -08:00
parent eb9848365f
commit 33d5db76c0
7 changed files with 109 additions and 104 deletions

View File

@ -40,7 +40,7 @@ pub struct DocumentNodeType {
static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
DocumentNodeType {
name: "Identity",
category: "Meta",
category: "General",
identifier: NodeIdentifier::new("graphene_core::ops::IdNode", &[Type::Concrete(Cow::Borrowed("Any<'_>"))]),
inputs: &[DocumentInputType {
name: "In",
@ -82,9 +82,9 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
properties: |_document_node, _node_id| node_properties::string_properties("The output to the graph is rendered in the frame".to_string()),
},
DocumentNodeType {
name: "Grayscale Image",
category: "Image Color Correction",
identifier: NodeIdentifier::new("graphene_std::raster::GrayscaleImageNode", &[]),
name: "Grayscale",
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::GrayscaleNode", &[]),
inputs: &[DocumentInputType {
name: "Image",
data_type: FrontendGraphDataType::Raster,
@ -94,9 +94,9 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
properties: node_properties::no_properties,
},
DocumentNodeType {
name: "Invert Image Color",
category: "Image Color Correction",
identifier: NodeIdentifier::new("graphene_std::raster::InvertImageColorNode", &[]),
name: "Invert RGB",
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::InvertRGBNode", &[]),
inputs: &[DocumentInputType {
name: "Image",
data_type: FrontendGraphDataType::Raster,
@ -106,9 +106,9 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
properties: node_properties::no_properties,
},
DocumentNodeType {
name: "Shift Image HSL",
category: "Image Color Correction",
identifier: NodeIdentifier::new("graphene_std::raster::ShiftImageHSLNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
name: "Hue/Saturation",
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::HueSaturationNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
inputs: &[
DocumentInputType {
name: "Image",
@ -126,7 +126,7 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
default: NodeInput::value(TaggedValue::F64(0.), false),
},
DocumentInputType {
name: "Luminance Shift",
name: "Lightness Shift",
data_type: FrontendGraphDataType::Number,
default: NodeInput::value(TaggedValue::F64(0.), false),
},
@ -135,9 +135,9 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
properties: node_properties::adjust_hsl_properties,
},
DocumentNodeType {
name: "Image Contrast and Brightness",
category: "Image Color Correction",
identifier: NodeIdentifier::new("graphene_std::raster::ImageBrightnessAndContrast", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
name: "Brightness/Contrast",
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::BrightnessContrastNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
inputs: &[
DocumentInputType {
name: "Image",
@ -159,9 +159,9 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
properties: node_properties::brighten_image_properties,
},
DocumentNodeType {
name: "Adjust Image Gamma",
category: "Image Color Correction",
identifier: NodeIdentifier::new("graphene_std::raster::ImageGammaNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
name: "Gamma",
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::GammaNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
inputs: &[
DocumentInputType {
name: "Image",
@ -178,9 +178,9 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
properties: node_properties::adjust_gamma_properties,
},
DocumentNodeType {
name: "Multiply Image Opactiy",
category: "Image Color Correction",
identifier: NodeIdentifier::new("graphene_std::raster::ImageOpacityNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
name: "Opacity",
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::OpacityNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
inputs: &[
DocumentInputType {
name: "Image",
@ -198,8 +198,8 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
},
DocumentNodeType {
name: "Posterize",
category: "Image Filters",
identifier: NodeIdentifier::new("graphene_std::raster::Posterize", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::PosterizeNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
inputs: &[
DocumentInputType {
name: "Image",
@ -217,7 +217,7 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
},
DocumentNodeType {
name: "Exposure",
category: "Image Color Correction",
category: "Image Adjustments",
identifier: NodeIdentifier::new("graphene_std::raster::ExposureNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
inputs: &[
DocumentInputType {
@ -228,7 +228,7 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
DocumentInputType {
name: "Value",
data_type: FrontendGraphDataType::Number,
default: NodeInput::value(TaggedValue::F64(1.), false),
default: NodeInput::value(TaggedValue::F64(0.), false),
},
],
outputs: &[FrontendGraphDataType::Raster],
@ -236,7 +236,7 @@ static DOCUMENT_NODE_TYPES: &[DocumentNodeType] = &[
},
DocumentNodeType {
name: "Add",
category: "Mathmatics",
category: "Math",
identifier: NodeIdentifier::new("graphene_core::ops::AddNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
inputs: &[
DocumentInputType {

View File

@ -76,12 +76,12 @@ fn number_range_widget(document_node: &DocumentNode, node_id: NodeId, index: usi
pub fn adjust_hsl_properties(document_node: &DocumentNode, node_id: NodeId) -> Vec<LayoutGroup> {
let hue_shift = number_range_widget(document_node, node_id, 1, "Hue Shift", Some(-180.), Some(180.), "°".into(), false);
let saturation_shift = number_range_widget(document_node, node_id, 2, "Saturation Shift", Some(-100.), Some(100.), "%".into(), false);
let luminance_shift = number_range_widget(document_node, node_id, 3, "Luminance Shift", Some(-100.), Some(100.), "%".into(), false);
let lightness_shift = number_range_widget(document_node, node_id, 3, "Lightness Shift", Some(-100.), Some(100.), "%".into(), false);
vec![
LayoutGroup::Row { widgets: hue_shift },
LayoutGroup::Row { widgets: saturation_shift },
LayoutGroup::Row { widgets: luminance_shift },
LayoutGroup::Row { widgets: lightness_shift },
]
}
@ -261,8 +261,8 @@ fn unknown_node_properties(document_node: &DocumentNode) -> Vec<LayoutGroup> {
string_properties(format!("Node '{}' cannot be found in library", document_node.name))
}
pub fn no_properties(document_node: &DocumentNode, _node_id: NodeId) -> Vec<LayoutGroup> {
string_properties(format!("The {} node requires no properties.", document_node.name.to_lowercase()))
pub fn no_properties(_document_node: &DocumentNode, _node_id: NodeId) -> Vec<LayoutGroup> {
string_properties("Node has no properties")
}
pub fn generate_node_properties(document_node: &DocumentNode, node_id: NodeId) -> LayoutGroup {

View File

@ -19,7 +19,7 @@
<TextInput placeholder="Search Nodes..." :value="searchTerm" @update:value="(val) => (searchTerm = val)" v-focus />
<LayoutCol v-for="nodeCategory in nodeCategories" :key="nodeCategory[0]">
<TextLabel>{{ nodeCategory[0] }}</TextLabel>
<TextButton v-for="nodeType in nodeCategory[1]" v-bind:key="String(nodeType)" :label="nodeType.name + ' Node'" :action="() => createNode(nodeType.name)" />
<TextButton v-for="nodeType in nodeCategory[1]" v-bind:key="String(nodeType)" :label="nodeType.name" :action="() => createNode(nodeType.name)" />
</LayoutCol>
<TextLabel v-if="nodeCategories.length === 0">No search results :(</TextLabel>
</LayoutCol>
@ -114,6 +114,11 @@
padding: 5px;
z-index: 3;
background-color: var(--color-3-darkgray);
.text-button + .text-button {
margin-left: 0;
margin-top: 4px;
}
}
.options-bar {

View File

@ -55,16 +55,16 @@ impl<N: Node<(), Output = f32>> Node<Color> for HueShiftColorNode<N> {
type Output = Color;
fn eval(self, color: Color) -> Color {
let hue_shift = self.0.eval(());
let [hue, saturation, luminance, alpha] = color.to_hsla();
Color::from_hsla(hue + hue_shift / 360., saturation, luminance, alpha)
let [hue, saturation, lightness, alpha] = color.to_hsla();
Color::from_hsla(hue + hue_shift / 360., saturation, lightness, alpha)
}
}
impl<N: Node<(), Output = f32> + Copy> Node<Color> for &HueShiftColorNode<N> {
type Output = Color;
fn eval(self, color: Color) -> Color {
let hue_shift = self.0.eval(());
let [hue, saturation, luminance, alpha] = color.to_hsla();
Color::from_hsla(hue + hue_shift / 360., saturation, luminance, alpha)
let [hue, saturation, lightness, alpha] = color.to_hsla();
Color::from_hsla(hue + hue_shift / 360., saturation, lightness, alpha)
}
}

View File

@ -82,20 +82,20 @@ impl Color {
}
}
/// Create a [Color] from a hue, saturation, luminance and alpha (all between 0 and 1)
/// Create a [Color] from a hue, saturation, lightness and alpha (all between 0 and 1)
///
/// # Examples
/// ```
/// use graphene_core::raster::color::Color;
/// let color = Color::from_hsla(0.5, 0.2, 0.3, 1.);
/// ```
pub fn from_hsla(hue: f32, saturation: f32, luminance: f32, alpha: f32) -> Color {
let temp1 = if luminance < 0.5 {
luminance * (saturation + 1.)
pub fn from_hsla(hue: f32, saturation: f32, lightness: f32, alpha: f32) -> Color {
let temp1 = if lightness < 0.5 {
lightness * (saturation + 1.)
} else {
luminance + saturation - luminance * saturation
lightness + saturation - lightness * saturation
};
let temp2 = 2. * luminance - temp1;
let temp2 = 2. * lightness - temp1;
let mut red = (hue + 1. / 3.).rem_euclid(1.);
let mut green = hue.rem_euclid(1.);
@ -190,7 +190,7 @@ impl Color {
}
// https://www.niwa.nu/2013/05/math-behind-colorspace-conversions-rgb-hsl/
/// Convert a [Color] to a hue, saturation, luminance and alpha (all between 0 and 1)
/// Convert a [Color] to a hue, saturation, lightness and alpha (all between 0 and 1)
///
/// # Examples
/// ```
@ -201,10 +201,10 @@ impl Color {
let min_channel = self.red.min(self.green).min(self.blue);
let max_channel = self.red.max(self.green).max(self.blue);
let luminance = (min_channel + max_channel) / 2.;
let lightness = (min_channel + max_channel) / 2.;
let saturation = if min_channel == max_channel {
0.
} else if luminance <= 0.5 {
} else if lightness <= 0.5 {
(max_channel - min_channel) / (max_channel + min_channel)
} else {
(max_channel - min_channel) / (2. - max_channel - min_channel)
@ -218,7 +218,7 @@ impl Color {
} / 6.;
let hue = hue.rem_euclid(1.);
[hue, saturation, luminance, self.alpha]
[hue, saturation, lightness, self.alpha]
}
// TODO: Readd formatting
@ -285,8 +285,8 @@ fn hsl_roundtrip() {
(255, 255, 178),
] {
let col = Color::from_rgb8(red, green, blue);
let [hue, saturation, luminance, alpha] = col.to_hsla();
let result = Color::from_hsla(hue, saturation, luminance, alpha);
let [hue, saturation, lightness, alpha] = col.to_hsla();
let result = Color::from_hsla(hue, saturation, lightness, alpha);
assert!((col.r() - result.r()) < f32::EPSILON * 100.);
assert!((col.g() - result.g()) < f32::EPSILON * 100.);
assert!((col.b() - result.b()) < f32::EPSILON * 100.);

View File

@ -287,9 +287,9 @@ static NODE_REGISTRY: &[(NodeIdentifier, NodeConstructor)] = &[
unimplemented!()
}
}),
(NodeIdentifier::new("graphene_std::raster::GrayscaleImageNode", &[]), |proto_node, stack| {
(NodeIdentifier::new("graphene_std::raster::GrayscaleNode", &[]), |proto_node, stack| {
stack.push_fn(move |nodes| {
let node = DynAnyNode::new(graphene_std::raster::GrayscaleImageNode);
let node = DynAnyNode::new(graphene_std::raster::GrayscaleNode);
if let ProtoNodeInput::Node(node_id) = proto_node.input {
let pre_node = nodes.get(node_id as usize).unwrap();
@ -299,9 +299,9 @@ static NODE_REGISTRY: &[(NodeIdentifier, NodeConstructor)] = &[
}
})
}),
(NodeIdentifier::new("graphene_std::raster::InvertImageColorNode", &[]), |proto_node, stack| {
(NodeIdentifier::new("graphene_std::raster::InvertRGBNode", &[]), |proto_node, stack| {
stack.push_fn(move |nodes| {
let node = DynAnyNode::new(graphene_std::raster::InvertImageColorNode);
let node = DynAnyNode::new(graphene_std::raster::InvertRGBNode);
if let ProtoNodeInput::Node(node_id) = proto_node.input {
let pre_node = nodes.get(node_id as usize).unwrap();
@ -312,15 +312,15 @@ static NODE_REGISTRY: &[(NodeIdentifier, NodeConstructor)] = &[
})
}),
(
NodeIdentifier::new("graphene_std::raster::ShiftImageHSLNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
NodeIdentifier::new("graphene_std::raster::HueSaturationNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
|proto_node, stack| {
stack.push_fn(move |nodes| {
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("ShiftImageHSLNode Node constructed without inputs") };
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("HueSaturationNode Node constructed without inputs") };
let hue: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[0] as usize).unwrap());
let saturation: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[1] as usize).unwrap());
let luminance: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[2] as usize).unwrap());
let node = DynAnyNode::new(graphene_std::raster::ShiftImageHSLNode::new(hue, saturation, luminance));
let lightness: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[2] as usize).unwrap());
let node = DynAnyNode::new(graphene_std::raster::HueSaturationNode::new(hue, saturation, lightness));
if let ProtoNodeInput::Node(node_id) = proto_node.input {
let pre_node = nodes.get(node_id as usize).unwrap();
@ -332,14 +332,14 @@ static NODE_REGISTRY: &[(NodeIdentifier, NodeConstructor)] = &[
},
),
(
NodeIdentifier::new("graphene_std::raster::ImageBrightnessAndContrast", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
NodeIdentifier::new("graphene_std::raster::BrightnessContrastNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
|proto_node, stack| {
stack.push_fn(move |nodes| {
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("ImageBrightnessAndContrast Node constructed without inputs") };
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("BrightnessContrastNode Node constructed without inputs") };
let brightness: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[0] as usize).unwrap());
let contrast: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[1] as usize).unwrap());
let node = DynAnyNode::new(graphene_std::raster::ImageBrightnessAndContrast::new(brightness, contrast));
let node = DynAnyNode::new(graphene_std::raster::BrightnessContrastNode::new(brightness, contrast));
if let ProtoNodeInput::Node(node_id) = proto_node.input {
let pre_node = nodes.get(node_id as usize).unwrap();
@ -351,12 +351,12 @@ static NODE_REGISTRY: &[(NodeIdentifier, NodeConstructor)] = &[
},
),
(
NodeIdentifier::new("graphene_std::raster::ImageGammaNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
NodeIdentifier::new("graphene_std::raster::GammaNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
|proto_node, stack| {
stack.push_fn(move |nodes| {
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("ImageGammaNode Node constructed without inputs") };
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("GammaNode Node constructed without inputs") };
let gamma: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[0] as usize).unwrap());
let node = DynAnyNode::new(graphene_std::raster::ImageGammaNode::new(gamma));
let node = DynAnyNode::new(graphene_std::raster::GammaNode::new(gamma));
if let ProtoNodeInput::Node(node_id) = proto_node.input {
let pre_node = nodes.get(node_id as usize).unwrap();
@ -368,12 +368,12 @@ static NODE_REGISTRY: &[(NodeIdentifier, NodeConstructor)] = &[
},
),
(
NodeIdentifier::new("graphene_std::raster::ImageOpacityNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
NodeIdentifier::new("graphene_std::raster::OpacityNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
|proto_node, stack| {
stack.push_fn(move |nodes| {
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("ImageOpacityNode Node constructed without inputs") };
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("OpacityNode Node constructed without inputs") };
let opacity: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[0] as usize).unwrap());
let node = DynAnyNode::new(graphene_std::raster::ImageOpacityNode::new(opacity));
let node = DynAnyNode::new(graphene_std::raster::OpacityNode::new(opacity));
if let ProtoNodeInput::Node(node_id) = proto_node.input {
let pre_node = nodes.get(node_id as usize).unwrap();
@ -385,12 +385,12 @@ static NODE_REGISTRY: &[(NodeIdentifier, NodeConstructor)] = &[
},
),
(
NodeIdentifier::new("graphene_std::raster::Posterize", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
NodeIdentifier::new("graphene_std::raster::PosterizeNode", &[Type::Concrete(Cow::Borrowed("&TypeErasedNode"))]),
|proto_node, stack| {
stack.push_fn(move |nodes| {
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("Posterize Node constructed without inputs") };
let ConstructionArgs::Nodes(construction_nodes) = proto_node.construction_args else { unreachable!("Posterize node constructed without inputs") };
let value: DowncastBothNode<_, (), f64> = DowncastBothNode::new(nodes.get(construction_nodes[0] as usize).unwrap());
let node = DynAnyNode::new(graphene_std::raster::Posterize::new(value));
let node = DynAnyNode::new(graphene_std::raster::PosterizeNode::new(value));
if let ProtoNodeInput::Node(node_id) = proto_node.input {
let pre_node = nodes.get(node_id as usize).unwrap();

View File

@ -185,15 +185,15 @@ fn grayscale_image(mut image: Image) -> Image {
}
#[derive(Debug, Clone, Copy)]
pub struct GrayscaleImageNode;
pub struct GrayscaleNode;
impl Node<Image> for GrayscaleImageNode {
impl Node<Image> for GrayscaleNode {
type Output = Image;
fn eval(self, image: Image) -> Image {
grayscale_image(image)
}
}
impl Node<Image> for &GrayscaleImageNode {
impl Node<Image> for &GrayscaleNode {
type Output = Image;
fn eval(self, image: Image) -> Image {
grayscale_image(image)
@ -208,28 +208,28 @@ fn invert_image(mut image: Image) -> Image {
}
#[derive(Debug, Clone, Copy)]
pub struct InvertImageColorNode;
pub struct InvertRGBNode;
impl Node<Image> for InvertImageColorNode {
impl Node<Image> for InvertRGBNode {
type Output = Image;
fn eval(self, image: Image) -> Image {
invert_image(image)
}
}
impl Node<Image> for &InvertImageColorNode {
impl Node<Image> for &InvertRGBNode {
type Output = Image;
fn eval(self, image: Image) -> Image {
invert_image(image)
}
}
fn shift_image_hsl(mut image: Image, hue_shift: f32, saturation_shift: f32, luminance_shift: f32) -> Image {
fn shift_image_hsl(mut image: Image, hue_shift: f32, saturation_shift: f32, lightness_shift: f32) -> Image {
for pixel in &mut image.data {
let [hue, saturation, luminance, alpha] = pixel.to_hsla();
let [hue, saturation, lightness, alpha] = pixel.to_hsla();
*pixel = Color::from_hsla(
(hue + hue_shift / 360.) % 1.,
(saturation + saturation_shift / 100.).clamp(0., 1.),
(luminance + luminance_shift / 100.).clamp(0., 1.),
(lightness + lightness_shift / 100.).clamp(0., 1.),
alpha,
);
}
@ -237,48 +237,48 @@ fn shift_image_hsl(mut image: Image, hue_shift: f32, saturation_shift: f32, lumi
}
#[derive(Debug, Clone, Copy)]
pub struct ShiftImageHSLNode<Hue, Sat, Lum>
pub struct HueSaturationNode<Hue, Sat, Lit>
where
Hue: Node<(), Output = f64>,
Sat: Node<(), Output = f64>,
Lum: Node<(), Output = f64>,
Lit: Node<(), Output = f64>,
{
hue: Hue,
saturation: Sat,
luminance: Lum,
lightness: Lit,
}
impl<Hue, Sat, Lum> Node<Image> for ShiftImageHSLNode<Hue, Sat, Lum>
impl<Hue, Sat, Lit> Node<Image> for HueSaturationNode<Hue, Sat, Lit>
where
Hue: Node<(), Output = f64>,
Sat: Node<(), Output = f64>,
Lum: Node<(), Output = f64>,
Lit: Node<(), Output = f64>,
{
type Output = Image;
fn eval(self, image: Image) -> Image {
shift_image_hsl(image, self.hue.eval(()) as f32, self.saturation.eval(()) as f32, self.luminance.eval(()) as f32)
shift_image_hsl(image, self.hue.eval(()) as f32, self.saturation.eval(()) as f32, self.lightness.eval(()) as f32)
}
}
impl<Hue, Sat, Lum> Node<Image> for &ShiftImageHSLNode<Hue, Sat, Lum>
impl<Hue, Sat, Lit> Node<Image> for &HueSaturationNode<Hue, Sat, Lit>
where
Hue: Node<(), Output = f64> + Copy,
Sat: Node<(), Output = f64> + Copy,
Lum: Node<(), Output = f64> + Copy,
Lit: Node<(), Output = f64> + Copy,
{
type Output = Image;
fn eval(self, image: Image) -> Image {
shift_image_hsl(image, self.hue.eval(()) as f32, self.saturation.eval(()) as f32, self.luminance.eval(()) as f32)
shift_image_hsl(image, self.hue.eval(()) as f32, self.saturation.eval(()) as f32, self.lightness.eval(()) as f32)
}
}
impl<Hue, Sat, Lum> ShiftImageHSLNode<Hue, Sat, Lum>
impl<Hue, Sat, Lit> HueSaturationNode<Hue, Sat, Lit>
where
Hue: Node<(), Output = f64>,
Sat: Node<(), Output = f64>,
Lum: Node<(), Output = f64>,
Lit: Node<(), Output = f64>,
{
pub fn new(hue: Hue, saturation: Sat, luminance: Lum) -> Self {
Self { hue, saturation, luminance }
pub fn new(hue: Hue, saturation: Sat, lightness: Lit) -> Self {
Self { hue, saturation, lightness }
}
}
@ -294,7 +294,7 @@ fn adjust_image_brightness_and_contrast(mut image: Image, brightness_shift: f32,
}
#[derive(Debug, Clone, Copy)]
pub struct ImageBrightnessAndContrast<Brightness, Contrast>
pub struct BrightnessContrastNode<Brightness, Contrast>
where
Brightness: Node<(), Output = f64>,
Contrast: Node<(), Output = f64>,
@ -303,7 +303,7 @@ where
contrast: Contrast,
}
impl<Brightness, Contrast> Node<Image> for ImageBrightnessAndContrast<Brightness, Contrast>
impl<Brightness, Contrast> Node<Image> for BrightnessContrastNode<Brightness, Contrast>
where
Brightness: Node<(), Output = f64>,
Contrast: Node<(), Output = f64>,
@ -314,7 +314,7 @@ where
}
}
impl<Brightness, Contrast> Node<Image> for &ImageBrightnessAndContrast<Brightness, Contrast>
impl<Brightness, Contrast> Node<Image> for &BrightnessContrastNode<Brightness, Contrast>
where
Brightness: Node<(), Output = f64> + Copy,
Contrast: Node<(), Output = f64> + Copy,
@ -325,7 +325,7 @@ where
}
}
impl<Brightness, Contrast> ImageBrightnessAndContrast<Brightness, Contrast>
impl<Brightness, Contrast> BrightnessContrastNode<Brightness, Contrast>
where
Brightness: Node<(), Output = f64>,
Contrast: Node<(), Output = f64>,
@ -346,22 +346,22 @@ fn image_gamma(mut image: Image, gamma: f32) -> Image {
}
#[derive(Debug, Clone, Copy)]
pub struct ImageGammaNode<N: Node<(), Output = f64>>(N);
pub struct GammaNode<N: Node<(), Output = f64>>(N);
impl<N: Node<(), Output = f64>> Node<Image> for ImageGammaNode<N> {
impl<N: Node<(), Output = f64>> Node<Image> for GammaNode<N> {
type Output = Image;
fn eval(self, image: Image) -> Image {
image_gamma(image, self.0.eval(()) as f32)
}
}
impl<N: Node<(), Output = f64> + Copy> Node<Image> for &ImageGammaNode<N> {
impl<N: Node<(), Output = f64> + Copy> Node<Image> for &GammaNode<N> {
type Output = Image;
fn eval(self, image: Image) -> Image {
image_gamma(image, self.0.eval(()) as f32)
}
}
impl<N: Node<(), Output = f64> + Copy> ImageGammaNode<N> {
impl<N: Node<(), Output = f64> + Copy> GammaNode<N> {
pub fn new(node: N) -> Self {
Self(node)
}
@ -396,44 +396,44 @@ fn exposure(mut image: Image, exposure: f32) -> Image {
}
#[derive(Debug, Clone, Copy)]
pub struct Posterize<N: Node<(), Output = f64>>(N);
pub struct PosterizeNode<N: Node<(), Output = f64>>(N);
impl<N: Node<(), Output = f64>> Node<Image> for Posterize<N> {
impl<N: Node<(), Output = f64>> Node<Image> for PosterizeNode<N> {
type Output = Image;
fn eval(self, image: Image) -> Image {
posterize(image, self.0.eval(()) as f32)
}
}
impl<N: Node<(), Output = f64> + Copy> Node<Image> for &Posterize<N> {
impl<N: Node<(), Output = f64> + Copy> Node<Image> for &PosterizeNode<N> {
type Output = Image;
fn eval(self, image: Image) -> Image {
posterize(image, self.0.eval(()) as f32)
}
}
impl<N: Node<(), Output = f64> + Copy> Posterize<N> {
impl<N: Node<(), Output = f64> + Copy> PosterizeNode<N> {
pub fn new(node: N) -> Self {
Self(node)
}
}
#[derive(Debug, Clone, Copy)]
pub struct ImageOpacityNode<N: Node<(), Output = f64>>(N);
pub struct OpacityNode<N: Node<(), Output = f64>>(N);
impl<N: Node<(), Output = f64>> Node<Image> for ImageOpacityNode<N> {
impl<N: Node<(), Output = f64>> Node<Image> for OpacityNode<N> {
type Output = Image;
fn eval(self, image: Image) -> Image {
image_opacity(image, self.0.eval(()) as f32)
}
}
impl<N: Node<(), Output = f64> + Copy> Node<Image> for &ImageOpacityNode<N> {
impl<N: Node<(), Output = f64> + Copy> Node<Image> for &OpacityNode<N> {
type Output = Image;
fn eval(self, image: Image) -> Image {
image_opacity(image, self.0.eval(()) as f32)
}
}
impl<N: Node<(), Output = f64> + Copy> ImageOpacityNode<N> {
impl<N: Node<(), Output = f64> + Copy> OpacityNode<N> {
pub fn new(node: N) -> Self {
Self(node)
}