Skip to content

Commit 0bae80f

Browse files
author
ynn
committed
feat: adds --base64 option
1 parent 9aaf532 commit 0bae80f

File tree

6 files changed

+41
-10
lines changed

6 files changed

+41
-10
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ default-run = "piet_programming_language"
77
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
88

99
[dependencies]
10+
base64 = "0.22.1"
1011
clap = { version = "4.5.48", features = ["derive"] }
1112
image = "0.25.8"
1213
itertools = "0.14.0"

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ Arguments:
5858

5959
Options:
6060
-c, --codel-size <CODEL_SIZE> Specifies the codel size (default: auto detect)
61-
--fall-back-to-white Treats unknown color as white instead of error
62-
--fall-back-to-black Treats unknown color as black instead of error
61+
--fall-back-to-white Treats unknown colors as white instead of error
62+
--fall-back-to-black Treats unknown colors as black instead of error
6363
--max-iter <MAX_ITER> Terminates the program after this number of iterations
64+
--base64 Interprets <IMAGE_FILE> as a base64-encoded image instead of a file path
6465
-v, --verbose Enables debug output (path trace etc.)
6566
-h, --help Print help
6667
-V, --version Print version

src/args.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ pub struct Args {
2323
#[arg(long)]
2424
pub max_iter: Option<usize>,
2525

26+
/// Interprets <IMAGE_FILE> as a base64-encoded image instead of a file path
27+
#[arg(long)]
28+
pub base64: bool,
29+
2630
/// Enables debug output (path trace etc.)
2731
#[arg(short, long)]
2832
pub verbose: bool,
@@ -54,6 +58,7 @@ mod tests {
5458
fall_back_to_white: false,
5559
fall_back_to_black: false,
5660
max_iter: None,
61+
base64: false,
5762
verbose: false,
5863
};
5964
assert!(args.validate().is_ok());

src/image.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{
22
error::Error,
33
fmt::{self, Display},
4-
path::Path,
4+
io::{BufRead, Seek},
55
rc::Rc,
66
};
77

@@ -72,16 +72,13 @@ impl Display for Image {
7272
}
7373

7474
impl Image {
75-
pub fn new(
76-
file: impl AsRef<Path>,
75+
pub fn new<R: BufRead + Seek>(
76+
reader: R,
7777
codel_size: Option<usize>,
7878
default_color: Option<Codel>,
7979
) -> Result<Self, Box<dyn Error>> {
8080
let mut pixel_map = vec![];
81-
if !file.as_ref().exists() {
82-
return Err("file not found".into());
83-
}
84-
match ImageReader::open(file)?.decode()? {
81+
match ImageReader::new(reader).with_guessed_format()?.decode()? {
8582
DynamicImage::ImageRgb8(img) => {
8683
let height = img.height();
8784
let width = img.width();

src/lib.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,13 @@ pub mod interpreter;
99
pub mod stdin;
1010

1111
use std::error::Error;
12+
use std::fs;
13+
use std::io::{BufReader, Cursor};
1214

15+
use base64::Engine;
16+
use base64::prelude::{BASE64_STANDARD, BASE64_STANDARD_NO_PAD};
1317
use codel::Codel;
18+
use itertools::Itertools;
1419
use rustc_hash::FxHashSet;
1520

1621
use crate::args::Args;
@@ -35,7 +40,21 @@ pub fn run(args: &Args) -> Result<(), Box<dyn Error>> {
3540
} else {
3641
None
3742
};
38-
let img = Image::new(&args.image_file, args.codel_size, default_color)?;
43+
44+
let image_content: Vec<u8> = if args.base64 {
45+
let base64_encoded_image = args.image_file.split_whitespace().join(""); //`split_whitespace()` removes the wrapping newlines of GNU `base64` command.
46+
if base64_encoded_image.len().is_multiple_of(4) {
47+
BASE64_STANDARD.decode(&base64_encoded_image)?
48+
} else {
49+
BASE64_STANDARD_NO_PAD.decode(&base64_encoded_image)?
50+
}
51+
} else {
52+
fs::read(&args.image_file)?
53+
};
54+
55+
let reader = BufReader::new(Cursor::new(image_content));
56+
57+
let img = Image::new(reader, args.codel_size, default_color)?;
3958
debug_print(args.verbose, &format!("{}", img));
4059

4160
if img.get_codel_at((0, 0)).is_black() {
@@ -167,6 +186,7 @@ mod tests {
167186
fall_back_to_white: true,
168187
fall_back_to_black: false,
169188
max_iter: None,
189+
base64: false,
170190
verbose: false,
171191
};
172192
assert!(run(&args).is_ok());

0 commit comments

Comments
 (0)