mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 19:08:05 +08:00
Optimize colorspace conversion (#1228)
* Enabled cross-crate inlining for release builds. * Sprinkled inline-enabling directives in color.rs. * Reduced abstraction in color channel handling for better inlining. * Alpha should not use gamma. * Oops, didn't compile. * Added discrete sRGB <-> linear float conversion. * Use new float <-> sRGB conversion. * Improved comments. * Don't convert fully transparent pixels.
This commit is contained in:
committed by
Keavon Chambers
parent
5816807f18
commit
bb93d243a0
@@ -1,3 +1,4 @@
|
||||
use super::discrete_srgb::float_to_srgb_u8;
|
||||
use super::{Color, ImageSlice};
|
||||
use crate::Node;
|
||||
use alloc::vec::Vec;
|
||||
@@ -135,27 +136,35 @@ use super::*;
|
||||
impl<P: Alpha + RGB + AssociatedAlpha> Image<P>
|
||||
where
|
||||
P::ColorChannel: Linear,
|
||||
<P as Alpha>::AlphaChannel: Linear,
|
||||
{
|
||||
/// Flattens each channel cast to a u8
|
||||
pub fn into_flat_u8(self) -> (Vec<u8>, u32, u32) {
|
||||
let Image { width, height, data } = self;
|
||||
assert!(data.len() == width as usize * height as usize);
|
||||
|
||||
let to_gamma = SRGBGammaFloat::from_linear;
|
||||
let to_u8 = |x| (num_cast::<_, f32>(x).unwrap() * 255.) as u8;
|
||||
let mut result = Vec::with_capacity(data.len() * 4);
|
||||
for color in data {
|
||||
let a = color.a().to_f32();
|
||||
if a < 0.5 / 255.0 {
|
||||
// This would map to fully transparent anyway, avoid expensive encoding.
|
||||
result.push(0);
|
||||
result.push(0);
|
||||
result.push(0);
|
||||
result.push(0);
|
||||
} else {
|
||||
let undo_premultiply = 1.0 / a;
|
||||
let r = float_to_srgb_u8(color.r().to_f32() * undo_premultiply);
|
||||
let g = float_to_srgb_u8(color.g().to_f32() * undo_premultiply);
|
||||
let b = float_to_srgb_u8(color.b().to_f32() * undo_premultiply);
|
||||
result.push(r);
|
||||
result.push(g);
|
||||
result.push(b);
|
||||
result.push((a * 255.0 + 0.5) as u8);
|
||||
}
|
||||
}
|
||||
|
||||
let result_bytes = data
|
||||
.into_iter()
|
||||
.flat_map(|color| {
|
||||
[
|
||||
to_u8(to_gamma(color.r() / color.a().to_channel())),
|
||||
to_u8(to_gamma(color.g() / color.a().to_channel())),
|
||||
to_u8(to_gamma(color.b() / color.a().to_channel())),
|
||||
(num_cast::<_, f32>(color.a()).unwrap() * 255.) as u8,
|
||||
]
|
||||
})
|
||||
.collect();
|
||||
|
||||
(result_bytes, width, height)
|
||||
(result, width, height)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user