Skip to content

Commit

Permalink
Add constructors for Pixel so users can use the SixelSerializer.
Browse files Browse the repository at this point in the history
  • Loading branch information
bddap committed Mar 2, 2023
1 parent 29e6deb commit 5d56849
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 1 deletion.
5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,8 @@ edition = "2021"

[dependencies]
sixel-tokenizer = "0.1.0"

[dev-dependencies]
image = "0.24.5"
itertools = "0.10.5"

11 changes: 11 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,17 @@ pub struct Pixel {
color: u16,
}

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

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

impl fmt::Debug for Pixel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.on {
Expand Down
57 changes: 56 additions & 1 deletion src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::SixelImage;
use crate::{Pixel, SixelColor, SixelImage, SixelSerializer};

fn remove_whitespace(s: &str) -> String {
let mut s = s.to_string();
Expand Down Expand Up @@ -236,3 +236,58 @@ fn corrupted_image() {
";
assert!(SixelImage::new(sample.as_bytes()).is_err());
}

#[test]
fn img_to_sixel() {
let img = image::RgbaImage::from_fn(64, 64, |x, y| {
image::Rgba([
((x + 128) % u8::MAX as u32) as u8,
((y + 128) % u8::MAX as u32) as u8,
(u8::MAX / 2) as u8,
255,
])
});
println!("{}", render_sixel(&img)); // run with `cargo test -- --nocapture` to see the output
}

fn render_sixel(img: &image::RgbaImage) -> String {
use std::collections::{BTreeMap, HashMap, HashSet};

use itertools::Itertools;

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<Pixel>> = img
.pixels()
.map(|p| {
let c = [p[0], p[1], p[2]].map(compress);
Pixel::new(colors[&c])
})
.chunks(img.width() as usize)
.into_iter()
.map(|c| c.collect())
.collect();

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
}

0 comments on commit 5d56849

Please sign in to comment.