diff --git a/bingus/Cargo.toml b/bingus/Cargo.toml index f2f32ff..f09e84b 100644 --- a/bingus/Cargo.toml +++ b/bingus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "bingus" -version = "0.9.0" +version = "0.8.0" edition.workspace = true license.workspace = true description.workspace = true diff --git a/bingus/src/doc.rs b/bingus/src/doc.rs index e6c0fe7..57af55a 100644 --- a/bingus/src/doc.rs +++ b/bingus/src/doc.rs @@ -1,6 +1,4 @@ -#[cfg(feature = "printpdf")] pub use printpdf; -#[cfg(feature = "printpdf")] mod pdf; #[cfg(feature = "shiva")] mod shiva; diff --git a/bingus/src/fnt.rs b/bingus/src/fnt.rs index e86a3b3..800fe2e 100644 --- a/bingus/src/fnt.rs +++ b/bingus/src/fnt.rs @@ -1,4 +1,2 @@ -#[cfg(feature = "font-kit")] mod fontkit; -#[cfg(feature = "font-kit")] pub use fontkit::Font; diff --git a/bingus/src/img.rs b/bingus/src/img.rs index 627154b..bb13e63 100644 --- a/bingus/src/img.rs +++ b/bingus/src/img.rs @@ -1,6 +1,3 @@ -#[cfg(feature = "image")] mod image; -#[cfg(feature = "image")] pub use image::ImageBuffer as Image; -#[cfg(feature = "image")] pub use image::*; diff --git a/bingus/src/lib.rs b/bingus/src/lib.rs index f924fe3..30c7bfc 100644 --- a/bingus/src/lib.rs +++ b/bingus/src/lib.rs @@ -1,5 +1,3 @@ -#![deny(unused_crate_dependencies)] - #[cfg(feature = "binary")] pub mod bin; #[cfg(feature = "documents")] @@ -25,13 +23,13 @@ pub mod dynamic { path::Path, }; - #[cfg(all(feature = "documents", feature = "shiva"))] + #[cfg(feature = "documents")] use super::doc::ShivaDocument; - #[cfg(all(feature = "fonts", feature = "font-kit"))] + #[cfg(feature = "fonts")] use super::fnt::Font as FontKitFont; - #[cfg(all(feature = "pictures", feature = "image"))] + #[cfg(feature = "pictures")] use super::img::{self, DynamicImage}; - #[cfg(all(feature = "music", feature = "symphonia"))] + #[cfg(feature = "music")] use super::snd::{self, Audio}; #[cfg(feature = "text")] use super::txt::Text; @@ -40,32 +38,32 @@ pub mod dynamic { use std::marker::PhantomData; use cfg_if::cfg_if; - #[cfg(all(feature = "fonts", feature = "font-kit"))] + #[cfg(feature = "fonts")] use font_kit::error::FontLoadingError; pub use infer::*; - #[cfg(all(feature = "documents", feature = "printpdf"))] + #[cfg(feature = "documents")] use printpdf::PdfDocument; - #[cfg(all(feature = "documents", feature = "shiva"))] + #[cfg(feature = "documents")] use shiva::core::{bytes, Document, DocumentType}; use thiserror::Error; pub enum DynamicBendable<'a> { - #[cfg(all(feature = "pictures", feature = "image"))] + #[cfg(feature = "pictures")] Image(DynamicImage), #[cfg(feature = "binary")] Binary(Bytes), - #[cfg(all(feature = "music", feature = "symphonia"))] + #[cfg(feature = "music")] Sound(Audio), #[cfg(feature = "text")] Text(Text<'a>), #[cfg(not(feature = "text"))] Phantom(PhantomData<&'a ()>), - #[cfg(all(feature = "documents", feature = "shiva"))] + #[cfg(feature = "documents")] Doc(ShivaDocument), - #[cfg(all(feature = "documents", feature = "printpdf"))] + #[cfg(feature = "documents")] Archive(PdfDocument), Meta, - #[cfg(all(feature = "fonts", feature = "font-kit"))] + #[cfg(feature = "fonts")] Font(FontKitFont), } @@ -87,22 +85,22 @@ pub mod dynamic { pub enum OpenError { #[error("io: {0}")] Io(#[from] io::Error), - #[cfg(all(feature = "pictures", feature = "image"))] + #[cfg(feature = "pictures")] #[error("image: {0}")] Image(#[from] img::ImageError), - #[cfg(all(feature = "music", feature = "symphonia"))] + #[cfg(feature = "music")] #[error("audio: {0}")] Audio(#[from] snd::AudioOpenError), - #[cfg(all(feature = "documents", feature = "printpdf"))] + #[cfg(feature = "documents")] #[error("pdf: {0}")] Pdf(String), #[cfg(feature = "text")] #[error("text: {0}")] Text(#[from] FromUtf8Error), - #[cfg(all(feature = "documents", feature = "shiva"))] + #[cfg(feature = "documents")] #[error("document: {0}")] Document(#[from] ShivaError), - #[cfg(all(feature = "fonts", feature = "font-kit"))] + #[cfg(feature = "fonts")] #[error("font: {0:?}")] Font(#[from] FontLoadingError), } @@ -157,11 +155,11 @@ pub mod dynamic { .map( |(matcher, extension)| -> Result { Ok(match matcher { - #[cfg(all(feature = "pictures", feature = "image"))] + #[cfg(feature = "pictures")] Image => DynamicBendable::Image(img::load_from_memory(&bytes)?), - #[cfg(all(feature = "music", feature = "symphonia"))] + #[cfg(feature = "music")] Audio => DynamicBendable::Sound(crate::snd::Audio::open(Cursor::new(bytes), None)?), - #[cfg(all(feature = "documents", feature = "printpdf"))] + #[cfg(feature = "documents")] Archive if extension == "pdf" => DynamicBendable::Archive( PdfDocument::try_from_data_bytes( bytes, @@ -170,7 +168,7 @@ pub mod dynamic { ) .map_err(OpenError::Pdf)?, ), - #[cfg(all(feature = "documents", feature = "shiva"))] + #[cfg(feature = "documents")] Archive | Doc => { let document_type = DocumentType::from_extension(extension) .ok_or(ShivaUnknownExtensionError) @@ -184,7 +182,7 @@ pub mod dynamic { document_type, )) } - #[cfg(all(feature = "fonts", feature = "font-kit"))] + #[cfg(feature = "fonts")] Font => DynamicBendable::Font(FontKitFont::try_from_data_bytes( bytes, (), diff --git a/bingus/src/snd.rs b/bingus/src/snd.rs index b6c1951..dda4d48 100644 --- a/bingus/src/snd.rs +++ b/bingus/src/snd.rs @@ -1,8 +1,5 @@ -#[cfg(feature = "symphonia")] pub use symphonia::core::*; mod raw; pub use raw::*; -#[cfg(feature = "symphonia")] mod simphonia; -#[cfg(feature = "symphonia")] pub use simphonia::*; diff --git a/bong/Cargo.toml b/bong/Cargo.toml index 001655a..c6aef48 100644 --- a/bong/Cargo.toml +++ b/bong/Cargo.toml @@ -12,7 +12,7 @@ keywords.workspace = true [dependencies] anyhow = "1" -bingus = "0.8" +bingus = "0.6" strum = { version = "0", features = ["derive"] } derive-new = "0" clap = { version = "4.5.40", features = ["derive"] } diff --git a/bong/src/cli.rs b/bong/src/cli.rs index 4c1492a..774f621 100644 --- a/bong/src/cli.rs +++ b/bong/src/cli.rs @@ -18,18 +18,17 @@ use strum::{Display, EnumString}; pub(crate) struct Cli { /// Input file or standard input ("-"). pub(crate) input: FileOrStd, + #[command(subcommand)] + pub(crate) output_format: OutputFormat, /// Output file or standard output ("-"). pub(crate) output: FileOrStd, - /// Output format - #[command(subcommand)] - pub(crate) output_format: Option, } #[derive(Clone, Copy, Parser)] #[cfg_attr(debug_assertions, derive(Debug))] pub struct Dimensions { - pub width: Option, - pub height: Option, + pub width: u32, + pub height: u32, } #[derive(Clone, Copy, Parser)] @@ -41,23 +40,16 @@ pub struct ShivaFormat { #[derive(Clone, Copy, Parser)] pub struct Mp3Format { + #[arg(default_value = "44100")] pub sample_rate: u32, + #[arg(default_value = "128")] pub bitrate: u16, + #[arg(default_value = "5")] pub quality: u8, + #[arg(default_value_t)] pub sample_format: Mp3SampleFormat, } -impl Default for Mp3Format { - fn default() -> Self { - Self { - sample_rate: 44100, - bitrate: 128, - quality: 5, - sample_format: Default::default(), - } - } -} - #[derive(Clone, Copy, EnumString, Default, Display)] #[strum(ascii_case_insensitive)] pub enum Mp3SampleFormat { @@ -71,19 +63,12 @@ pub enum Mp3SampleFormat { #[derive(Clone, Copy, Parser)] pub struct WavFormat { + #[arg(default_value = "48000")] pub sample_rate: u32, + #[arg(default_value_t)] pub sample_format: WavSampleFormat, } -impl Default for WavFormat { - fn default() -> Self { - Self { - sample_rate: 48000, - sample_format: Default::default(), - } - } -} - #[derive(Clone, Copy, EnumString, Display, Default)] #[strum(ascii_case_insensitive)] pub enum WavSampleFormat { @@ -96,20 +81,12 @@ pub enum WavSampleFormat { #[derive(Clone, Copy, Parser)] pub struct FlacFormat { + #[arg(default_value = "48000")] pub sample_rate: usize, - #[arg(value_parser = flac_bps_value_parser)] + #[arg(value_parser = flac_bps_value_parser, default_value = "16")] pub bps: usize, } -impl Default for FlacFormat { - fn default() -> Self { - Self { - sample_rate: 48000, - bps: 16, - } - } -} - fn flac_bps_value_parser(input: &str) -> anyhow::Result { input.parse().context("not a number").and_then(|n| match n { 8 | 16 | 24 => Ok(n), @@ -129,8 +106,8 @@ impl From for hound::SampleFormat { impl From for bingus::img::Dimensions { fn from(value: Dimensions) -> Self { Self { - width: value.width.unwrap_or_default(), - height: value.height.unwrap_or_default(), + width: value.width, + height: value.height, } } } @@ -196,10 +173,8 @@ where } } -#[derive(Clone, Parser, Default)] +#[derive(Clone, Parser)] pub(crate) enum OutputFormat { - #[default] - Auto, Bytes, Pdf, ShivaDocument(ShivaFormat), diff --git a/bong/src/main.rs b/bong/src/main.rs index dbac40a..5292fe7 100644 --- a/bong/src/main.rs +++ b/bong/src/main.rs @@ -1,5 +1,3 @@ -#![deny(unused_crate_dependencies)] - use std::{ borrow::Cow, fs::File, @@ -8,12 +6,12 @@ use std::{ use anyhow::{anyhow, bail, Context}; use bingus::{ - doc::{printpdf::PdfDocument, DocumentType, ShivaDocument, ShivaFormat}, + doc::{printpdf::PdfDocument, ShivaDocument}, dynamic::{self, DynamicBendable}, fnt::Font, img::{ - Dimensions, GrayAlphaImage, GrayImage, Image, ImageFormat, Luma, LumaA, Rgb, Rgb32FImage, - RgbImage, Rgba, Rgba32FImage, RgbaImage, + GrayAlphaImage, GrayImage, Image, Luma, LumaA, Rgb, Rgb32FImage, RgbImage, Rgba, + Rgba32FImage, RgbaImage, }, snd::{conv::IntoSample, sample::i24, RawSamples}, txt::Text, @@ -44,7 +42,7 @@ fn main() -> anyhow::Result<()> { .context("reading input")?; buf }; - let bytes = match dynamic::open(&mut Cursor::new(input_bytes.clone())) + let mut bytes = match dynamic::open(&mut Cursor::new(input_bytes.clone())) .context("guessing media type / loading media")? .or(String::from_utf8(input_bytes.clone()) .ok() @@ -72,483 +70,10 @@ fn main() -> anyhow::Result<()> { .context("bending input into bytes")?; match output { cli::FileOrStd::File(file) => { - match output_format.unwrap_or_default() { - cli::OutputFormat::Auto => { - let extension = file - .extension() - .and_then(|os_str| os_str.to_str()) - .map(|s| s.to_ascii_lowercase()); - if let Some(ext) = &extension { - match ext.as_str() { - "pdf" => { - File::bend_from( - PdfDocument::bend_from(bytes, (), Default::default()) - .map_err(|s| anyhow!("{}", s)) - .context("bending into PDF document")? - .into_data_bytes(), - Box::new(file), - Default::default(), - ) - .context("writing PDF to output file")?; - } - _valid_shiva_extension - if DocumentType::from_extension(ext).is_some() => - { - let document_type = DocumentType::from_extension(ext).unwrap(); - File::bend_from( - ShivaDocument::bend_from( - bytes, - ShivaFormat::new(document_type, document_type), - Default::default(), - ) - .context("bending into a Shiva Document")?, - Box::new(file), - Default::default(), - ) - .context("writing Shiva Document to output file")?; - } - "ttf" | "ttc" | "otf" | "otc" | "cff" | "pfb" | "pfa" | "pfm" - | "afm" | "bdf" | "pcf" | "fon" | "fnt" | "svg" | "dfont" | "woff" - | "woff2" | "eot" => { - File::bend_from( - Font::bend_from(bytes, (), Default::default()) - .context("bending to font")? - .into_data_bytes(), - Box::new(file), - Default::default(), - ) - .context("writing font to output file")?; - } - "mp3" => { - eprintln!("warning: Rust MP3 lame encoder is freaky!"); - let mp3_format = Mp3Format::default(); - let Mp3Format { - bitrate, - quality, - sample_rate, - sample_format, - } = mp3_format; - let buff = { - use mp3lame_encoder::{Bitrate::*, Quality::*}; - let mut encoder = Mp3EncoderBuilder::new() - .context("Failed to create MP3 encoder builder")?; - encoder - .set_num_channels(1) - .context("Failed to set MP3 encoder channels")?; - encoder - .set_sample_rate(sample_rate) - .context("Failed to set MP3 encoder sample rate")?; - encoder - .set_brate(match bitrate { - 8 => Kbps8, - 16 => Kbps16, - 24 => Kbps24, - 32 => Kbps32, - 40 => Kbps40, - 48 => Kbps48, - 64 => Kbps64, - 80 => Kbps80, - 96 => Kbps96, - 112 => Kbps112, - 128 => Kbps128, - 160 => Kbps160, - 192 => Kbps192, - 224 => Kbps224, - 256 => Kbps256, - 320 => Kbps320, - _ => bail!("invalid MP3 bitrate"), - }) - .context("Failed to set MP3 encoder bitrate")?; - encoder - .set_quality(match quality { - 0 => Best, - 1 => SecondBest, - 2 => NearBest, - 3 => VeryNice, - 4 => Nice, - 5 => Good, - 6 => Decent, - 7 => Ok, - 8 => SecondWorst, - 9 => Worst, - _ => bail!("invalid MP3 quality"), - }) - .context("Failed to set MP3 encoder quality")?; - - let mut encoder = encoder - .build() - .context("Failed to initialize MP3 encoder")?; - - let (encoded_size, mut output) = { - match sample_format { - cli::Mp3SampleFormat::U16 => { - let (left, right): (Vec<_>, Vec<_>) = - RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap() - .into_inner() - .chunks_exact(2) - .map(|c| (c[0], c[1])) - .unzip(); - let input = DualPcm { - left: &left, - right: &right, - }; - let mut output = Vec::with_capacity( - mp3lame_encoder::max_required_buffer_size( - left.len() + right.len(), - ), - ); - ( - encoder - .encode(input, output.spare_capacity_mut()) - .context("Failed MP3 encoding")?, - output, - ) - } - cli::Mp3SampleFormat::I16 => { - let (left, right): (Vec<_>, Vec<_>) = - RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap() - .into_inner() - .chunks_exact(2) - .map(|c| (c[0], c[1])) - .unzip(); - let input = DualPcm { - left: &left, - right: &right, - }; - let mut output = Vec::with_capacity( - mp3lame_encoder::max_required_buffer_size( - left.len() + right.len(), - ), - ); - ( - encoder - .encode(input, output.spare_capacity_mut()) - .context("Failed MP3 encoding")?, - output, - ) - } - cli::Mp3SampleFormat::I32 => { - let (left, right): (Vec<_>, Vec<_>) = - RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap() - .into_inner() - .chunks_exact(2) - .map(|c| (c[0], c[1])) - .unzip(); - let input = DualPcm { - left: &left, - right: &right, - }; - let mut output = Vec::with_capacity( - mp3lame_encoder::max_required_buffer_size( - left.len() + right.len(), - ), - ); - ( - encoder - .encode(input, output.spare_capacity_mut()) - .context("Failed MP3 encoding")?, - output, - ) - } - cli::Mp3SampleFormat::F32 => { - let (left, right): (Vec<_>, Vec<_>) = - RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap() - .into_inner() - .chunks_exact(2) - .map(|c| (c[0], c[1])) - .unzip(); - let input = DualPcm { - left: &left, - right: &right, - }; - let mut output = Vec::with_capacity( - mp3lame_encoder::max_required_buffer_size( - left.len() + right.len(), - ), - ); - ( - encoder - .encode(input, output.spare_capacity_mut()) - .context("Failed MP3 encoding")?, - output, - ) - } - cli::Mp3SampleFormat::F64 => { - let (left, right): (Vec<_>, Vec<_>) = - RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap() - .into_inner() - .chunks_exact(2) - .map(|c| (c[0], c[1])) - .unzip(); - let input = DualPcm { - left: &left, - right: &right, - }; - let mut output = Vec::with_capacity( - mp3lame_encoder::max_required_buffer_size( - left.len() + right.len(), - ), - ); - ( - encoder - .encode(input, output.spare_capacity_mut()) - .context("Failed MP3 encoding")?, - output, - ) - } - } - }; - unsafe { - output.set_len(output.len().wrapping_add(encoded_size)); - } - let encoded_size = encoder - .flush::(output.spare_capacity_mut()) - .context( - "Failed MP3 flushing (don't know what that means)", - )?; - unsafe { - output.set_len(output.len().wrapping_add(encoded_size)); - } - output - }; - File::bend_from(buff, Box::new(file), Default::default()) - .context("writing MP3 to output file")?; - } - "wav" => { - let wav_format = Default::default(); - let WavFormat { - sample_rate, - sample_format, - } = wav_format; - match sample_format { - cli::WavSampleFormat::I8 => { - let samples = RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap_infallible(); - let mut buff = Cursor::new(Vec::with_capacity( - samples.as_ref().len() * 8, - )); - { - let mut writer = WavWriter::new( - &mut buff, - WavSpec { - channels: 1, - sample_rate, - bits_per_sample: i8::BITS as u16, - sample_format: sample_format.into(), - }, - ) - .context("Failed to create WAV writer")?; - for sample in samples.as_ref() { - writer.write_sample(*sample)?; - } - } - File::try_from_data_bytes( - buff.into_inner(), - Box::new(file), - Default::default(), - ) - .context("writing WAV data to output file")? - } - cli::WavSampleFormat::I16 => { - let samples = RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap_infallible(); - let mut buff = Cursor::new(Vec::with_capacity( - samples.as_ref().len() * 8, - )); - { - let mut writer = WavWriter::new( - &mut buff, - WavSpec { - channels: 1, - sample_rate, - bits_per_sample: i16::BITS as u16, - sample_format: sample_format.into(), - }, - ) - .context("Failed to create WAV writer")?; - for sample in samples.as_ref() { - writer.write_sample(*sample)?; - } - } - File::try_from_data_bytes( - buff.into_inner(), - Box::new(file), - Default::default(), - ) - .context("writing WAV data to output file")? - } - cli::WavSampleFormat::I32 => { - let samples = RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap_infallible(); - let mut buff = Cursor::new(Vec::with_capacity( - samples.as_ref().len() * 8, - )); - { - let mut writer = WavWriter::new( - &mut buff, - WavSpec { - channels: 1, - sample_rate, - bits_per_sample: i32::BITS as u16, - sample_format: sample_format.into(), - }, - ) - .context("Failed to create WAV writer")?; - for sample in samples.as_ref() { - writer.write_sample(*sample)?; - } - } - File::try_from_data_bytes( - buff.into_inner(), - Box::new(file), - Default::default(), - ) - .context("writing WAV data to output file")? - } - cli::WavSampleFormat::F32 => { - let samples = RawSamples::::bend_from( - bytes, - (), - Default::default(), - ) - .unwrap_infallible(); - let mut buff = Cursor::new(Vec::with_capacity( - samples.as_ref().len() * 8, - )); - { - let mut writer = WavWriter::new( - &mut buff, - WavSpec { - channels: 1, - sample_rate, - bits_per_sample: 32, - sample_format: sample_format.into(), - }, - ) - .context("Failed to create WAV writer")?; - for sample in samples.as_ref() { - writer.write_sample(*sample)?; - } - } - File::try_from_data_bytes( - buff.into_inner(), - Box::new(file), - Default::default(), - ) - .context("writing WAV data to output file")? - } - }; - } - "flac" => { - let flac_format = Default::default(); - let FlacFormat { sample_rate, bps } = flac_format; - let config = flacenc::config::Encoder::default() - .into_verified() - .expect("Config data error."); - let samples = - RawSamples::::bend_from(bytes, (), Default::default()) - .unwrap_infallible(); - let source = flacenc::source::MemSource::from_samples( - samples.as_ref().iter().copied() - .map(|sample| match bps { - 8 => IntoSample::::into_sample(sample) as i32, - 16 => IntoSample::::into_sample(sample) as i32, - 24 => IntoSample::::into_sample(sample).inner(), - _=> unimplemented!("sorry, the current implementation for the flac encoder doesn't support any other bitrate than 8, 16 or 24.") - }) - .collect::>() - .as_slice(), - 1, - bps, - sample_rate, - ); - let flac_stream = flacenc::encode_with_fixed_block_size( - &config, - source, - config.block_size, - ) - .expect("Encode failed."); - - // `Stream` imlpements `BitRepr` so you can obtain the encoded stream via - // `ByteSink` struct that implements `BitSink`. - let mut sink = flacenc::bitsink::ByteSink::new(); - flac_stream - .write(&mut sink) - .context("Failed to write samples to FLAC byte sink")?; - File::try_from_data_bytes( - sink.into_inner(), - Box::new(file), - Default::default(), - ) - .context("writing FLAC data to output file")?; - } - "txt" => { - File::bend_from( - Text::try_from_data_bytes(bytes, (), Default::default()) - .context("invalid UTF-8")?, - Box::new(file), - Default::default(), - ) - .context("writing text to output file")?; - } - _valid_image_extension - if ImageFormat::from_extension(ext).is_some() => - { - let len = bytes.len(); - RgbImage::from_data_bytes( - bytes, - Dimensions::square((len / 3).isqrt() as u32), - Default::default(), - ) - .save(file) - .context("writing image data to output file")? - } - "bin" => { - File::bend_from(bytes, Box::new(file), Default::default()) - .context("writing to file")?; - } - _ => bail!("Unknown file extension! Can't guess output file type. Please use one of the available types instead (see --help)."), - } - } else { - bail!("Can't guess the output file type without a file extension. Please specify one."); - } + match output_format { + cli::OutputFormat::Bytes => { + File::bend_from(bytes, Box::new(file), Default::default()) + .context("writing to file")?; } cli::OutputFormat::Pdf => { File::bend_from( @@ -946,126 +471,76 @@ fn main() -> anyhow::Result<()> { .context("writing text to output file")?; } cli::OutputFormat::ImageLuma8(dimensions) => { - let len = bytes.len(); - GrayImage::from_data_bytes( - bytes, - if_zero_adjust(dimensions.into(), len), - Default::default(), - ) - .save(file) - .context("writing image data to output file")? + GrayImage::from_data_bytes(bytes, dimensions.into(), Default::default()) + .save(file) + .context("writing image data to output file")? } cli::OutputFormat::ImageLumaA8(dimensions) => { - let len = bytes.len(); - GrayAlphaImage::from_data_bytes( - bytes, - if_zero_adjust(dimensions.into(), len), - Default::default(), - ) - .save(file) - .context("writing image data to output file")? + GrayAlphaImage::from_data_bytes(bytes, dimensions.into(), Default::default()) + .save(file) + .context("writing image data to output file")? } cli::OutputFormat::ImageRgb8(dimensions) => { - let len = bytes.len(); - RgbImage::from_data_bytes( - bytes, - if_zero_adjust(dimensions.into(), len), - Default::default(), - ) - .save(file) - .context("writing image data to output file")? + RgbImage::from_data_bytes(bytes, dimensions.into(), Default::default()) + .save(file) + .context("writing image data to output file")? } cli::OutputFormat::ImageRgba8(dimensions) => { - let len = bytes.len(); - RgbaImage::from_data_bytes( - bytes, - if_zero_adjust(dimensions.into(), len), - Default::default(), - ) - .save(file) - .context("writing image data to output file")? + RgbaImage::from_data_bytes(bytes, dimensions.into(), Default::default()) + .save(file) + .context("writing image data to output file")? } cli::OutputFormat::ImageLuma16(dimensions) => { - let len = bytes.len(); Image::, Vec>::from_data_bytes( bytes, - if_zero_adjust(dimensions.into(), len), + dimensions.into(), Default::default(), ) .save(file) .context("writing image data to output file")? } cli::OutputFormat::ImageLumaA16(dimensions) => { - let len = bytes.len(); Image::, Vec>::from_data_bytes( bytes, - if_zero_adjust(dimensions.into(), len), + dimensions.into(), Default::default(), ) .save(file) .context("writing image data to output file")? } cli::OutputFormat::ImageRgb16(dimensions) => { - let len = bytes.len(); Image::, Vec>::from_data_bytes( bytes, - if_zero_adjust(dimensions.into(), len), + dimensions.into(), Default::default(), ) .save(file) .context("writing image data to output file")? } cli::OutputFormat::ImageRgba16(dimensions) => { - let len = bytes.len(); Image::, Vec>::from_data_bytes( bytes, - if_zero_adjust(dimensions.into(), len), + dimensions.into(), Default::default(), ) .save(file) .context("writing image data to output file")? } cli::OutputFormat::ImageRgb32F(dimensions) => { - let len = bytes.len(); - Rgb32FImage::from_data_bytes( - bytes, - if_zero_adjust(dimensions.into(), len), - Default::default(), - ) - .save(file) - .context("writing image data to output file")? + Rgb32FImage::from_data_bytes(bytes, dimensions.into(), Default::default()) + .save(file) + .context("writing image data to output file")? } cli::OutputFormat::ImageRgba32F(dimensions) => { - let len = bytes.len(); - Rgba32FImage::from_data_bytes( - bytes, - if_zero_adjust(dimensions.into(), len), - Default::default(), - ) - .save(file) - .context("writing image data to output file")? - } - cli::OutputFormat::Bytes => { - File::bend_from(bytes, Box::new(file), Default::default()) - .context("writing to file")?; + Rgba32FImage::from_data_bytes(bytes, dimensions.into(), Default::default()) + .save(file) + .context("writing image data to output file")? } }; } cli::FileOrStd::Std(_) => Stdout::new() - .write_all(&bytes) + .write_all(&mut bytes) .context("writing to stdout")?, }; Ok(()) } - -fn if_zero_adjust(dimensions: Dimensions, bytes_len: usize) -> Dimensions { - if dimensions == Dimensions::square(0) { - Dimensions::square((bytes_len / 3).isqrt() as u32) - } else if dimensions.width == 0 { - Dimensions::square(dimensions.height) - } else if dimensions.height == 0 { - Dimensions::square(dimensions.width) - } else { - dimensions - } -}