mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 16:58:11 +08:00
Add mix node
This commit is contained in:
@@ -646,7 +646,7 @@ async fn threshold<T: Adjust<Color>>(
|
|||||||
image
|
image
|
||||||
}
|
}
|
||||||
|
|
||||||
trait Blend<P: Pixel> {
|
pub trait Blend<P: Pixel> {
|
||||||
fn blend(&self, under: &Self, blend_fn: impl Fn(P, P) -> P) -> Self;
|
fn blend(&self, under: &Self, blend_fn: impl Fn(P, P) -> P) -> Self;
|
||||||
}
|
}
|
||||||
impl Blend<Color> for Color {
|
impl Blend<Color> for Color {
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use graphene_core::raster::image::{Image, ImageFrameTable};
|
|||||||
use graphene_core::raster::{
|
use graphene_core::raster::{
|
||||||
Alpha, AlphaMut, Bitmap, BitmapMut, CellularDistanceFunction, CellularReturnType, DomainWarpType, FractalType, LinearChannel, Luminance, NoiseType, Pixel, RGBMut, Sample,
|
Alpha, AlphaMut, Bitmap, BitmapMut, CellularDistanceFunction, CellularReturnType, DomainWarpType, FractalType, LinearChannel, Luminance, NoiseType, Pixel, RGBMut, Sample,
|
||||||
};
|
};
|
||||||
|
use graphene_core::raster::{BlendMode, blend_colors};
|
||||||
use graphene_core::transform::{Transform, TransformMut};
|
use graphene_core::transform::{Transform, TransformMut};
|
||||||
use graphene_core::{AlphaBlending, Color, Ctx, ExtractFootprint, GraphicElement, Node};
|
use graphene_core::{AlphaBlending, Color, Ctx, ExtractFootprint, GraphicElement, Node};
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
@@ -191,6 +192,35 @@ where
|
|||||||
image
|
image
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[node_macro::node(category("Raster"))]
|
||||||
|
async fn mix(ctx: impl Ctx + Clone, modified_image: ImageFrameTable<Color>, original_image: ImageFrameTable<Color>, mask: ImageFrameTable<Color>) -> ImageFrameTable<Color> {
|
||||||
|
let mut inverted_mask_table = mask.clone();
|
||||||
|
for instance_wrapper in inverted_mask_table.instance_mut_iter() {
|
||||||
|
for pixel_color in instance_wrapper.instance.data.iter_mut() {
|
||||||
|
let color = pixel_color.to_gamma_srgb();
|
||||||
|
let color = color.map_rgb(|c| color.a() - c);
|
||||||
|
*pixel_color = color.to_linear_srgb();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let background_layer_table = crate::raster::mask(ctx.clone(), original_image, inverted_mask_table);
|
||||||
|
let foreground_layer_table = crate::raster::mask(ctx.clone(), modified_image, mask);
|
||||||
|
|
||||||
|
let mut final_blended_table = foreground_layer_table.clone();
|
||||||
|
for (over_instance_wrapper, under_instance_wrapper) in final_blended_table.instance_mut_iter().zip(background_layer_table.instance_ref_iter()) {
|
||||||
|
let over_image_data = &mut over_instance_wrapper.instance.data;
|
||||||
|
let under_image_data = &under_instance_wrapper.instance.data;
|
||||||
|
|
||||||
|
if over_image_data.len() == under_image_data.len() {
|
||||||
|
for (over_pixel, under_pixel) in over_image_data.iter_mut().zip(under_image_data.iter()) {
|
||||||
|
*over_pixel = blend_colors(*over_pixel, *under_pixel, BlendMode::Normal, 1.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final_blended_table
|
||||||
|
}
|
||||||
|
|
||||||
// #[derive(Debug, Clone, Copy)]
|
// #[derive(Debug, Clone, Copy)]
|
||||||
// pub struct BlendImageTupleNode<P, Fg, MapFn> {
|
// pub struct BlendImageTupleNode<P, Fg, MapFn> {
|
||||||
// map_fn: MapFn,
|
// map_fn: MapFn,
|
||||||
|
|||||||
Reference in New Issue
Block a user