8000 Implement `Image::from_peniko_image` by tomcur · Pull Request #996 · linebender/vello · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Implement Image::from_peniko_image #996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 9, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions sparse_strips/vello_common/src/paint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,60 @@ pub struct Image {
pub quality: ImageQuality,
}

impl Image {
/// Convert a [`peniko::Image`] to an [`Image`].
///
/// This is a somewhat lossy conversion, as the image data data is transformed to
/// [premultiplied RGBA8](`PremulRgba8`).
///
/// # Panics
///
/// This panics if `image` has a `width` or `height` greater than `u16::MAX`.
pub fn from_peniko_image(image: &peniko::Image) -> Self {
// TODO: how do we deal with `peniko::ImageFormat` growing? See also
// <https://github.com/linebender/vello/pull/996#discussion_r2080510863>.
if image.format != peniko::ImageFormat::Rgba8 {
unimplemented!("Unsupported image format: {:?}", image.format);
}

assert!(
image.width <= u16::MAX as u32 && image.height <= u16::MAX as u32,
"The image is too big. Its width and height can be no larger than {} pixels.",
u16::MAX,
);
let width = image.width.try_into().unwrap();
let height = image.height.try_into().unwrap();

#[expect(clippy::cast_possible_truncation, reason = "deliberate quantization")]
let global_alpha = u16::from((image.alpha * 255. + 0.5) as u8);

#[expect(clippy::cast_possible_truncation, reason = "This cannot overflow.")]
let pixels = image
.data
.data()
.chunks_exact(4)
.map(|rgba| {
let alpha = ((u16::from(rgba[3]) * global_alpha) / 255) as u8;
let multiply = |component| ((u16::from(alpha) * u16::from(component)) / 255) as u8;
PremulRgba8 {
r: multiply(rgba[0]),
g: multiply(rgba[1]),
b: multiply(rgba[2]),
a: alpha,
}
})
.collect();
let pixmap = Pixmap::from_parts(pixels, width, height);

Self {
pixmap: Arc::new(pixmap),
x_extend: image.x_extend,
y_extend: image.y_extend,
quality: image.quality,
}
}
}

/// A premultiplied color.
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct PremulColor {
Expand Down
0