Skip to content
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

Pixel type is not constructable. #1

Open
bddap opened this issue Mar 2, 2023 · 1 comment · May be fixed by #2
Open

Pixel type is not constructable. #1

bddap opened this issue Mar 2, 2023 · 1 comment · May be fixed by #2

Comments

@bddap
Copy link

bddap commented Mar 2, 2023

It's very nearly possible to serialize some image as sixel using this library. Just missing one thing.

To use the SixelSerializer type we need to pass in Pixels, but Pixels is has no constructor and its fields are private.

This sample code demonstrates what the sixel-image crate can almost do:

use std::collections::{BTreeMap, HashMap, HashSet};

use image::RgbaImage;
use itertools::Itertools;
use sixel_image::SixelColor;

fn render_sixel(img: &RgbaImage) -> String {
    let colors: HashMap<[u8; 3], u16> = img
        .pixels()
        .map(|p| [p[0], p[1], p[2]].map(compress))
        .collect::<HashSet<[u8; 3]>>() // dedup
        .into_iter()
        .enumerate()
        .map(|(i, c)| (c, wrapping_into(i)))
        .collect();
    let color_registers: BTreeMap<u16, SixelColor> = colors
        .iter()
        .map(|(&c, &i)| (i, SixelColor::Rgb(c[0], c[1], c[2])))
        .collect();

    let pixels: Vec<Vec<sixel_image::Pixel>> = img
        .pixels()
        .map(|p| {
            let c = [p[0], p[1], p[2]].map(compress);
            let ci = colors[&c];
            unimplemented!("can't construct the `Pixel` from external crate")
        })
        .chunks(img.width() as usize)
        .into_iter()
        .map(|c| c.collect())
        .collect();

    sixel_image::SixelSerializer::new(&color_registers, &pixels).serialize()
}

fn wrapping_into(u: usize) -> u16 {
    (u % u16::MAX as usize) as u16
}

/// compress a color value from the range [0, 255] to the range [0, 100]
fn compress(a: u8) -> u8 {
    (a as u16 * 100 / 255) as u8
}

fn main() {
    let img = image::RgbaImage::new(100, 100);
    println!("{}", render_sixel(&img));
}
@bddap
Copy link
Author

bddap commented Mar 2, 2023

A minimal solution would be to add Pixel::new function:

impl Pixel {
    pub fn new(color: u16) -> Self {
        Pixel {on: true, color}
    }
}

For a little extra expressiveness we might add this as well:

impl Pixel {
    pub const OFF: Pixel = Pixel {on: false, color: 0};
}

bddap added a commit to bddap/sixel-image that referenced this issue Mar 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant