Introduce Split/Combine Channels nodes (#1153)

* Add Channel Extrataction Node

* Add hacky BlendModes for Inserting Color Channels

* Fix Channel Exporter

* Add Monochrome Option and Multi Output Node

* Fix Input Mapping

* Fix Formatting

* Split Alpha Extraction to seperate node

* Remove unnecessary functionality

* Add Alpha Channel as an output to the extract channel node

* Fix compilation

* Add unpolished 'Combine Channels' Node

* Fix Rebasing Issues

* Add a bit of polish

* Fix Rebase Issues

* Switch from 'ColorChannel' to 'RedGreenBlue'
I initially added an enum to hold color channels called 'ColorChannel', but while implementing the nodes, there somebody allready added a similar enum so I switched to that type

* Add correct names

* Add Improvement

- Some Performance Improvements
- Some Formatting Improvements

* Add some improvements
Most of this stuff was done by TrueDoctor in my Luchbreak :D

* Implement IO Improvements
- Converted primary output from split node to a dummy output
- Removed primary Input from split node

* Fix Formatting

* Fix Combine RGB Node (hopefully final :D )

* Swap around Inputs and Outputs
Move from ARGB -> RGBA

* Improve naming

* More naming fixes

* Fix Replace -> Into

* Rename Replacment -> Insertion

* Add blank assist area

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
Co-authored-by: Dennis Kobert <dennis@kobert.dev>
This commit is contained in:
isiko
2023-05-25 12:15:00 +02:00
committed by Keavon Chambers
parent 41f7ce0bb3
commit 8d778e4848
7 changed files with 331 additions and 5 deletions

View File

@@ -1,6 +1,6 @@
use dyn_any::{DynAny, StaticType};
use glam::{DAffine2, DVec2};
use graphene_core::raster::{Alpha, BlendMode, BlendNode, Image, ImageFrame, LinearChannel, Luminance, Pixel, RasterMut, Sample};
use graphene_core::raster::{Alpha, BlendMode, BlendNode, Image, ImageFrame, Linear, LinearChannel, Luminance, Pixel, RGBMut, Raster, RasterMut, RedGreenBlue, Sample};
use graphene_core::transform::Transform;
use graphene_core::value::CopiedNode;
@@ -174,6 +174,54 @@ fn compute_transformed_bounding_box(transform: DAffine2) -> Bbox {
}
}
#[derive(Debug, Clone, Copy)]
pub struct InsertChannelNode<P, S, Insertion, TargetChannel> {
insertion: Insertion,
target_channel: TargetChannel,
_p: PhantomData<P>,
_s: PhantomData<S>,
}
#[node_macro::node_fn(InsertChannelNode<_P, _S>)]
fn insert_channel_node<
// _P is the color of the input image.
_P: RGBMut,
_S: Pixel + Luminance,
// Input image
Input: RasterMut<Pixel = _P>,
Insertion: Raster<Pixel = _S>,
>(
mut image: Input,
insertion: Insertion,
target_channel: RedGreenBlue,
) -> Input
where
_P::ColorChannel: Linear,
{
if insertion.width() == 0 {
return image;
}
if insertion.width() != image.width() || insertion.height() != image.height() {
log::warn!("Stencil and image have different sizes. This is not supported.");
return image;
}
for y in 0..image.height() {
for x in 0..image.width() {
let image_pixel = image.get_pixel_mut(x, y).unwrap();
let insertion_pixel = insertion.get_pixel(x, y).unwrap();
match target_channel {
RedGreenBlue::Red => image_pixel.set_red(insertion_pixel.l().cast_linear_channel()),
RedGreenBlue::Green => image_pixel.set_green(insertion_pixel.l().cast_linear_channel()),
RedGreenBlue::Blue => image_pixel.set_blue(insertion_pixel.l().cast_linear_channel()),
}
}
}
image
}
#[derive(Debug, Clone, Copy)]
pub struct MaskImageNode<P, S, Stencil> {
stencil: Stencil,
@@ -182,7 +230,7 @@ pub struct MaskImageNode<P, S, Stencil> {
}
#[node_macro::node_fn(MaskImageNode<_P, _S>)]
fn mask_image<
fn mask_imge<
// _P is the color of the input image. It must have an alpha channel because that is going to
// be modified by the mask
_P: Copy + Alpha,