mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-02 04:38:11 +08:00
Fix transform logic for mask node (#1134)
Fix transform logic for mask node + other fixes * Fixes the transform logic for the mask node reverting the breakage introduced by the color pr * Actually modifies the pixel values * Fix storage format for images * Export images as unassociated alpha
This commit is contained in:
@@ -105,6 +105,10 @@ pub trait Pixel: Clone + Pod + Zeroable {
|
|||||||
fn from_bytes(bytes: &[u8]) -> &Self {
|
fn from_bytes(bytes: &[u8]) -> &Self {
|
||||||
bytemuck::try_from_bytes(bytes).expect("Failed to convert bytes to pixel")
|
bytemuck::try_from_bytes(bytes).expect("Failed to convert bytes to pixel")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn byte_size() -> usize {
|
||||||
|
std::mem::size_of::<Self>()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
impl<T: Serde + Clone + Pod + Zeroable> Pixel for T {}
|
impl<T: Serde + Clone + Pod + Zeroable> Pixel for T {}
|
||||||
|
|
||||||
@@ -138,7 +142,7 @@ pub trait Alpha {
|
|||||||
fn a(&self) -> Self::AlphaChannel {
|
fn a(&self) -> Self::AlphaChannel {
|
||||||
self.alpha()
|
self.alpha()
|
||||||
}
|
}
|
||||||
fn multiply_alpha(&self, alpha: Self::AlphaChannel) -> Self;
|
fn multiplied_alpha(&self, alpha: Self::AlphaChannel) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Depth {
|
pub trait Depth {
|
||||||
@@ -565,7 +569,7 @@ mod image {
|
|||||||
|
|
||||||
let color_from_chunk = |chunk: &[u8]| P::from_bytes(chunk.try_into().unwrap()).clone();
|
let color_from_chunk = |chunk: &[u8]| P::from_bytes(chunk.try_into().unwrap()).clone();
|
||||||
|
|
||||||
let colors_from_bytes = |bytes: Vec<u8>| bytes.chunks_exact(4).map(color_from_chunk).collect();
|
let colors_from_bytes = |bytes: Vec<u8>| bytes.chunks_exact(P::byte_size()).map(color_from_chunk).collect();
|
||||||
|
|
||||||
String::deserialize(deserializer)
|
String::deserialize(deserializer)
|
||||||
.and_then(|string| base64::decode(string).map_err(|err| Error::custom(err.to_string())))
|
.and_then(|string| base64::decode(string).map_err(|err| Error::custom(err.to_string())))
|
||||||
@@ -656,7 +660,7 @@ mod image {
|
|||||||
}
|
}
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
impl<P: Alpha + RGB> Image<P>
|
impl<P: Alpha + RGB + AssociatedAlpha> Image<P>
|
||||||
where
|
where
|
||||||
P::ColorChannel: Linear,
|
P::ColorChannel: Linear,
|
||||||
{
|
{
|
||||||
@@ -671,9 +675,9 @@ mod image {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|color| {
|
.flat_map(|color| {
|
||||||
[
|
[
|
||||||
to_u8(to_gamma(color.r())),
|
to_u8(to_gamma(color.r() / color.a().to_channel())),
|
||||||
to_u8(to_gamma(color.g())),
|
to_u8(to_gamma(color.g() / color.a().to_channel())),
|
||||||
to_u8(to_gamma(color.b())),
|
to_u8(to_gamma(color.b() / color.a().to_channel())),
|
||||||
(num::cast::<_, f32>(color.a()).unwrap() * 255.) as u8,
|
(num::cast::<_, f32>(color.a()).unwrap() * 255.) as u8,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ impl Alpha for Color {
|
|||||||
fn alpha(&self) -> f32 {
|
fn alpha(&self) -> f32 {
|
||||||
self.alpha
|
self.alpha
|
||||||
}
|
}
|
||||||
fn multiply_alpha(&self, alpha: Self::AlphaChannel) -> Self {
|
fn multiplied_alpha(&self, alpha: Self::AlphaChannel) -> Self {
|
||||||
Self {
|
Self {
|
||||||
red: self.red * alpha,
|
red: self.red * alpha,
|
||||||
green: self.green * alpha,
|
green: self.green * alpha,
|
||||||
|
|||||||
@@ -239,17 +239,18 @@ fn mask_image<
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Transforms a point from the background image to the forground image
|
// Transforms a point from the background image to the forground image
|
||||||
let bg_to_fg = DAffine2::from_scale(mask_size) * stencil.transform().inverse() * image.transform() * DAffine2::from_scale(1. / image_size);
|
let bg_to_fg = image.transform() * DAffine2::from_scale(1. / image_size);
|
||||||
|
|
||||||
for y in 0..image.height() {
|
for y in 0..image.height() {
|
||||||
for x in 0..image.width() {
|
for x in 0..image.width() {
|
||||||
let image_point = DVec2::new(x as f64, y as f64);
|
let image_point = DVec2::new(x as f64, y as f64);
|
||||||
let mut mask_point = bg_to_fg.transform_point2(image_point);
|
let mut mask_point = bg_to_fg.transform_point2(image_point);
|
||||||
mask_point = mask_point.clamp(DVec2::ZERO, mask_size);
|
let local_mask_point = stencil.transform().inverse().transform_point2(mask_point);
|
||||||
|
mask_point = stencil.transform().transform_point2(local_mask_point.clamp(DVec2::ZERO, DVec2::ONE));
|
||||||
|
|
||||||
let image_pixel = image.get_pixel_mut(x as u32, y as u32).unwrap();
|
let image_pixel = image.get_pixel_mut(x as u32, y as u32).unwrap();
|
||||||
if let Some(mask_pixel) = stencil.sample(mask_point) {
|
if let Some(mask_pixel) = stencil.sample(mask_point) {
|
||||||
image_pixel.multiply_alpha(mask_pixel.l().to_channel());
|
*image_pixel = image_pixel.multiplied_alpha(mask_pixel.l().to_channel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user