diff options
author | gennyble <gen@nyble.dev> | 2023-02-20 09:09:56 -0600 |
---|---|---|
committer | gennyble <gen@nyble.dev> | 2023-02-20 09:09:56 -0600 |
commit | a124c54ba8547403574554908578adeb7a423fee (patch) | |
tree | f270552f77f7e2dcd02abe6cb6595dc89a0906ac /src/lib.rs | |
parent | b8244907bae232420b0a7e358a970f5ff24d7433 (diff) | |
download | colorsquash-a124c54ba8547403574554908578adeb7a423fee.tar.gz colorsquash-a124c54ba8547403574554908578adeb7a423fee.zip |
collect colours multiple times with colorcollector
Diffstat (limited to 'src/lib.rs')
-rw-r--r-- | src/lib.rs | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/src/lib.rs b/src/lib.rs index 43aec69..3af73f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,6 +3,37 @@ use std::ops::Deref; use ahash::RandomState; +pub struct ColorCollector { + colors: HashMap<Rgb, usize, RandomState>, +} + +impl ColorCollector { + pub fn new() -> Self { + Self { + colors: HashMap::default(), + } + } + + /// Wants an RGB buffer + pub fn add(&mut self, buffer: &[u8]) { + for pixel in buffer.chunks(3) { + let rgb = Rgb([pixel[0], pixel[1], pixel[2]]); + + match self.colors.get_mut(&rgb) { + None => { + self.colors.insert(rgb, 1); + } + Some(n) => *n += 1, + } + } + } + + pub fn as_squasher<T: Count>(self, max_colors: T) -> Squasher<T> { + let sorted = Squasher::<T>::sort(self.colors); + Squasher::from_sorted(max_colors, sorted) + } +} + pub struct Squasher<T> { palette: Vec<(Rgb, usize)>, larget_count: usize, @@ -15,6 +46,10 @@ impl<T: Count> Squasher<T> { /// equal to `16MB * std::mem::size_of(T)` pub fn new(max_colors: T, buffer: &[u8]) -> Self { let sorted = Self::unique_and_sort(buffer); + Self::from_sorted(max_colors, sorted) + } + + fn from_sorted(max_colors: T, sorted: Vec<(Rgb, usize)>) -> Self { let selected = Self::select_colors(&sorted, max_colors); let mut this = Self { @@ -43,6 +78,17 @@ impl<T: Count> Squasher<T> { } } + /// Take an RGB image buffer and an output buffer. The function will fill + /// the output buffer with indexes into the Palette. + //TODO: gen- Better name? + pub fn map_unsafe(&self, image: &[u8], buffer: &mut [T]) { + for (idx, color) in image.chunks(3).enumerate() { + let index = self.map[color_index(&Rgb([color[0], color[1], color[2]]))]; + + buffer[idx] = index; + } + } + /// Retrieve the palette this squasher is working from pub fn palette(&self) -> Vec<Rgb> { self.palette.iter().map(|ahh| ahh.0).collect() @@ -74,7 +120,11 @@ impl<T: Count> Squasher<T> { } } - let mut sorted: Vec<(Rgb, usize)> = colors.into_iter().collect(); + Self::sort(colors) + } + + fn sort(map: HashMap<Rgb, usize, RandomState>) -> Vec<(Rgb, usize)> { + let mut sorted: Vec<(Rgb, usize)> = map.into_iter().collect(); sorted.sort_by(|(colour1, freq1), (colour2, freq2)| { freq2 .cmp(freq1) |