pub fn dither_image<C: ColorSpace, D: Ditherer>(
    info: &ImageInfo,
    remapper: &Remapper<C, D>,
    png: bool,
) -> Result<()> {
    let img = Reader::open(&info.input)
        .with_context(|| format!("Failed to open image {:?}", info.input))?
        .decode()
        .with_context(|| format!("Failed to decode image {:?}", info.input))?
        .to_rgb8();

    let width = img.width();
    let height = img.height();
    if img.width() != WIDTH || height != HEIGHT {
        return Err(anyhow!(
            "Skipping {:?} with dimensions {}x{}",
            info.input,
            width,
            height
        ));
    }

    let pixels: Vec<_> = img.pixels().map(|p| color(p[0], p[1], p[2])).collect();
    let dithered = remapper.remap(&pixels, width as usize);
    let bytes: Vec<_> = dithered.chunks(2).map(|x| x[0] << 4 | x[1]).collect();

    let mut file = File::create(&info.output)
        .with_context(|| format!("Failed to create output file {:?}", info.output,))?;
    file.write_all(&bytes)
        .with_context(|| format!("Failed to write output file {:?}", info.output,))?;

    // If requested, map the dithered index values back to the palette colors and save a PNG
    // for preview purposes without having to load the output files on the frame.
    if png {
        let rgb: Vec<_> = dithered
            .iter()
            .flat_map(|i| {
                let color = PALETTE[*i as usize];
                [color.r, color.g, color.b]
            })
            .collect();
        let rgb_img = ImageBuffer::<Rgb<u8>, Vec<_>>::from_vec(width, height, rgb).unwrap();
        let png_file = info.output.with_extension("png");
        rgb_img
            .save(&png_file)
            .with_context(|| format!("Failed to write PNG file {:?}", png_file))?;
    }

    Ok(())
}
/// Given an image mapping, dithers the image and saves it to the output location.
/// Optionally saves a PNG preview alongside it.
Given an image mapping, dithers the image and saves it to the output location.
Optionally saves a PNG preview alongside it.
Given an image mapping dithers the image and saves it to the output location . Optionally saves a PNG preview alongside it .
pub fn dither_image<C: ColorSpace, D: Ditherer>(
    info: &ImageInfo,
    remapper: &Remapper<C, D>,
    png: bool,
) -> Result<()> {
    let img = Reader::open(&info.input)
        .with_context(|| format!("Failed to open image {:?}", info.input))?
        .decode()
        .with_context(|| format!("Failed to decode image {:?}", info.input))?
        .to_rgb8();
    let width = img.width();
    let height = img.height();
    if img.width() != WIDTH || height != HEIGHT {
        return Err(anyhow!(
            "Skipping {:?} with dimensions {}x{}",
            info.input,
            width,
            height
        ));
    }
    let pixels: Vec<_> = img.pixels().map(|p| color(p[0], p[1], p[2])).collect();
    let dithered = remapper.remap(&pixels, width as usize);
    let bytes: Vec<_> = dithered.chunks(2).map(|x| x[0] << 4 | x[1]).collect();
    let mut file = File::create(&info.output)
        .with_context(|| format!("Failed to create output file {:?}", info.output,))?;
    file.write_all(&bytes)
        .with_context(|| format!("Failed to write output file {:?}", info.output,))?;
    // If requested, map the dithered index values back to the palette colors and save a PNG
    // for preview purposes without having to load the output files on the frame.
    if png {
        let rgb: Vec<_> = dithered
            .iter()
            .flat_map(|i| {
                let color = PALETTE[*i as usize];
                [color.r, color.g, color.b]
            })
            .collect();
        let rgb_img = ImageBuffer::<Rgb<u8>, Vec<_>>::from_vec(width, height, rgb).unwrap();
        let png_file = info.output.with_extension("png");
        rgb_img
            .save(&png_file)
            .with_context(|| format!("Failed to write PNG file {:?}", png_file))?;
    }
    Ok(())
}
pub fn dither_image < C : ColorSpace , D : Ditherer > ( info : & ImageInfo , remapper : & Remapper < C , D > , png : bool , ) -> Result < ( ) > { let img = Reader :: open ( & info . input ) . with_context ( | | format ! ( " " info input ) ) ? . decode ( ) . with_context ( | | format ! ( " " info input ) ) ? . to_rgb8 ( ) ; let width = img . width ( ) ; let height = img . height ( ) ; if img . width ( ) != WIDTH || height != HEIGHT { return Err ( anyhow ! ( " " info input width height ) ) ; } let pixels : Vec < _ > = img . pixels ( ) . map ( | p | color ( p [ 0 ] , p [ 1 ] , p [ 2 ] ) ) . collect ( ) ; let dithered = remapper . remap ( & pixels , width as usize ) ; let bytes : Vec < _ > = dithered . chunks ( 2 ) . map ( | x | x [ 0 ] << 4 | x [ 1 ] ) . collect ( ) ; let mut file = File :: create ( & info . output ) . with_context ( | | format ! ( " " info output ) ) ? ; file . write_all ( & bytes ) . with_context ( | | format ! ( " " info output ) ) ? ; // If requested, map the dithered index values back to the palette colors and save a PNG // for preview purposes without having to load the output files on the frame. if png { let rgb : Vec < _ > = dithered . iter ( ) . flat_map ( | i | { let color = PALETTE [ * i as usize ] ; [ color . r , color . g , color . b ] } ) . collect ( ) ; let rgb_img = ImageBuffer :: < Rgb < u8 > , Vec < _ > > :: from_vec ( width , height , rgb ) . unwrap ( ) ; let png_file = info . output . with_extension ( " " ) ; rgb_img . save ( & png_file ) . with_context ( | | format ! ( " " png_file ) ) ? ; } Ok ( ( ) ) }
Given an image mapping, dithers the image and saves it to the output location.
Given an image mapping dithers the image and saves it to the output location .
info
&ImageInfo
remapper
&Remapper<C, D>
png
bool