Add 'Gradient Map' adjustment node

This commit is contained in:
Keavon Chambers
2024-08-09 23:19:22 -07:00
parent f6ffa45a81
commit 501b562d0f
5 changed files with 108 additions and 10 deletions

View File

@@ -5,6 +5,7 @@ use super::curve::{Curve, CurveManipulatorGroup, ValueMapperNode};
#[cfg(feature = "alloc")]
use super::ImageFrame;
use super::{Channel, Color, Node, RGBMut};
use crate::vector::style::GradientStops;
use crate::vector::VectorData;
use crate::GraphicGroup;
@@ -554,6 +555,21 @@ pub fn blend_colors(foreground: Color, background: Color, blend_mode: BlendMode,
background.alpha_blend(target_color.to_associated_alpha(opacity))
}
#[derive(Debug, Clone, Copy)]
pub struct GradientMapNode<Gradient, Reverse> {
gradient: Gradient,
reverse: Reverse,
// TODO: Add support for dithering to break up gradient color banding
// TODO: Add support for controlling the gradient interpolation method (instead of always `luminance_srgb()`)
}
#[node_macro::node_fn(GradientMapNode)]
fn gradient_map_node(color: Color, gradient: GradientStops, reverse: bool) -> Color {
let intensity = color.luminance_srgb();
let intensity = if reverse { 1. - intensity } else { intensity };
gradient.evalute(intensity as f64)
}
#[derive(Debug, Clone, Copy)]
pub struct VibranceNode<Vibrance> {
vibrance: Vibrance,

View File

@@ -36,6 +36,32 @@ impl Default for GradientStops {
}
}
impl GradientStops {
pub fn evalute(&self, t: f64) -> Color {
if self.0.is_empty() {
return Color::BLACK;
}
if t <= self.0[0].0 {
return self.0[0].1;
}
if t >= self.0[self.0.len() - 1].0 {
return self.0[self.0.len() - 1].1;
}
for i in 0..self.0.len() - 1 {
let (t1, c1) = self.0[i];
let (t2, c2) = self.0[i + 1];
if t >= t1 && t <= t2 {
let normalized_t = (t - t1) / (t2 - t1);
return c1.lerp(&c2, normalized_t as f32);
}
}
Color::BLACK
}
}
/// A gradient fill.
///
/// Contains the start and end points, along with the colors at varying points along the length.