1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use super::*; use ditherer::Ditherer; /// A helper type to very slightly simplify remapping images using a `Ditherer`. /// /// The plain `remap` function remaps a `&[Color]` to a `Vec<u8>`, while /// the `remap_iter` function remaps a `Box<Iterator<Item = Color>>` to a /// `Box<Iterator<Item = u8>>`. The `_usize` functions remap to `usize` instead of `u8`, /// in case you need palettes with more than 256 colors. /// /// # Examples /// ``` /// # use exoquant::*; /// # let image = testdata::test_image(); /// # let histogram: Histogram = image.pixels.iter().cloned().collect(); /// # let colorspace = SimpleColorSpace::default(); /// # let palette = generate_palette(&histogram, &colorspace, &optimizer::None, 256); /// let ditherer = ditherer::FloydSteinberg::new(); /// let remapper = Remapper::new(&palette, &colorspace, &ditherer); /// let indexed_image_data = remapper.remap(&image.pixels, image.width); /// ``` /// ``` /// # use exoquant::*; /// # let image = testdata::test_image(); /// # let histogram: Histogram = image.pixels.iter().cloned().collect(); /// # let colorspace = SimpleColorSpace::default(); /// # let palette = generate_palette(&histogram, &colorspace, &optimizer::None, 256); /// let ditherer = ditherer::FloydSteinberg::new(); /// let remapper = Remapper::new(&palette, &colorspace, &ditherer); /// let iter = remapper.remap_iter(Box::new(image.pixels.iter().cloned()), image.width); /// let indexed_image_data: Vec<u8> = iter.collect(); /// ``` pub struct Remapper<'a, T: 'a + ColorSpace, D: 'a + Ditherer + ?Sized> { map: ColorMap, colorspace: &'a T, ditherer: &'a D, } impl<'a, T: ColorSpace, D: Ditherer + ?Sized> Remapper<'a, T, D> { /// Create a new Remapper instance for the given palette, colorspace and ditherer. pub fn new(palette: &[Color], colorspace: &'a T, ditherer: &'a D) -> Remapper<'a, T, D> { Remapper { map: ColorMap::new(palette, colorspace), colorspace: colorspace, ditherer: ditherer, } } /// Remap and dither a `&[Color]` to a `Vec<u8>`. pub fn remap(&self, image: &[Color], width: usize) -> Vec<u8> { assert!(self.map.num_colors() <= 256); self.ditherer .remap(Box::new(image.iter().map(|&c| self.colorspace.to_float(c))), width, &self.map, self.colorspace) .map(|i| i as u8) .collect() } /// Remap and dither a `&[Color]` to a `Vec<usize>`. pub fn remap_usize(&self, image: &[Color], width: usize) -> Vec<usize> { self.ditherer .remap(Box::new(image.iter().map(|&c| self.colorspace.to_float(c))), width, &self.map, self.colorspace) .collect() } /// Remap and dither a `Box<Iterator<Item = Color>>` to a `Box<Iterator<Item = u8>>`. pub fn remap_iter<'b>(&'b self, image: Box<Iterator<Item = Color> + 'b>, width: usize) -> Box<Iterator<Item = u8> + 'b> { assert!(self.map.num_colors() <= 256); Box::new(self.ditherer .remap(Box::new(image.map(move |c| self.colorspace.to_float(c))), width, &self.map, self.colorspace) .map(|i| i as u8)) } /// Remap and dither a `Box<Iterator<Item = Color>>` to a `Box<Iterator<Item = usize>>`. pub fn remap_iter_usize<'b>(&'b self, image: Box<Iterator<Item = Color> + 'b>, width: usize) -> Box<Iterator<Item = usize> + 'b> { assert!(self.map.num_colors() <= 256); self.ditherer .remap(Box::new(image.map(move |c| self.colorspace.to_float(c))), width, &self.map, self.colorspace) } }