From 734bdc7bfcd58860b0a92dde0a98055a1f94b422 Mon Sep 17 00:00:00 2001 From: caleb Date: Sat, 27 Jul 2024 23:40:08 +0300 Subject: [PATCH] bin: Allow input from stdin --- crates/zune-bin/src/cmd_parsers/filters.rs | 5 +- crates/zune-bin/src/cmd_parsers/operations.rs | 5 +- crates/zune-bin/src/file_io.rs | 21 ++++++- crates/zune-bin/src/lib.rs | 1 + crates/zune-bin/src/workflow.rs | 59 ++++++++++++------- crates/zune-image/src/traits.rs | 8 +-- 6 files changed, 61 insertions(+), 38 deletions(-) diff --git a/crates/zune-bin/src/cmd_parsers/filters.rs b/crates/zune-bin/src/cmd_parsers/filters.rs index 08de2350..4d995c31 100644 --- a/crates/zune-bin/src/cmd_parsers/filters.rs +++ b/crates/zune-bin/src/cmd_parsers/filters.rs @@ -9,7 +9,6 @@ use clap::ArgMatches; use log::debug; use zune_image::pipelines::Pipeline; -use zune_image::traits::IntoImage; use zune_imageprocs::box_blur::BoxBlur; use zune_imageprocs::convolve::Convolve; use zune_imageprocs::gaussian_blur::GaussianBlur; @@ -21,8 +20,8 @@ use zune_imageprocs::spatial_ops::SpatialOperations; use zune_imageprocs::unsharpen::Unsharpen; //use zune_opencl::ocl_sobel::OclSobel; -pub fn parse_options( - workflow: &mut Pipeline, argument: &str, args: &ArgMatches +pub fn parse_options( + workflow: &mut Pipeline, argument: &str, args: &ArgMatches ) -> Result<(), String> { if argument == "box-blur" { let radius = *args.get_one::(argument).unwrap(); diff --git a/crates/zune-bin/src/cmd_parsers/operations.rs b/crates/zune-bin/src/cmd_parsers/operations.rs index cb671a3c..2571d5f4 100644 --- a/crates/zune-bin/src/cmd_parsers/operations.rs +++ b/crates/zune-bin/src/cmd_parsers/operations.rs @@ -13,7 +13,6 @@ use zune_core::colorspace::ColorSpace; use zune_image::core_filters::colorspace::ColorspaceConv; use zune_image::core_filters::depth::Depth; use zune_image::pipelines::Pipeline; -use zune_image::traits::IntoImage; use zune_imageprocs::brighten::Brighten; use zune_imageprocs::contrast::Contrast; use zune_imageprocs::crop::Crop; @@ -33,8 +32,8 @@ use zune_imageprocs::transpose::Transpose; use crate::cmd_args::arg_parsers::IColorSpace; -pub fn parse_options( - workflow: &mut Pipeline, argument: &str, args: &ArgMatches +pub fn parse_options( + workflow: &mut Pipeline, argument: &str, args: &ArgMatches ) -> Result<(), String> { if argument == "flip" { debug!("Added flip operation"); diff --git a/crates/zune-bin/src/file_io.rs b/crates/zune-bin/src/file_io.rs index a3d00e49..285e566c 100644 --- a/crates/zune-bin/src/file_io.rs +++ b/crates/zune-bin/src/file_io.rs @@ -5,11 +5,11 @@ * * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license */ - use std::ffi::OsString; use std::fs::File; use std::io::BufReader; +use zune_core::bytestream::ZCursor; use zune_core::options::DecoderOptions; use zune_image::errors::ImageErrors; use zune_image::image::Image; @@ -27,10 +27,25 @@ impl ZuneFile { } impl IntoImage for ZuneFile { - fn into_image(self) -> Result { + fn into_image(&mut self) -> Result { // read file - let fd = BufReader::new(File::open(self.file_path)?); + let fd = BufReader::new(File::open(self.file_path.clone())?); Image::read(fd, self.options) } } + +pub struct ZuneMem> { + source: T, + options: DecoderOptions +} +impl> ZuneMem { + pub fn new(source: T, options: DecoderOptions) -> ZuneMem { + ZuneMem { source, options } + } +} +impl> IntoImage for ZuneMem { + fn into_image(&mut self) -> Result { + Image::read(ZCursor::new(self.source.as_ref()), self.options) + } +} diff --git a/crates/zune-bin/src/lib.rs b/crates/zune-bin/src/lib.rs index 376f73d3..a970243e 100644 --- a/crates/zune-bin/src/lib.rs +++ b/crates/zune-bin/src/lib.rs @@ -5,6 +5,7 @@ * * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license */ +extern crate core; use std::process::exit; diff --git a/crates/zune-bin/src/workflow.rs b/crates/zune-bin/src/workflow.rs index 22c8011b..f7c15045 100644 --- a/crates/zune-bin/src/workflow.rs +++ b/crates/zune-bin/src/workflow.rs @@ -18,21 +18,20 @@ use log::{debug, error, info, trace}; use zune_image::codecs::ImageFormat; use zune_image::errors::ImageErrors; use zune_image::pipelines::Pipeline; -use zune_image::traits::IntoImage; use crate::cmd_args::CmdImageFormats; use crate::cmd_parsers::global_options::CmdOptions; use crate::cmd_parsers::{decoder_options, encoder_options}; -use crate::file_io::ZuneFile; +use crate::file_io::{ZuneFile, ZuneMem}; use crate::probe_files::probe_input_files; use crate::show_gui::open_in_default_app; -struct CmdPipeline { - inner: Pipeline, +struct CmdPipeline { + inner: Pipeline, formats: Vec } -impl CmdPipeline { - pub fn new() -> CmdPipeline { +impl CmdPipeline { + pub fn new() -> CmdPipeline { CmdPipeline { inner: Pipeline::new(), formats: vec![] @@ -58,22 +57,40 @@ pub(crate) fn create_and_exec_workflow_from_cmd( let mut buf = [0; 30]; for in_file in args.get_raw("in").unwrap() { - let mut workflow: CmdPipeline = CmdPipeline::new(); - - File::open(in_file)?.read(&mut buf)?; - - add_operations(args, &mut workflow.inner)?; - - if let Some((format, _)) = ImageFormat::guess_format(std::io::Cursor::new(&buf)) { - if format.has_decoder() { - workflow - .inner - .chain_decoder(ZuneFile::new(in_file.to_os_string(), decoder_options)); + let mut workflow: CmdPipeline = CmdPipeline::new(); + + if in_file == "-" { + // handle stdin + let mut data = Vec::new(); + let bytes_read = std::io::stdin().read_to_end(&mut data)?; + if let Some((format, _)) = ImageFormat::guess_format(std::io::Cursor::new(&data)) { + if format.has_decoder() { + workflow + .inner + .chain_decoder(Box::new(ZuneMem::new(data, decoder_options))); + } else { + return Err(ImageErrors::ImageDecoderNotImplemented(format)); + } } else { - return Err(ImageErrors::ImageDecoderNotImplemented(format)); + return Err(ImageErrors::ImageDecoderNotIncluded(ImageFormat::Unknown)); } } else { - return Err(ImageErrors::ImageDecoderNotIncluded(ImageFormat::Unknown)); + File::open(in_file)?.read(&mut buf)?; + + add_operations(args, &mut workflow.inner)?; + + if let Some((format, _)) = ImageFormat::guess_format(std::io::Cursor::new(&buf)) { + if format.has_decoder() { + workflow.inner.chain_decoder(Box::new(ZuneFile::new( + in_file.to_os_string(), + decoder_options + ))); + } else { + return Err(ImageErrors::ImageDecoderNotImplemented(format)); + } + } else { + return Err(ImageErrors::ImageDecoderNotIncluded(ImageFormat::Unknown)); + } } let options = encoder_options(args); @@ -173,9 +190,7 @@ pub(crate) fn create_and_exec_workflow_from_cmd( Ok(()) } -pub fn add_operations( - args: &ArgMatches, workflow: &mut Pipeline -) -> Result<(), String> { +pub fn add_operations(args: &ArgMatches, workflow: &mut Pipeline) -> Result<(), String> { for id in args.ids() { if args.try_get_many::(id.as_str()).is_ok() { // ignore groups diff --git a/crates/zune-image/src/traits.rs b/crates/zune-image/src/traits.rs index c2068ee6..50a8b3d0 100644 --- a/crates/zune-image/src/traits.rs +++ b/crates/zune-image/src/traits.rs @@ -499,11 +499,5 @@ pub trait DecodeInto { /// Convert something into an image by consuming it pub trait IntoImage { /// Consumes this and returns an image - fn into_image(self) -> Result; -} - -impl IntoImage for Image { - fn into_image(self) -> Result { - Ok(self) - } + fn into_image(&mut self) -> Result; }