-
Notifications
You must be signed in to change notification settings - Fork 61
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
320: Implement struct-of-arrays (SoA) utilities r=Ogeon a=Ogeon This adds a set of iterators and utilities for converting between arrays of structs and structs of arrays. There's definitely more that can be done, but it's a start. This pull request includes: * Creating and extending`ColorType<Collection<T>>` from any `IntoIterator<Item=ColorType<T>>`. * Iterating over `ColorType<Collection<T>>`. * Some `Vec` functions are available for `ColorType<Vec<T>>`, with more that can be added. * Slicing and indexing with `get` and `get_mut`. * Working with `ColorType<&T>` and `ColorType<&mut T>`, using `copied`, `cloned` and `set`. See the discussion in #303 for some background. ## Closed Issues * Closes #305. Co-authored-by: Erik Hedvall <erikwhedvall@gmail.com>
- Loading branch information
Showing
37 changed files
with
2,056 additions
and
31 deletions.
There are no files selected for viewing
This file contains 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,50 @@ | ||
use palette::{cast, color_difference::EuclideanDistance, IntoColor, Oklab, Srgb}; | ||
|
||
fn main() { | ||
let image = image::open("example-data/input/fruits.png") | ||
.expect("could not open 'example-data/input/fruits.png'") | ||
.to_rgb8(); | ||
|
||
let image = cast::from_component_slice::<Srgb<u8>>(image.as_raw()); | ||
|
||
// Convert and collect the colors in a struct-of-arrays (SoA) format, where | ||
// each component is a Vec of all the pixels' component values. | ||
let oklab_image: Oklab<Vec<f32>> = image | ||
.iter() | ||
.map(|rgb| rgb.into_linear::<f32>().into_color()) | ||
.collect(); | ||
|
||
// Find the min, max and average of each component. We are doing it by | ||
// iterating over each component Vec separately, starting with l... | ||
let (min_l, max_l, average_l) = get_min_max_average(oklab_image.l.iter().copied()); | ||
let (min_a, max_a, average_a) = get_min_max_average(oklab_image.a.iter().copied()); | ||
let (min_b, max_b, average_b) = get_min_max_average(oklab_image.b.iter().copied()); | ||
|
||
// Find out how far the colors in the image are from the average color. In | ||
// this case, we can just iterate over all of the colors and consume the | ||
// collection(s). | ||
let average_color = Oklab::new(average_l, average_a, average_b); | ||
let (min_d, max_d, average_d) = get_min_max_average( | ||
oklab_image | ||
.into_iter() | ||
.map(|color| average_color.distance(color)), | ||
); | ||
|
||
// Print the stats. | ||
println!("Oklab l: min {min_l}, average {average_l}, max {max_l}"); | ||
println!("Oklab a: min {min_a}, average {average_a}, max {max_a}"); | ||
println!("Oklab b: min {min_b}, average {average_b}, max {max_b}"); | ||
println!("Distance from average color: min {min_d}, average {average_d}, max {max_d}"); | ||
} | ||
|
||
/// Calculates the min, max and average of the iterator's values. | ||
fn get_min_max_average(iter: impl ExactSizeIterator<Item = f32>) -> (f32, f32, f32) { | ||
let length = iter.len(); | ||
|
||
let (min, max, sum) = iter.fold( | ||
(f32::INFINITY, f32::NEG_INFINITY, 0.0), | ||
|(min, max, sum), value| (min.min(value), max.max(value), sum + value), | ||
); | ||
|
||
(min, max, sum / length as f32) | ||
} |
This file contains 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 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 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
Oops, something went wrong.