mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-12-22 19:31:35 +00:00
Add jpegxl and avif support
This commit is contained in:
parent
e925f2ba58
commit
6d2aef8cc0
5 changed files with 53 additions and 16 deletions
|
@ -121,7 +121,7 @@ Options:
|
|||
--media-filters <MEDIA_FILTERS>
|
||||
Which media filters should be enabled on the `process` endpoint
|
||||
--media-format <MEDIA_FORMAT>
|
||||
Enforce uploaded media is transcoded to the provided format [possible values: jpeg, webp, png]
|
||||
Enforce uploaded media is transcoded to the provided format [possible values: avif, jpeg, jxl, png, webp]
|
||||
-h, --help
|
||||
Print help information (use `--help` for more detail)
|
||||
```
|
||||
|
@ -383,7 +383,7 @@ pict-rs offers the following endpoints:
|
|||
aspect ratio. For example, a 1600x900 image cropped with a 1x1 aspect ratio will become 900x900. A
|
||||
1600x1100 image cropped with a 16x9 aspect ratio will become 1600x900.
|
||||
|
||||
Supported `ext` file extensions include `png`, `jpg`, and `webp`
|
||||
Supported `ext` file extensions include `avif`, `jpg`, `jxl`, `png`, and `webp`
|
||||
|
||||
An example of usage could be
|
||||
```
|
||||
|
|
|
@ -188,10 +188,10 @@ filters = ['blur', 'crop', 'identity', 'resize', 'thumbnail']
|
|||
# environment variable: PICTRS__MEDIA__FORMAT
|
||||
# default: empty
|
||||
#
|
||||
# available options: png, jpeg, webp
|
||||
# When set, all uploaded still images will be converted to this file type. If you care about file
|
||||
# size, setting this to 'webp' is probably the best option. By default, images are stored in their
|
||||
# original file type.
|
||||
# available options: avif, png, jpeg, jxl, webp
|
||||
# When set, all uploaded still images will be converted to this file type. For balancing quality vs
|
||||
# file size vs browser support, 'avif', 'jxl', and 'webp' should be considered. By default, images
|
||||
# are stored in their original file type.
|
||||
format = "webp"
|
||||
|
||||
## Optional: whether to validate images uploaded through the `import` endpoint
|
||||
|
|
|
@ -40,9 +40,11 @@ pub(crate) enum LogFormat {
|
|||
)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub(crate) enum ImageFormat {
|
||||
Avif,
|
||||
Jpeg,
|
||||
Webp,
|
||||
Jxl,
|
||||
Png,
|
||||
Webp,
|
||||
}
|
||||
|
||||
#[derive(
|
||||
|
@ -158,7 +160,9 @@ impl ImageFormat {
|
|||
|
||||
pub(crate) fn as_magick_format(self) -> &'static str {
|
||||
match self {
|
||||
Self::Avif => "AVIF",
|
||||
Self::Jpeg => "JPEG",
|
||||
Self::Jxl => "JXL",
|
||||
Self::Png => "PNG",
|
||||
Self::Webp => "WEBP",
|
||||
}
|
||||
|
@ -166,7 +170,9 @@ impl ImageFormat {
|
|||
|
||||
pub(crate) fn as_ext(self) -> &'static str {
|
||||
match self {
|
||||
Self::Avif => ".avif",
|
||||
Self::Jpeg => ".jpeg",
|
||||
Self::Jxl => ".jxl",
|
||||
Self::Png => ".png",
|
||||
Self::Webp => ".webp",
|
||||
}
|
||||
|
@ -243,7 +249,9 @@ impl FromStr for ImageFormat {
|
|||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s.to_lowercase().as_str() {
|
||||
"avif" => Ok(Self::Avif),
|
||||
"jpeg" | "jpg" => Ok(Self::Jpeg),
|
||||
"jxl" => Ok(Self::Jxl),
|
||||
"png" => Ok(Self::Png),
|
||||
"webp" => Ok(Self::Webp),
|
||||
other => Err(format!("Invalid variant: {other}")),
|
||||
|
|
|
@ -222,7 +222,9 @@ impl ValidInputType {
|
|||
Self::Gif => FileFormat::Video(VideoFormat::Gif),
|
||||
Self::Mp4 => FileFormat::Video(VideoFormat::Mp4),
|
||||
Self::Webm => FileFormat::Video(VideoFormat::Webm),
|
||||
Self::Avif => FileFormat::Image(ImageFormat::Avif),
|
||||
Self::Jpeg => FileFormat::Image(ImageFormat::Jpeg),
|
||||
Self::Jxl => FileFormat::Image(ImageFormat::Jxl),
|
||||
Self::Png => FileFormat::Image(ImageFormat::Png),
|
||||
Self::Webp => FileFormat::Image(ImageFormat::Webp),
|
||||
}
|
||||
|
@ -472,7 +474,7 @@ fn parse_details(output: std::borrow::Cow<'_, str>) -> Result<Option<Details>, E
|
|||
|
||||
for (k, v) in FORMAT_MAPPINGS {
|
||||
if formats.contains(k) {
|
||||
return Ok(Some(parse_details_inner(width, height, frames, *v)?));
|
||||
return parse_details_inner(width, height, frames, *v);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,17 +486,22 @@ fn parse_details_inner(
|
|||
height: &str,
|
||||
frames: &str,
|
||||
format: VideoFormat,
|
||||
) -> Result<Details, Error> {
|
||||
) -> Result<Option<Details>, Error> {
|
||||
let width = width.parse().map_err(|_| UploadError::UnsupportedFormat)?;
|
||||
let height = height.parse().map_err(|_| UploadError::UnsupportedFormat)?;
|
||||
let frames = frames.parse().map_err(|_| UploadError::UnsupportedFormat)?;
|
||||
|
||||
Ok(Details {
|
||||
// Probably a still image. ffmpeg thinks AVIF is an mp4
|
||||
if frames == 1 {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
Ok(Some(Details {
|
||||
mime_type: format.to_mime(),
|
||||
width,
|
||||
height,
|
||||
frames: Some(frames),
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
async fn pixel_format(input_file: &str) -> Result<String, Error> {
|
||||
|
|
|
@ -22,6 +22,14 @@ pub(crate) fn details_hint(alias: &Alias) -> Option<ValidInputType> {
|
|||
}
|
||||
}
|
||||
|
||||
fn image_avif() -> mime::Mime {
|
||||
"image/avif".parse().unwrap()
|
||||
}
|
||||
|
||||
fn image_jxl() -> mime::Mime {
|
||||
"image/jxl".parse().unwrap()
|
||||
}
|
||||
|
||||
fn image_webp() -> mime::Mime {
|
||||
"image/webp".parse().unwrap()
|
||||
}
|
||||
|
@ -39,8 +47,10 @@ pub(crate) enum ValidInputType {
|
|||
Mp4,
|
||||
Webm,
|
||||
Gif,
|
||||
Png,
|
||||
Avif,
|
||||
Jpeg,
|
||||
Jxl,
|
||||
Png,
|
||||
Webp,
|
||||
}
|
||||
|
||||
|
@ -50,8 +60,10 @@ impl ValidInputType {
|
|||
Self::Mp4 => "MP4",
|
||||
Self::Webm => "WEBM",
|
||||
Self::Gif => "GIF",
|
||||
Self::Png => "PNG",
|
||||
Self::Avif => "AVIF",
|
||||
Self::Jpeg => "JPEG",
|
||||
Self::Jxl => "JXL",
|
||||
Self::Png => "PNG",
|
||||
Self::Webp => "WEBP",
|
||||
}
|
||||
}
|
||||
|
@ -61,8 +73,10 @@ impl ValidInputType {
|
|||
Self::Mp4 => ".mp4",
|
||||
Self::Webm => ".webm",
|
||||
Self::Gif => ".gif",
|
||||
Self::Png => ".png",
|
||||
Self::Avif => ".avif",
|
||||
Self::Jpeg => ".jpeg",
|
||||
Self::Jxl => ".jxl",
|
||||
Self::Png => ".png",
|
||||
Self::Webp => ".webp",
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +103,9 @@ impl ValidInputType {
|
|||
|
||||
pub(crate) const fn from_format(format: ImageFormat) -> Self {
|
||||
match format {
|
||||
ImageFormat::Avif => ValidInputType::Avif,
|
||||
ImageFormat::Jpeg => ValidInputType::Jpeg,
|
||||
ImageFormat::Jxl => ValidInputType::Jxl,
|
||||
ImageFormat::Png => ValidInputType::Png,
|
||||
ImageFormat::Webp => ValidInputType::Webp,
|
||||
}
|
||||
|
@ -97,7 +113,9 @@ impl ValidInputType {
|
|||
|
||||
pub(crate) const fn to_format(self) -> Option<ImageFormat> {
|
||||
match self {
|
||||
Self::Avif => Some(ImageFormat::Avif),
|
||||
Self::Jpeg => Some(ImageFormat::Jpeg),
|
||||
Self::Jxl => Some(ImageFormat::Jxl),
|
||||
Self::Png => Some(ImageFormat::Png),
|
||||
Self::Webp => Some(ImageFormat::Webp),
|
||||
_ => None,
|
||||
|
@ -273,8 +291,10 @@ fn parse_details(s: std::borrow::Cow<'_, str>) -> Result<Details, Error> {
|
|||
"MP4" => video_mp4(),
|
||||
"WEBM" => video_webm(),
|
||||
"GIF" => mime::IMAGE_GIF,
|
||||
"PNG" => mime::IMAGE_PNG,
|
||||
"AVIF" => image_avif(),
|
||||
"JPEG" => mime::IMAGE_JPEG,
|
||||
"JXL" => image_jxl(),
|
||||
"PNG" => mime::IMAGE_PNG,
|
||||
"WEBP" => image_webp(),
|
||||
_ => return Err(UploadError::UnsupportedFormat.into()),
|
||||
};
|
||||
|
@ -343,8 +363,10 @@ impl Details {
|
|||
(mime::VIDEO, mime::MP4 | mime::MPEG) => ValidInputType::Mp4,
|
||||
(mime::VIDEO, subtype) if subtype.as_str() == "webm" => ValidInputType::Webm,
|
||||
(mime::IMAGE, mime::GIF) => ValidInputType::Gif,
|
||||
(mime::IMAGE, mime::PNG) => ValidInputType::Png,
|
||||
(mime::IMAGE, subtype) if subtype.as_str() == "avif" => ValidInputType::Avif,
|
||||
(mime::IMAGE, mime::JPEG) => ValidInputType::Jpeg,
|
||||
(mime::IMAGE, subtype) if subtype.as_str() == "jxl" => ValidInputType::Jxl,
|
||||
(mime::IMAGE, mime::PNG) => ValidInputType::Png,
|
||||
(mime::IMAGE, subtype) if subtype.as_str() == "webp" => ValidInputType::Webp,
|
||||
_ => return Err(UploadError::UnsupportedFormat.into()),
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue