Compare commits

..

2 commits

Author SHA1 Message Date
Winter Hille
f1cc0e65d4 switch to fenix to manage rust toolchain in nix 2025-11-10 21:05:01 -08:00
Winter Hille
728847157b add image rendering support 2025-11-10 20:21:57 -08:00
5 changed files with 1207 additions and 55 deletions

1151
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -11,6 +11,7 @@ path = "src/cli.rs"
required-features = ["cli"] required-features = ["cli"]
[dependencies] [dependencies]
image = { version = "0.25.8", optional = true }
rug = "1.27" rug = "1.27"
[dependencies.clap] [dependencies.clap]
@ -21,3 +22,4 @@ optional = true
[features] [features]
default = [] default = []
cli = ["dep:clap"] cli = ["dep:clap"]
image = ["dep:image"]

39
flake.lock generated
View file

@ -1,5 +1,26 @@
{ {
"nodes": { "nodes": {
"fenix": {
"inputs": {
"nixpkgs": [
"nixpkgs"
],
"rust-analyzer-src": "rust-analyzer-src"
},
"locked": {
"lastModified": 1761806629,
"narHash": "sha256-3u8345VliQtbpOtCNYYpDTCsjS8A9osrpU03E8TaIBw=",
"owner": "nix-community",
"repo": "fenix",
"rev": "c7c690951af16e60912678fab6155fb120cc27b0",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "fenix",
"type": "github"
}
},
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1758690382, "lastModified": 1758690382,
@ -18,8 +39,26 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"fenix": "fenix",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
} }
},
"rust-analyzer-src": {
"flake": false,
"locked": {
"lastModified": 1761739801,
"narHash": "sha256-ONUpb+l5oEIb9iOGkmUhze5YjRexZ6sc3mwQyLXlcms=",
"owner": "rust-lang",
"repo": "rust-analyzer",
"rev": "769ebafdc66559d620bdc414743f32bb28180c58",
"type": "github"
},
"original": {
"owner": "rust-lang",
"ref": "nightly",
"repo": "rust-analyzer",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -1,12 +1,30 @@
{ {
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
fenix = {
url = "github:nix-community/fenix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = outputs =
{ self, nixpkgs }: {
self,
nixpkgs,
fenix,
}:
let let
pkgs = nixpkgs.legacyPackages.x86_64-linux; pkgs = nixpkgs.legacyPackages.x86_64-linux;
rustPkgs = fenix.packages.x86_64-linux.default;
rustPlatform = pkgs.makeRustPlatform {
inherit (rustPkgs)
cargo
rustc
;
};
nativeBuildInputs = with pkgs; [ nativeBuildInputs = with pkgs; [
pkg-config pkg-config
m4 m4
@ -29,7 +47,7 @@
}; };
devShells.x86_64-linux.default = mkShell { devShells.x86_64-linux.default = mkShell {
packages = [ packages = with rustPkgs; [
cargo cargo
clippy clippy
rustc rustc

View file

@ -1,3 +1,6 @@
#[cfg(feature = "image")]
use image::{ImageBuffer, Pixel};
use rug::Integer as Int; use rug::Integer as Int;
#[derive(Debug)] #[derive(Debug)]
@ -45,6 +48,7 @@ impl Dollcode {
} }
out.reverse(); out.reverse();
Dollcode(out.into_iter().collect()) Dollcode(out.into_iter().collect())
} }
@ -94,8 +98,52 @@ impl Dollcode {
} }
out.reverse(); out.reverse();
out.into_iter().collect() out.into_iter().collect()
} }
#[cfg(feature = "image")]
pub fn render_image<Pix>(&self) -> ImageBuffer<Pix, Vec<u8>>
where
Pix: Pixel<Subpixel = u8> + 'static,
{
let char_width = 16u32;
let char_height = char_width * 4u32;
let img_width = ((char_width * 2) * self.0.chars().count() as u32) - char_width;
let img_height = char_height;
let mut dark_pixel =
*Pix::from_slice(&vec![Pix::Subpixel::MIN; Pix::CHANNEL_COUNT as usize]);
let mut light_pixel =
*Pix::from_slice(&vec![Pix::Subpixel::MAX; Pix::CHANNEL_COUNT as usize]);
if matches!(Pix::CHANNEL_COUNT, 2 | 4) {
dark_pixel.channels_mut()[Pix::CHANNEL_COUNT as usize - 1] = Pix::Subpixel::MAX;
light_pixel.channels_mut()[Pix::CHANNEL_COUNT as usize - 1] = Pix::Subpixel::MIN;
}
let mut img = ImageBuffer::from_pixel(img_width, img_height, light_pixel);
for (i, ch) in self.0.chars().enumerate() {
let x_offset = (i as u32) * char_width * 2;
let (x, y, width, height) = match ch {
'▖' => (x_offset, char_height / 2, char_width, char_height / 2),
'▘' => (x_offset, 0, char_width, char_height / 2),
'▌' => (x_offset, 0, char_width, char_height),
_ => unreachable!(),
};
for y_ in y..(y + height) {
for x_ in x..(x + width) {
img.put_pixel(x_, y_, dark_pixel)
}
}
}
img
}
} }
impl std::str::FromStr for Dollcode { impl std::str::FromStr for Dollcode {