pict-rs/src/magick.rs

90 lines
2.3 KiB
Rust
Raw Normal View History

2021-09-14 01:22:42 +00:00
use crate::{
formats::ProcessableFormat,
2023-07-10 20:29:41 +00:00
process::{Process, ProcessError},
store::Store,
2021-09-14 01:22:42 +00:00
};
use tokio::io::AsyncRead;
2023-07-10 20:29:41 +00:00
#[derive(Debug, thiserror::Error)]
pub(crate) enum MagickError {
#[error("Error in imagemagick process")]
Process(#[source] ProcessError),
#[error("Invalid output format")]
Json(#[source] serde_json::Error),
#[error("Error reading bytes")]
Read(#[source] std::io::Error),
#[error("Error writing bytes")]
Write(#[source] std::io::Error),
#[error("Error creating file")]
CreateFile(#[source] std::io::Error),
#[error("Error creating directory")]
CreateDir(#[source] crate::store::file_store::FileError),
#[error("Error closing file")]
CloseFile(#[source] std::io::Error),
#[error("Error removing file")]
RemoveFile(#[source] std::io::Error),
#[error("Invalid file path")]
Path,
}
impl MagickError {
pub(crate) fn is_client_error(&self) -> bool {
// Failing validation or imagemagick bailing probably means bad input
matches!(self, Self::Process(ProcessError::Status(_)))
2023-07-10 20:29:41 +00:00
}
}
fn process_image(
process_args: Vec<String>,
format: ProcessableFormat,
) -> Result<Process, ProcessError> {
2021-09-14 01:22:42 +00:00
let command = "magick";
let convert_args = ["convert", "-"];
let last_arg = format!("{}:-", format.magick_format());
2021-09-14 01:22:42 +00:00
let len = if format.coalesce() {
process_args.len() + 4
} else {
process_args.len() + 3
};
let mut args = Vec::with_capacity(len);
2023-07-10 20:29:41 +00:00
args.extend_from_slice(&convert_args[..]);
args.extend(process_args.iter().map(|s| s.as_str()));
if format.coalesce() {
args.push("-coalesce");
}
2023-07-10 20:29:41 +00:00
args.push(&last_arg);
Process::run(command, &args)
}
pub(crate) fn process_image_store_read<S: Store + 'static>(
store: S,
identifier: S::Identifier,
args: Vec<String>,
format: ProcessableFormat,
2023-07-10 20:29:41 +00:00
) -> Result<impl AsyncRead + Unpin, MagickError> {
Ok(process_image(args, format)
.map_err(MagickError::Process)?
.store_read(store, identifier))
}
pub(crate) fn process_image_async_read<A: AsyncRead + Unpin + 'static>(
async_read: A,
args: Vec<String>,
format: ProcessableFormat,
2023-07-10 20:29:41 +00:00
) -> Result<impl AsyncRead + Unpin, MagickError> {
Ok(process_image(args, format)
.map_err(MagickError::Process)?
.pipe_async_read(async_read))
}