-
Notifications
You must be signed in to change notification settings - Fork 158
Add support for rendering images #919
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
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
0e4f353
Add support for rendering images
LaurenzV 0386338
Rename `extend`
LaurenzV ca8aae2
Change resampler to be a const fn
LaurenzV 54509e9
Merge branch 'main' into images
LaurenzV 81a5885
Merge with newest main
LaurenzV 494dbcc
Reformat all
LaurenzV 78be13b
Fix clippy
LaurenzV 4fa03d5
Fix no_std for vello_api
LaurenzV bd33a7a
Rename two methods
LaurenzV 230a2aa
next attempt
LaurenzV adbfe90
Exclude png from no_std
LaurenzV f0035ae
More
LaurenzV 6edff4d
Add png feature to vello_cpu
LaurenzV 5138912
Add copyright headers
LaurenzV 9af07f2
Fix clippy complaint
LaurenzV 3f352a7
More fixes
LaurenzV bab4def
Fix alpha check
LaurenzV ea3058d
Reformat
LaurenzV 5444fd5
Temporarily ignore rotation test cases
LaurenzV 0c321e4
Retrigger CI
LaurenzV File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LaurenzV marked this conversation as resolved.
Show resolved
Hide resolved
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Copyright 2025 the Vello Authors | ||
// SPDX-License-Identifier: Apache-2.0 OR MIT | ||
|
||
//! A simple pixmap type. | ||
|
||
use alloc::vec; | ||
use alloc::vec::Vec; | ||
|
||
/// A pixmap backed by u8. | ||
#[derive(Debug, Clone)] | ||
pub struct Pixmap { | ||
/// Width of the pixmap in pixels. | ||
pub width: u16, | ||
/// Height of the pixmap in pixels. | ||
pub height: u16, | ||
/// Buffer of the pixmap in RGBA format. | ||
pub buf: Vec<u8>, | ||
LaurenzV marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
impl Pixmap { | ||
/// Create a new pixmap with the given width and height in pixels. | ||
pub fn new(width: u16, height: u16) -> Self { | ||
let buf = vec![0; width as usize * height as usize * 4]; | ||
Self { width, height, buf } | ||
} | ||
|
||
/// Return the width of the pixmap. | ||
pub fn width(&self) -> u16 { | ||
self.width | ||
} | ||
|
||
/// Return the height of the pixmap. | ||
pub fn height(&self) -> u16 { | ||
self.height | ||
} | ||
|
||
/// Apply an alpha value to the whole pixmap. | ||
pub fn multiply_alpha(&mut self, alpha: u8) { | ||
for comp in self.data_mut() { | ||
*comp = ((alpha as u16 * *comp as u16) / 255) as u8; | ||
} | ||
} | ||
|
||
/// Create a pixmap from a PNG file. | ||
pub fn from_png(data: &[u8]) -> Result<Self, png::DecodingError> { | ||
let mut decoder = png::Decoder::new(data); | ||
decoder.set_transformations(png::Transformations::ALPHA); | ||
|
||
let mut reader = decoder.read_info()?; | ||
let mut img_data = vec![0; reader.output_buffer_size()]; | ||
let info = reader.next_frame(&mut img_data)?; | ||
|
||
let data = match info.color_type { | ||
// We set a transformation to always convert to alpha. | ||
png::ColorType::Rgb => unreachable!(), | ||
png::ColorType::Grayscale => unreachable!(), | ||
// I believe the above transformation also expands indexed images. | ||
png::ColorType::Indexed => unreachable!(), | ||
png::ColorType::Rgba => img_data, | ||
png::ColorType::GrayscaleAlpha => { | ||
let mut rgba_data = Vec::with_capacity(img_data.len() * 2); | ||
for slice in img_data.chunks(2) { | ||
let gray = slice[0]; | ||
let alpha = slice[1]; | ||
rgba_data.push(gray); | ||
rgba_data.push(gray); | ||
rgba_data.push(gray); | ||
rgba_data.push(alpha); | ||
} | ||
|
||
rgba_data | ||
} | ||
}; | ||
|
||
let premultiplied = data.chunks_exact(4).flat_map(|d| { | ||
let alpha = d[3] as u16; | ||
let premultiply = |e: u8| { | ||
((e as u16 * alpha) / 255) as u8 | ||
}; | ||
|
||
if alpha == 0 { | ||
[0, 0, 0, 0] | ||
} else { | ||
[premultiply(d[0]), premultiply(d[1]), premultiply(d[2]), d[3]] | ||
} | ||
}).collect::<Vec<_>>(); | ||
|
||
Ok(Self { | ||
width: info.width as u16, | ||
height: info.height as u16, | ||
buf: premultiplied, | ||
}) | ||
} | ||
|
||
/// Returns a reference to the underlying data as premultiplied RGBA8. | ||
pub fn data(&self) -> &[u8] { | ||
&self.buf | ||
} | ||
|
||
/// Returns a mutable reference to the underlying data as premultiplied RGBA8. | ||
pub fn data_mut(&mut self) -> &mut [u8] { | ||
&mut self.buf | ||
} | ||
|
||
/// Sample a pixel from the pixmap. | ||
#[inline(always)] | ||
pub fn sample(&self, x: u16, y: u16) -> &[u8] { | ||
let idx = 4 * (self.width as usize * y as usize + x as usize); | ||
&self.buf[idx..][..4] | ||
} | ||
|
||
/// Convert from premultiplied to separate alpha. | ||
/// | ||
/// Not fast, but useful for saving to PNG etc. | ||
pub fn unpremultiply(&mut self) { | ||
for rgba in self.buf.chunks_exact_mut(4) { | ||
let alpha = 255.0 / rgba[3] as f32; | ||
if alpha != 0.0 { | ||
LaurenzV marked this conversation as resolved.
Show resolved
Hide resolved
|
||
rgba[0] = (rgba[0] as f32 * alpha).round().min(255.0) as u8; | ||
rgba[1] = (rgba[1] as f32 * alpha).round().min(255.0) as u8; | ||
rgba[2] = (rgba[2] as f32 * alpha).round().min(255.0) as u8; | ||
} | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we actually need this? Could we move the responsibility of preparing the image data to the client? If it still provides value, perhaps we could consider making it an optional feature?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that loading png images is such a common operation, I think it would be good to keep this. But I will definitely make it an optional feature.