mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 19:31:35 +00:00
Allow processing still images into animation formats
This commit is contained in:
parent
f3ef2d870b
commit
fd965bb1a5
4 changed files with 16 additions and 27 deletions
|
@ -107,9 +107,6 @@ pub(crate) enum UploadError {
|
||||||
#[error("pict-rs is in read-only mode")]
|
#[error("pict-rs is in read-only mode")]
|
||||||
ReadOnly,
|
ReadOnly,
|
||||||
|
|
||||||
#[error("Requested file extension cannot be served by source file")]
|
|
||||||
InvalidProcessExtension,
|
|
||||||
|
|
||||||
#[error("Provided process path is invalid")]
|
#[error("Provided process path is invalid")]
|
||||||
ParsePath,
|
ParsePath,
|
||||||
|
|
||||||
|
@ -173,7 +170,6 @@ impl UploadError {
|
||||||
}
|
}
|
||||||
Self::Download(_) => ErrorCode::DOWNLOAD_FILE_ERROR,
|
Self::Download(_) => ErrorCode::DOWNLOAD_FILE_ERROR,
|
||||||
Self::ReadOnly => ErrorCode::READ_ONLY,
|
Self::ReadOnly => ErrorCode::READ_ONLY,
|
||||||
Self::InvalidProcessExtension => ErrorCode::INVALID_FILE_EXTENSION,
|
|
||||||
Self::ParsePath => ErrorCode::INVALID_PROCESS_PATH,
|
Self::ParsePath => ErrorCode::INVALID_PROCESS_PATH,
|
||||||
Self::Semaphore => ErrorCode::PROCESS_SEMAPHORE_CLOSED,
|
Self::Semaphore => ErrorCode::PROCESS_SEMAPHORE_CLOSED,
|
||||||
Self::Canceled => ErrorCode::PANIC,
|
Self::Canceled => ErrorCode::PANIC,
|
||||||
|
@ -235,7 +231,6 @@ impl ResponseError for Error {
|
||||||
| UploadError::Repo(crate::repo::RepoError::AlreadyClaimed)
|
| UploadError::Repo(crate::repo::RepoError::AlreadyClaimed)
|
||||||
| UploadError::Validation(_)
|
| UploadError::Validation(_)
|
||||||
| UploadError::UnsupportedProcessExtension
|
| UploadError::UnsupportedProcessExtension
|
||||||
| UploadError::InvalidProcessExtension
|
|
||||||
| UploadError::ReadOnly
|
| UploadError::ReadOnly
|
||||||
| UploadError::FailedExternalValidation,
|
| UploadError::FailedExternalValidation,
|
||||||
) => StatusCode::BAD_REQUEST,
|
) => StatusCode::BAD_REQUEST,
|
||||||
|
|
|
@ -166,33 +166,31 @@ impl ProcessableFormat {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) const fn process_to(self, output: InputProcessableFormat) -> Option<Self> {
|
pub(crate) const fn process_to(self, output: InputProcessableFormat) -> Self {
|
||||||
match (self, output) {
|
match (self, output) {
|
||||||
(Self::Image(_), InputProcessableFormat::Avif) => Some(Self::Image(ImageFormat::Avif)),
|
(Self::Image(_), InputProcessableFormat::Avif) => Self::Image(ImageFormat::Avif),
|
||||||
(Self::Image(_) | Self::Animation(_), InputProcessableFormat::Jpeg) => {
|
(Self::Image(_) | Self::Animation(_), InputProcessableFormat::Jpeg) => {
|
||||||
Some(Self::Image(ImageFormat::Jpeg))
|
Self::Image(ImageFormat::Jpeg)
|
||||||
}
|
}
|
||||||
(Self::Image(_) | Self::Animation(_), InputProcessableFormat::Jxl) => {
|
(Self::Image(_) | Self::Animation(_), InputProcessableFormat::Jxl) => {
|
||||||
Some(Self::Image(ImageFormat::Jxl))
|
Self::Image(ImageFormat::Jxl)
|
||||||
}
|
}
|
||||||
(Self::Image(_) | Self::Animation(_), InputProcessableFormat::Png) => {
|
(Self::Image(_) | Self::Animation(_), InputProcessableFormat::Png) => {
|
||||||
Some(Self::Image(ImageFormat::Png))
|
Self::Image(ImageFormat::Png)
|
||||||
}
|
}
|
||||||
(Self::Image(_), InputProcessableFormat::Webp) => Some(Self::Image(ImageFormat::Webp)),
|
(Self::Image(_), InputProcessableFormat::Webp) => Self::Image(ImageFormat::Webp),
|
||||||
(Self::Animation(_), InputProcessableFormat::Apng) => {
|
(Self::Animation(_) | Self::Image(_), InputProcessableFormat::Apng) => {
|
||||||
Some(Self::Animation(AnimationFormat::Apng))
|
Self::Animation(AnimationFormat::Apng)
|
||||||
}
|
}
|
||||||
(Self::Animation(_), InputProcessableFormat::Avif) => {
|
(Self::Animation(_), InputProcessableFormat::Avif) => {
|
||||||
Some(Self::Animation(AnimationFormat::Avif))
|
Self::Animation(AnimationFormat::Avif)
|
||||||
}
|
}
|
||||||
(Self::Animation(_), InputProcessableFormat::Gif) => {
|
(Self::Animation(_) | Self::Image(_), InputProcessableFormat::Gif) => {
|
||||||
Some(Self::Animation(AnimationFormat::Gif))
|
Self::Animation(AnimationFormat::Gif)
|
||||||
}
|
}
|
||||||
(Self::Animation(_), InputProcessableFormat::Webp) => {
|
(Self::Animation(_), InputProcessableFormat::Webp) => {
|
||||||
Some(Self::Animation(AnimationFormat::Webp))
|
Self::Animation(AnimationFormat::Webp)
|
||||||
}
|
}
|
||||||
(Self::Image(_), InputProcessableFormat::Apng) => None,
|
|
||||||
(Self::Image(_), InputProcessableFormat::Gif) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -111,9 +111,7 @@ async fn process<S: Store + 'static>(
|
||||||
.processable_format()
|
.processable_format()
|
||||||
.expect("Already verified format is processable");
|
.expect("Already verified format is processable");
|
||||||
|
|
||||||
let format = input_format
|
let format = input_format.process_to(output_format);
|
||||||
.process_to(output_format)
|
|
||||||
.ok_or(UploadError::InvalidProcessExtension)?;
|
|
||||||
|
|
||||||
let quality = match format {
|
let quality = match format {
|
||||||
ProcessableFormat::Image(format) => media.image.quality_for(format),
|
ProcessableFormat::Image(format) => media.image.quality_for(format),
|
||||||
|
@ -178,9 +176,7 @@ where
|
||||||
{
|
{
|
||||||
let should_thumbnail =
|
let should_thumbnail =
|
||||||
if let Some(input_format) = original_details.internal_format().processable_format() {
|
if let Some(input_format) = original_details.internal_format().processable_format() {
|
||||||
let output_format = input_format
|
let output_format = input_format.process_to(output_format);
|
||||||
.process_to(output_format)
|
|
||||||
.ok_or(UploadError::InvalidProcessExtension)?;
|
|
||||||
|
|
||||||
input_format.should_thumbnail(output_format)
|
input_format.should_thumbnail(output_format)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -118,14 +118,14 @@ where
|
||||||
let quality = quality.map(|q| q.to_string());
|
let quality = quality.map(|q| q.to_string());
|
||||||
|
|
||||||
let len = 3
|
let len = 3
|
||||||
+ if format.coalesce() { 1 } else { 0 }
|
+ if input_format.coalesce() { 1 } else { 0 }
|
||||||
+ if quality.is_some() { 1 } else { 0 }
|
+ if quality.is_some() { 1 } else { 0 }
|
||||||
+ process_args.len();
|
+ process_args.len();
|
||||||
|
|
||||||
let mut args: Vec<&str> = Vec::with_capacity(len);
|
let mut args: Vec<&str> = Vec::with_capacity(len);
|
||||||
args.push("convert");
|
args.push("convert");
|
||||||
args.push(&input_arg);
|
args.push(&input_arg);
|
||||||
if format.coalesce() {
|
if input_format.coalesce() {
|
||||||
args.push("-coalesce");
|
args.push("-coalesce");
|
||||||
}
|
}
|
||||||
args.extend(process_args.iter().map(|s| s.as_str()));
|
args.extend(process_args.iter().map(|s| s.as_str()));
|
||||||
|
|
Loading…
Reference in a new issue