Skip to content

Commit

Permalink
Restore streaming output writes
Browse files Browse the repository at this point in the history
During the upgrade from image 0.23 to 0.24, `ImageBuffer::write_to()`
was changed to require a seekable writer.
This doesn't work when writing to stdout, so we were forced to buffer
the output before writing it out in one go.

It turns out that most individual encoders don't actually require
seeking, and neither of the two we use does.
Restore streaming behavior by invoking encoders directly.

See: image-rs/image#1922
  • Loading branch information
9ary committed May 14, 2023
1 parent eb4fc02 commit ba7edad
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 21 deletions.
7 changes: 7 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ edition = "2018"
getopts = "0.2"
libc = "0.2"
num-traits = "0.2"
either = "1.8.1"

[dependencies.image]
default-features = false
Expand Down
48 changes: 27 additions & 21 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
use std::env;
use std::ffi::CString;
use std::fs::File;
use std::io::{self, Write};
use std::io;
use std::path::Path;
use std::process;
use std::time;

use getopts::Options;
use image::EncodableLayout;
use image::GenericImage;
use image::GenericImageView;
use image::ImageEncoder;
use image::Rgba;
use image::RgbaImage;
use x11::xlib;
Expand Down Expand Up @@ -96,14 +98,6 @@ fn run() -> i32 {
.opt_str("f")
.unwrap_or("png".to_string())
.to_lowercase();
let output_format = match output_ext.as_ref() {
"png" => image::ImageOutputFormat::Png,
"pam" => image::ImageOutputFormat::Pnm(image::codecs::pnm::PnmSubtype::ArbitraryMap),
_ => {
eprintln!("Invalid image format specified");
return 1;
}
};

let window_rect = display.get_window_rect(window);

Expand Down Expand Up @@ -234,25 +228,37 @@ fn run() -> i32 {
}
};

if path == "-" {
let mut buf = Vec::new();
image
.write_to(&mut io::Cursor::new(&mut buf), output_format)
.expect("Encoding failed");
io::stdout()
.write_all(buf.as_slice())
.expect("Writing to stdout failed");
let writer = if path == "-" {
either::Left(io::stdout())
} else {
match File::create(&Path::new(&path)) {
Ok(mut f) => image
.write_to(&mut f, output_format)
.expect("Writing to file failed"),
Ok(f) => either::Right(f),
Err(e) => {
eprintln!("Failed to create {}: {}", path, e);
return 1;
}
}
}
};

let encoder = match output_ext.as_ref() {
"png" => either::Left(image::codecs::png::PngEncoder::new(writer)),
"pam" => either::Right(
image::codecs::pnm::PnmEncoder::new(writer)
.with_subtype(image::codecs::pnm::PnmSubtype::ArbitraryMap),
),
_ => {
eprintln!("Invalid image format specified");
return 1;
}
};

either::for_both!(encoder, e => e.write_image(
image.as_raw().as_bytes(),
image.width(),
image.height(),
util::color_type(&image),
))
.expect("Failed to write output");

0
}
Expand Down
7 changes: 7 additions & 0 deletions src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,10 @@ pub fn parse_int<T: num_traits::Num>(string: &str) -> Result<T, T::FromStrRadixE
_ => T::from_str_radix(string, 10),
}
}

pub fn color_type<P, Container>(_: &image::ImageBuffer<P, Container>) -> image::ColorType
where
P: image::PixelWithColorType,
{
P::COLOR_TYPE
}

0 comments on commit ba7edad

Please sign in to comment.