mirror of
https://git.asonix.dog/asonix/pict-rs
synced 2024-11-20 11:21:14 +00:00
Use json for ffmpeg, imagemagick details parsing
This commit is contained in:
parent
fa74e3c82d
commit
1694f49436
23 changed files with 11742 additions and 99 deletions
|
@ -66,6 +66,9 @@ pub(crate) enum UploadError {
|
|||
#[error("Error in store")]
|
||||
Store(#[source] crate::store::StoreError),
|
||||
|
||||
#[error("Error parsing image details")]
|
||||
ParseDetails(#[from] crate::magick::ParseDetailsError),
|
||||
|
||||
#[error("Provided process path is invalid")]
|
||||
ParsePath,
|
||||
|
||||
|
|
123
src/ffmpeg.rs
123
src/ffmpeg.rs
|
@ -1,3 +1,6 @@
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::{
|
||||
config::{AudioCodec, ImageFormat, MediaConfiguration, VideoCodec},
|
||||
error::{Error, UploadError},
|
||||
|
@ -368,6 +371,22 @@ pub(crate) async fn details_bytes(input: Bytes) -> Result<Option<Details>, Error
|
|||
.await
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct PixelFormatOutput {
|
||||
pixel_formats: Vec<PixelFormat>,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct PixelFormat {
|
||||
name: String,
|
||||
flags: Flags,
|
||||
}
|
||||
|
||||
#[derive(serde::Deserialize)]
|
||||
struct Flags {
|
||||
alpha: usize,
|
||||
}
|
||||
|
||||
async fn alpha_pixel_formats() -> Result<HashSet<String>, Error> {
|
||||
let process = Process::run(
|
||||
"ffprobe",
|
||||
|
@ -378,33 +397,49 @@ async fn alpha_pixel_formats() -> Result<HashSet<String>, Error> {
|
|||
"pixel_format=name:flags=alpha",
|
||||
"-of",
|
||||
"compact=p=0",
|
||||
"-print_format",
|
||||
"json",
|
||||
],
|
||||
)?;
|
||||
|
||||
let mut output = Vec::new();
|
||||
process.read().read_to_end(&mut output).await?;
|
||||
let output = String::from_utf8_lossy(&output);
|
||||
let formats = output
|
||||
.split('\n')
|
||||
.filter_map(|format| {
|
||||
if format.is_empty() {
|
||||
|
||||
let formats: PixelFormatOutput = serde_json::from_slice(&output)?;
|
||||
|
||||
Ok(parse_pixel_formats(formats))
|
||||
}
|
||||
|
||||
fn parse_pixel_formats(formats: PixelFormatOutput) -> HashSet<String> {
|
||||
formats
|
||||
.pixel_formats
|
||||
.into_iter()
|
||||
.filter_map(|PixelFormat { name, flags }| {
|
||||
if flags.alpha == 0 {
|
||||
return None;
|
||||
}
|
||||
|
||||
if !format.ends_with('1') {
|
||||
return None;
|
||||
}
|
||||
|
||||
Some(
|
||||
format
|
||||
.trim_start_matches("name=")
|
||||
.trim_end_matches("|flags:alpha=1")
|
||||
.to_string(),
|
||||
)
|
||||
Some(name)
|
||||
})
|
||||
.collect();
|
||||
.collect()
|
||||
}
|
||||
|
||||
Ok(formats)
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct DetailsOutput {
|
||||
streams: [Stream; 1],
|
||||
format: Format,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct Stream {
|
||||
width: usize,
|
||||
height: usize,
|
||||
nb_read_frames: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct Format {
|
||||
format_name: String,
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(f))]
|
||||
|
@ -435,46 +470,35 @@ where
|
|||
"stream=width,height,nb_read_frames:format=format_name",
|
||||
"-of",
|
||||
"default=noprint_wrappers=1:nokey=1",
|
||||
"-print_format",
|
||||
"json",
|
||||
input_file_str,
|
||||
],
|
||||
)?;
|
||||
|
||||
let mut output = Vec::new();
|
||||
process.read().read_to_end(&mut output).await?;
|
||||
let output = String::from_utf8_lossy(&output);
|
||||
tokio::fs::remove_file(input_file_str).await?;
|
||||
|
||||
let output: DetailsOutput = serde_json::from_slice(&output)?;
|
||||
|
||||
parse_details(output)
|
||||
}
|
||||
|
||||
fn parse_details(output: std::borrow::Cow<'_, str>) -> Result<Option<Details>, Error> {
|
||||
tracing::debug!("OUTPUT: {}", output);
|
||||
fn parse_details(output: DetailsOutput) -> Result<Option<Details>, Error> {
|
||||
tracing::debug!("OUTPUT: {:?}", output);
|
||||
|
||||
let mut lines = output.lines();
|
||||
|
||||
let width = match lines.next() {
|
||||
Some(line) => line,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let height = match lines.next() {
|
||||
Some(line) => line,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let frames = match lines.next() {
|
||||
Some(line) => line,
|
||||
None => return Ok(None),
|
||||
};
|
||||
|
||||
let formats = match lines.next() {
|
||||
Some(line) => line,
|
||||
None => return Ok(None),
|
||||
};
|
||||
let [stream] = output.streams;
|
||||
let Format { format_name } = output.format;
|
||||
|
||||
for (k, v) in FORMAT_MAPPINGS {
|
||||
if formats.contains(k) {
|
||||
return parse_details_inner(width, height, frames, *v);
|
||||
if format_name.contains(k) {
|
||||
return parse_details_inner(
|
||||
stream.width,
|
||||
stream.height,
|
||||
stream.nb_read_frames.as_deref(),
|
||||
*v,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -482,14 +506,15 @@ fn parse_details(output: std::borrow::Cow<'_, str>) -> Result<Option<Details>, E
|
|||
}
|
||||
|
||||
fn parse_details_inner(
|
||||
width: &str,
|
||||
height: &str,
|
||||
frames: &str,
|
||||
width: usize,
|
||||
height: usize,
|
||||
frames: Option<&str>,
|
||||
format: VideoFormat,
|
||||
) -> 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)?;
|
||||
let frames = frames
|
||||
.map(|frames| frames.parse().map_err(|_| UploadError::UnsupportedFormat))
|
||||
.transpose()?
|
||||
.unwrap_or(1);
|
||||
|
||||
// Probably a still image. ffmpeg thinks AVIF is an mp4
|
||||
if frames == 1 {
|
||||
|
|
15
src/ffmpeg/ffprobe_6_0_avif_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_avif_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"nb_read_frames": "1"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "mov,mp4,m4a,3gp,3g2,mj2"
|
||||
}
|
||||
}
|
15
src/ffmpeg/ffprobe_6_0_gif_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_gif_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 160,
|
||||
"height": 227,
|
||||
"nb_read_frames": "28"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "gif"
|
||||
}
|
||||
}
|
15
src/ffmpeg/ffprobe_6_0_jpeg_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_jpeg_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"nb_read_frames": "1"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "image2"
|
||||
}
|
||||
}
|
14
src/ffmpeg/ffprobe_6_0_jxl_details.json
Normal file
14
src/ffmpeg/ffprobe_6_0_jxl_details.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 0,
|
||||
"height": 0
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "jpegxl_pipe"
|
||||
}
|
||||
}
|
15
src/ffmpeg/ffprobe_6_0_mp4_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_mp4_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 852,
|
||||
"height": 480,
|
||||
"nb_read_frames": "35364"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "mov,mp4,m4a,3gp,3g2,mj2"
|
||||
}
|
||||
}
|
1336
src/ffmpeg/ffprobe_6_0_pixel_formats.json
Normal file
1336
src/ffmpeg/ffprobe_6_0_pixel_formats.json
Normal file
File diff suppressed because it is too large
Load diff
15
src/ffmpeg/ffprobe_6_0_png_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_png_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 450,
|
||||
"height": 401,
|
||||
"nb_read_frames": "1"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "png_pipe"
|
||||
}
|
||||
}
|
15
src/ffmpeg/ffprobe_6_0_webm_av1_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_webm_av1_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 112,
|
||||
"height": 112,
|
||||
"nb_read_frames": "27"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "matroska,webm"
|
||||
}
|
||||
}
|
15
src/ffmpeg/ffprobe_6_0_webm_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_webm_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 640,
|
||||
"height": 480,
|
||||
"nb_read_frames": "34650"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "matroska,webm"
|
||||
}
|
||||
}
|
15
src/ffmpeg/ffprobe_6_0_webp_details.json
Normal file
15
src/ffmpeg/ffprobe_6_0_webp_details.json
Normal file
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"programs": [
|
||||
|
||||
],
|
||||
"streams": [
|
||||
{
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"nb_read_frames": "1"
|
||||
}
|
||||
],
|
||||
"format": {
|
||||
"format_name": "webp_pipe"
|
||||
}
|
||||
}
|
132
src/ffmpeg/tests.rs
Normal file
132
src/ffmpeg/tests.rs
Normal file
|
@ -0,0 +1,132 @@
|
|||
use super::{Details, DetailsOutput, PixelFormatOutput};
|
||||
|
||||
fn details_tests() -> [(&'static str, Option<Details>); 9] {
|
||||
[
|
||||
("avif", None),
|
||||
(
|
||||
"gif",
|
||||
Some(Details {
|
||||
mime_type: mime::IMAGE_GIF,
|
||||
width: 160,
|
||||
height: 227,
|
||||
frames: Some(28),
|
||||
}),
|
||||
),
|
||||
("jpeg", None),
|
||||
("jxl", None),
|
||||
(
|
||||
"mp4",
|
||||
Some(Details {
|
||||
mime_type: crate::magick::video_mp4(),
|
||||
width: 852,
|
||||
height: 480,
|
||||
frames: Some(35364),
|
||||
}),
|
||||
),
|
||||
("png", None),
|
||||
(
|
||||
"webm",
|
||||
Some(Details {
|
||||
mime_type: crate::magick::video_webm(),
|
||||
width: 640,
|
||||
height: 480,
|
||||
frames: Some(34650),
|
||||
}),
|
||||
),
|
||||
(
|
||||
"webm_av1",
|
||||
Some(Details {
|
||||
mime_type: crate::magick::video_webm(),
|
||||
width: 112,
|
||||
height: 112,
|
||||
frames: Some(27),
|
||||
}),
|
||||
),
|
||||
("webp", None),
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_details() {
|
||||
for (case, expected) in details_tests() {
|
||||
let string =
|
||||
std::fs::read_to_string(format!("./src/ffmpeg/ffprobe_6_0_{case}_details.json"))
|
||||
.expect("Read file");
|
||||
|
||||
let json: DetailsOutput = serde_json::from_str(&string).expect("Valid json");
|
||||
|
||||
let output = super::parse_details(json).expect("Parsed details");
|
||||
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
}
|
||||
|
||||
const ALPHA_PIXEL_FORMATS: &[&str] = &[
|
||||
"pal8",
|
||||
"argb",
|
||||
"rgba",
|
||||
"abgr",
|
||||
"bgra",
|
||||
"yuva420p",
|
||||
"ya8",
|
||||
"yuva422p",
|
||||
"yuva444p",
|
||||
"yuva420p9be",
|
||||
"yuva420p9le",
|
||||
"yuva422p9be",
|
||||
"yuva422p9le",
|
||||
"yuva444p9be",
|
||||
"yuva444p9le",
|
||||
"yuva420p10be",
|
||||
"yuva420p10le",
|
||||
"yuva422p10be",
|
||||
"yuva422p10le",
|
||||
"yuva444p10be",
|
||||
"yuva444p10le",
|
||||
"yuva420p16be",
|
||||
"yuva420p16le",
|
||||
"yuva422p16be",
|
||||
"yuva422p16le",
|
||||
"yuva444p16be",
|
||||
"yuva444p16le",
|
||||
"rgba64be",
|
||||
"rgba64le",
|
||||
"bgra64be",
|
||||
"bgra64le",
|
||||
"ya16be",
|
||||
"ya16le",
|
||||
"gbrap",
|
||||
"gbrap16be",
|
||||
"gbrap16le",
|
||||
"ayuv64le",
|
||||
"ayuv64be",
|
||||
"gbrap12be",
|
||||
"gbrap12le",
|
||||
"gbrap10be",
|
||||
"gbrap10le",
|
||||
"gbrapf32be",
|
||||
"gbrapf32le",
|
||||
"yuva422p12be",
|
||||
"yuva422p12le",
|
||||
"yuva444p12be",
|
||||
"yuva444p12le",
|
||||
"vuya",
|
||||
"rgbaf16be",
|
||||
"rgbaf16le",
|
||||
"rgbaf32be",
|
||||
"rgbaf32le",
|
||||
];
|
||||
|
||||
#[test]
|
||||
fn parse_pixel_formats() {
|
||||
let formats =
|
||||
std::fs::read_to_string("./src/ffmpeg/ffprobe_6_0_pixel_formats.json").expect("Read file");
|
||||
|
||||
let json: PixelFormatOutput = serde_json::from_str(&formats).expect("Valid json");
|
||||
|
||||
let output = super::parse_pixel_formats(json);
|
||||
|
||||
for format in ALPHA_PIXEL_FORMATS {
|
||||
assert!(output.contains(*format), "Doesn't contain {format}");
|
||||
}
|
||||
}
|
115
src/magick.rs
115
src/magick.rs
|
@ -1,3 +1,6 @@
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
use crate::{
|
||||
config::{ImageFormat, VideoCodec},
|
||||
error::{Error, UploadError},
|
||||
|
@ -123,7 +126,7 @@ impl ValidInputType {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub(crate) struct Details {
|
||||
pub(crate) mime_type: mime::Mime,
|
||||
pub(crate) width: usize,
|
||||
|
@ -175,18 +178,33 @@ pub(crate) async fn details_bytes(
|
|||
"-".to_owned()
|
||||
};
|
||||
|
||||
let process = Process::run(
|
||||
"magick",
|
||||
&["identify", "-ping", "-format", "%w %h | %m\n", &last_arg],
|
||||
)?;
|
||||
let process = Process::run("magick", &["convert", "-ping", &last_arg, "JSON:"])?;
|
||||
|
||||
let mut reader = process.bytes_read(input);
|
||||
|
||||
let mut bytes = Vec::new();
|
||||
reader.read_to_end(&mut bytes).await?;
|
||||
let s = String::from_utf8_lossy(&bytes);
|
||||
|
||||
parse_details(s)
|
||||
let details_output: Vec<DetailsOutput> = serde_json::from_slice(&bytes)?;
|
||||
|
||||
parse_details(details_output)
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct DetailsOutput {
|
||||
image: Image,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct Image {
|
||||
format: String,
|
||||
geometry: Geometry,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
struct Geometry {
|
||||
width: usize,
|
||||
height: usize,
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(store))]
|
||||
|
@ -217,27 +235,21 @@ pub(crate) async fn details_store<S: Store + 'static>(
|
|||
"-".to_owned()
|
||||
};
|
||||
|
||||
let process = Process::run(
|
||||
"magick",
|
||||
&["identify", "-ping", "-format", "%w %h | %m\n", &last_arg],
|
||||
)?;
|
||||
let process = Process::run("magick", &["convert", "-ping", &last_arg, "JSON:"])?;
|
||||
|
||||
let mut reader = process.store_read(store, identifier);
|
||||
|
||||
let mut output = Vec::new();
|
||||
reader.read_to_end(&mut output).await?;
|
||||
|
||||
let s = String::from_utf8_lossy(&output);
|
||||
let details_output: Vec<DetailsOutput> = serde_json::from_slice(&output)?;
|
||||
|
||||
parse_details(s)
|
||||
parse_details(details_output)
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
pub(crate) async fn details_file(path_str: &str) -> Result<Details, Error> {
|
||||
let process = Process::run(
|
||||
"magick",
|
||||
&["identify", "-ping", "-format", "%w %h | %m\n", path_str],
|
||||
)?;
|
||||
let process = Process::run("magick", &["convert", "-ping", path_str, "JSON:"])?;
|
||||
|
||||
let mut reader = process.read();
|
||||
|
||||
|
@ -245,46 +257,49 @@ pub(crate) async fn details_file(path_str: &str) -> Result<Details, Error> {
|
|||
reader.read_to_end(&mut output).await?;
|
||||
tokio::fs::remove_file(path_str).await?;
|
||||
|
||||
let s = String::from_utf8_lossy(&output);
|
||||
let details_output: Vec<DetailsOutput> = serde_json::from_slice(&output)?;
|
||||
|
||||
parse_details(s)
|
||||
parse_details(details_output)
|
||||
}
|
||||
|
||||
fn parse_details(s: std::borrow::Cow<'_, str>) -> Result<Details, Error> {
|
||||
let frames = s.lines().count();
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub(crate) enum ParseDetailsError {
|
||||
#[error("No frames present in image")]
|
||||
NoFrames,
|
||||
|
||||
let mut lines = s.lines();
|
||||
let first = lines.next().ok_or(UploadError::UnsupportedFormat)?;
|
||||
#[error("Multiple image formats used in same file")]
|
||||
MixedFormats,
|
||||
|
||||
let mut segments = first.split('|');
|
||||
#[error("Format is unsupported: {0}")]
|
||||
Unsupported(String),
|
||||
}
|
||||
|
||||
let dimensions = segments
|
||||
.next()
|
||||
.ok_or(UploadError::UnsupportedFormat)?
|
||||
.trim();
|
||||
tracing::debug!("dimensions: {}", dimensions);
|
||||
let mut dims = dimensions.split(' ');
|
||||
let width = dims
|
||||
.next()
|
||||
.ok_or(UploadError::UnsupportedFormat)?
|
||||
.trim()
|
||||
.parse()
|
||||
.map_err(|_| UploadError::UnsupportedFormat)?;
|
||||
let height = dims
|
||||
.next()
|
||||
.ok_or(UploadError::UnsupportedFormat)?
|
||||
.trim()
|
||||
.parse()
|
||||
.map_err(|_| UploadError::UnsupportedFormat)?;
|
||||
fn parse_details(details_output: Vec<DetailsOutput>) -> Result<Details, Error> {
|
||||
let frames = details_output.len();
|
||||
|
||||
let format = segments
|
||||
.next()
|
||||
.ok_or(UploadError::UnsupportedFormat)?
|
||||
.trim();
|
||||
if frames == 0 {
|
||||
return Err(ParseDetailsError::NoFrames.into());
|
||||
}
|
||||
|
||||
let width = details_output
|
||||
.iter()
|
||||
.map(|details| details.image.geometry.width)
|
||||
.max()
|
||||
.expect("Nonempty vector");
|
||||
let height = details_output
|
||||
.iter()
|
||||
.map(|details| details.image.geometry.height)
|
||||
.max()
|
||||
.expect("Nonempty vector");
|
||||
|
||||
let format = details_output[0].image.format.as_str();
|
||||
tracing::debug!("format: {}", format);
|
||||
|
||||
if !lines.all(|item| item.ends_with(format)) {
|
||||
return Err(UploadError::UnsupportedFormat.into());
|
||||
if !details_output
|
||||
.iter()
|
||||
.all(|details| &details.image.format == format)
|
||||
{
|
||||
return Err(ParseDetailsError::MixedFormats.into());
|
||||
}
|
||||
|
||||
let mime_type = match format {
|
||||
|
@ -296,7 +311,7 @@ fn parse_details(s: std::borrow::Cow<'_, str>) -> Result<Details, Error> {
|
|||
"JXL" => image_jxl(),
|
||||
"PNG" => mime::IMAGE_PNG,
|
||||
"WEBP" => image_webp(),
|
||||
_ => return Err(UploadError::UnsupportedFormat.into()),
|
||||
e => return Err(ParseDetailsError::Unsupported(String::from(e)).into()),
|
||||
};
|
||||
|
||||
Ok(Details {
|
||||
|
@ -368,7 +383,7 @@ impl Details {
|
|||
(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()),
|
||||
_ => return Err(ParseDetailsError::Unsupported(self.mime_type.to_string()).into()),
|
||||
};
|
||||
|
||||
Ok(input_type)
|
||||
|
|
122
src/magick/magick_7_1_1_avif_details.json
Normal file
122
src/magick/magick_7_1_1_avif_details.json
Normal file
|
@ -0,0 +1,122 @@
|
|||
[{
|
||||
"version": "1.0",
|
||||
"image": {
|
||||
"name": "out.avif",
|
||||
"baseName": "out.avif",
|
||||
"permissions": 644,
|
||||
"format": "AVIF",
|
||||
"formatDescription": "AV1 Image File Format",
|
||||
"mimeType": "image/avif",
|
||||
"class": "DirectClass",
|
||||
"geometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"units": "Undefined",
|
||||
"type": "Bilevel",
|
||||
"baseType": "Undefined",
|
||||
"endianness": "Undefined",
|
||||
"colorspace": "sRGB",
|
||||
"depth": 1,
|
||||
"baseDepth": 8,
|
||||
"channelDepth": {
|
||||
"red": 1,
|
||||
"green": 1,
|
||||
"blue": 1
|
||||
},
|
||||
"pixels": 6220800,
|
||||
"imageStatistics": {
|
||||
"Overall": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"channelStatistics": {
|
||||
"red": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"green": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"blue": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"renderingIntent": "Perceptual",
|
||||
"gamma": 0.454545,
|
||||
"chromaticity": {
|
||||
"redPrimary": {
|
||||
"x": 0.64,
|
||||
"y": 0.33
|
||||
},
|
||||
"greenPrimary": {
|
||||
"x": 0.3,
|
||||
"y": 0.6
|
||||
},
|
||||
"bluePrimary": {
|
||||
"x": 0.15,
|
||||
"y": 0.06
|
||||
},
|
||||
"whitePrimary": {
|
||||
"x": 0.3127,
|
||||
"y": 0.329
|
||||
}
|
||||
},
|
||||
"matteColor": "#BDBDBDBDBDBD",
|
||||
"backgroundColor": "#FFFFFFFFFFFF",
|
||||
"borderColor": "#DFDFDFDFDFDF",
|
||||
"transparentColor": "#000000000000",
|
||||
"interlace": "None",
|
||||
"intensity": "Undefined",
|
||||
"compose": "Over",
|
||||
"pageGeometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"dispose": "Undefined",
|
||||
"iterations": 0,
|
||||
"compression": "Undefined",
|
||||
"orientation": "TopLeft",
|
||||
"properties": {
|
||||
"signature": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"tainted": false,
|
||||
"filesize": "8427B",
|
||||
"numberPixels": "2.0736M",
|
||||
"pixelsPerSecond": "9.82581GB",
|
||||
"userTime": "0.000u",
|
||||
"elapsedTime": "0:01.000",
|
||||
"version": "ImageMagick 7.1.1-11 Q16-HDRI x86_64 f04a7eb33:20230528 https://imagemagick.org"
|
||||
}
|
||||
}]
|
3269
src/magick/magick_7_1_1_gif_details.json
Normal file
3269
src/magick/magick_7_1_1_gif_details.json
Normal file
File diff suppressed because it is too large
Load diff
125
src/magick/magick_7_1_1_jpeg_details.json
Normal file
125
src/magick/magick_7_1_1_jpeg_details.json
Normal file
|
@ -0,0 +1,125 @@
|
|||
[{
|
||||
"version": "1.0",
|
||||
"image": {
|
||||
"name": "out.jpg",
|
||||
"baseName": "out.jpg",
|
||||
"permissions": 644,
|
||||
"format": "JPEG",
|
||||
"formatDescription": "Joint Photographic Experts Group JFIF format",
|
||||
"mimeType": "image/jpeg",
|
||||
"class": "DirectClass",
|
||||
"geometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"units": "Undefined",
|
||||
"type": "Bilevel",
|
||||
"baseType": "Undefined",
|
||||
"endianness": "Undefined",
|
||||
"colorspace": "sRGB",
|
||||
"depth": 1,
|
||||
"baseDepth": 8,
|
||||
"channelDepth": {
|
||||
"red": 1,
|
||||
"green": 1,
|
||||
"blue": 1
|
||||
},
|
||||
"pixels": 6220800,
|
||||
"imageStatistics": {
|
||||
"Overall": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"channelStatistics": {
|
||||
"red": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"green": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"blue": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"renderingIntent": "Perceptual",
|
||||
"gamma": 0.454545,
|
||||
"chromaticity": {
|
||||
"redPrimary": {
|
||||
"x": 0.64,
|
||||
"y": 0.33
|
||||
},
|
||||
"greenPrimary": {
|
||||
"x": 0.3,
|
||||
"y": 0.6
|
||||
},
|
||||
"bluePrimary": {
|
||||
"x": 0.15,
|
||||
"y": 0.06
|
||||
},
|
||||
"whitePrimary": {
|
||||
"x": 0.3127,
|
||||
"y": 0.329
|
||||
}
|
||||
},
|
||||
"matteColor": "#BDBDBDBDBDBD",
|
||||
"backgroundColor": "#FFFFFFFFFFFF",
|
||||
"borderColor": "#DFDFDFDFDFDF",
|
||||
"transparentColor": "#000000000000",
|
||||
"interlace": "None",
|
||||
"intensity": "Undefined",
|
||||
"compose": "Over",
|
||||
"pageGeometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"dispose": "Undefined",
|
||||
"iterations": 0,
|
||||
"compression": "JPEG",
|
||||
"quality": 92,
|
||||
"orientation": "Undefined",
|
||||
"properties": {
|
||||
"jpeg:colorspace": "2",
|
||||
"jpeg:sampling-factor": "1x1,1x1,1x1",
|
||||
"signature": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"tainted": false,
|
||||
"filesize": "93100B",
|
||||
"numberPixels": "2.0736M",
|
||||
"pixelsPerSecond": "12.0946GB",
|
||||
"userTime": "0.000u",
|
||||
"elapsedTime": "0:01.000",
|
||||
"version": "ImageMagick 7.1.1-11 Q16-HDRI x86_64 f04a7eb33:20230528 https://imagemagick.org"
|
||||
}
|
||||
}]
|
122
src/magick/magick_7_1_1_jxl_details.json
Normal file
122
src/magick/magick_7_1_1_jxl_details.json
Normal file
|
@ -0,0 +1,122 @@
|
|||
[{
|
||||
"version": "1.0",
|
||||
"image": {
|
||||
"name": "out.jxl",
|
||||
"baseName": "out.jxl",
|
||||
"permissions": 644,
|
||||
"format": "JXL",
|
||||
"formatDescription": "JPEG XL (ISO/IEC 18181)",
|
||||
"mimeType": "image/jxl",
|
||||
"class": "DirectClass",
|
||||
"geometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"units": "Undefined",
|
||||
"type": "Bilevel",
|
||||
"baseType": "Undefined",
|
||||
"endianness": "Undefined",
|
||||
"colorspace": "sRGB",
|
||||
"depth": 1,
|
||||
"baseDepth": 8,
|
||||
"channelDepth": {
|
||||
"red": 1,
|
||||
"green": 1,
|
||||
"blue": 1
|
||||
},
|
||||
"pixels": 6220800,
|
||||
"imageStatistics": {
|
||||
"Overall": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"channelStatistics": {
|
||||
"red": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"green": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"blue": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"renderingIntent": "Perceptual",
|
||||
"gamma": 0.454545,
|
||||
"chromaticity": {
|
||||
"redPrimary": {
|
||||
"x": 0.64,
|
||||
"y": 0.33
|
||||
},
|
||||
"greenPrimary": {
|
||||
"x": 0.3,
|
||||
"y": 0.6
|
||||
},
|
||||
"bluePrimary": {
|
||||
"x": 0.15,
|
||||
"y": 0.06
|
||||
},
|
||||
"whitePrimary": {
|
||||
"x": 0.3127,
|
||||
"y": 0.329
|
||||
}
|
||||
},
|
||||
"matteColor": "#BDBDBDBDBDBD",
|
||||
"backgroundColor": "#FFFFFFFFFFFF",
|
||||
"borderColor": "#DFDFDFDFDFDF",
|
||||
"transparentColor": "#000000000000",
|
||||
"interlace": "None",
|
||||
"intensity": "Undefined",
|
||||
"compose": "Over",
|
||||
"pageGeometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"dispose": "Undefined",
|
||||
"iterations": 0,
|
||||
"compression": "Undefined",
|
||||
"orientation": "TopLeft",
|
||||
"properties": {
|
||||
"signature": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"tainted": false,
|
||||
"filesize": "42934B",
|
||||
"numberPixels": "2.0736M",
|
||||
"pixelsPerSecond": "3.79105GB",
|
||||
"userTime": "0.000u",
|
||||
"elapsedTime": "0:01.000",
|
||||
"version": "ImageMagick 7.1.1-11 Q16-HDRI x86_64 f04a7eb33:20230528 https://imagemagick.org"
|
||||
}
|
||||
}]
|
2305
src/magick/magick_7_1_1_mp4_details.json
Normal file
2305
src/magick/magick_7_1_1_mp4_details.json
Normal file
File diff suppressed because it is too large
Load diff
158
src/magick/magick_7_1_1_png_details.json
Normal file
158
src/magick/magick_7_1_1_png_details.json
Normal file
|
@ -0,0 +1,158 @@
|
|||
[{
|
||||
"version": "1.0",
|
||||
"image": {
|
||||
"name": "/home/asonix/Pictures/shenzi/Bad_under_Mufasa.png",
|
||||
"baseName": "Bad_under_Mufasa.png",
|
||||
"permissions": 644,
|
||||
"format": "PNG",
|
||||
"formatDescription": "Portable Network Graphics",
|
||||
"mimeType": "image/png",
|
||||
"class": "DirectClass",
|
||||
"geometry": {
|
||||
"width": 497,
|
||||
"height": 694,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"resolution": {
|
||||
"x": 118.11,
|
||||
"y": 118.11
|
||||
},
|
||||
"printSize": {
|
||||
"x": 4.20794,
|
||||
"y": 5.87588
|
||||
},
|
||||
"units": "PixelsPerCentimeter",
|
||||
"type": "Bilevel",
|
||||
"baseType": "Undefined",
|
||||
"endianness": "Undefined",
|
||||
"colorspace": "sRGB",
|
||||
"depth": 1,
|
||||
"baseDepth": 8,
|
||||
"channelDepth": {
|
||||
"alpha": 1,
|
||||
"red": 1,
|
||||
"green": 1,
|
||||
"blue": 1
|
||||
},
|
||||
"pixels": 1379672,
|
||||
"imageStatistics": {
|
||||
"Overall": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"channelStatistics": {
|
||||
"alpha": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"red": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"green": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
},
|
||||
"blue": {
|
||||
"min": 0,
|
||||
"max": 0,
|
||||
"mean": 0,
|
||||
"median": 0,
|
||||
"standardDeviation": 0,
|
||||
"kurtosis": -3,
|
||||
"skewness": 0,
|
||||
"entropy": 0
|
||||
}
|
||||
},
|
||||
"alpha": "#00000000",
|
||||
"renderingIntent": "Perceptual",
|
||||
"gamma": 0.454545,
|
||||
"chromaticity": {
|
||||
"redPrimary": {
|
||||
"x": 0.64,
|
||||
"y": 0.33
|
||||
},
|
||||
"greenPrimary": {
|
||||
"x": 0.3,
|
||||
"y": 0.6
|
||||
},
|
||||
"bluePrimary": {
|
||||
"x": 0.15,
|
||||
"y": 0.06
|
||||
},
|
||||
"whitePrimary": {
|
||||
"x": 0.3127,
|
||||
"y": 0.329
|
||||
}
|
||||
},
|
||||
"matteColor": "#BDBDBDBDBDBD",
|
||||
"backgroundColor": "#FFFFFFFFFFFF",
|
||||
"borderColor": "#DFDFDFDFDFDF",
|
||||
"transparentColor": "#000000000000",
|
||||
"interlace": "None",
|
||||
"intensity": "Undefined",
|
||||
"compose": "Over",
|
||||
"pageGeometry": {
|
||||
"width": 497,
|
||||
"height": 694,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"dispose": "Undefined",
|
||||
"iterations": 0,
|
||||
"compression": "Zip",
|
||||
"orientation": "Undefined",
|
||||
"properties": {
|
||||
"icc:copyright": "Public Domain",
|
||||
"icc:description": "Glimpse built-in sRGB",
|
||||
"icc:manufacturer": "GIMP",
|
||||
"icc:model": "sRGB",
|
||||
"png:IHDR.bit-depth-orig": "8",
|
||||
"png:IHDR.bit_depth": "8",
|
||||
"png:IHDR.color-type-orig": "6",
|
||||
"png:IHDR.color_type": "6 (RGBA)",
|
||||
"png:IHDR.interlace_method": "0 (Not interlaced)",
|
||||
"png:IHDR.width,height": "497, 694",
|
||||
"png:tIME": "2020-09-03T00:14:24Z",
|
||||
"signature": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"profiles": {
|
||||
"icc": {
|
||||
"length": 680
|
||||
}
|
||||
},
|
||||
"tainted": false,
|
||||
"filesize": "269655B",
|
||||
"numberPixels": "344918",
|
||||
"pixelsPerSecond": "1.13565GB",
|
||||
"userTime": "0.000u",
|
||||
"elapsedTime": "0:01.000",
|
||||
"version": "ImageMagick 7.1.1-11 Q16-HDRI x86_64 f04a7eb33:20230528 https://imagemagick.org"
|
||||
}
|
||||
}]
|
3682
src/magick/magick_7_1_1_webm_details.json
Normal file
3682
src/magick/magick_7_1_1_webm_details.json
Normal file
File diff suppressed because it is too large
Load diff
122
src/magick/magick_7_1_1_webp_details.json
Normal file
122
src/magick/magick_7_1_1_webp_details.json
Normal file
|
@ -0,0 +1,122 @@
|
|||
[{
|
||||
"version": "1.0",
|
||||
"image": {
|
||||
"name": "/home/asonix/Pictures/shenzi/1242635_1372997258512_full.webp",
|
||||
"baseName": "1242635_1372997258512_full.webp",
|
||||
"permissions": 644,
|
||||
"format": "WEBP",
|
||||
"formatDescription": "WebP Image Format",
|
||||
"mimeType": "image/webp",
|
||||
"class": "DirectClass",
|
||||
"geometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"units": "Undefined",
|
||||
"type": "Bilevel",
|
||||
"baseType": "Undefined",
|
||||
"endianness": "Undefined",
|
||||
"colorspace": "sRGB",
|
||||
"depth": 1,
|
||||
"baseDepth": 8,
|
||||
"channelDepth": {
|
||||
"red": 8,
|
||||
"green": 8,
|
||||
"blue": 1
|
||||
},
|
||||
"pixels": 6220800,
|
||||
"imageStatistics": {
|
||||
"Overall": {
|
||||
"min": 0,
|
||||
"max": 244,
|
||||
"mean": 99.8391,
|
||||
"median": 121.333,
|
||||
"standardDeviation": 43.645,
|
||||
"kurtosis": -0.145553,
|
||||
"skewness": 0.984726,
|
||||
"entropy": 0.701104
|
||||
}
|
||||
},
|
||||
"channelStatistics": {
|
||||
"red": {
|
||||
"min": 34,
|
||||
"max": 244,
|
||||
"mean": 166.595,
|
||||
"median": 196,
|
||||
"standardDeviation": 70.8386,
|
||||
"kurtosis": -1.65286,
|
||||
"skewness": -0.357383,
|
||||
"entropy": 0.725609
|
||||
},
|
||||
"green": {
|
||||
"min": 0,
|
||||
"max": 106,
|
||||
"mean": 70.0406,
|
||||
"median": 88,
|
||||
"standardDeviation": 30.5371,
|
||||
"kurtosis": -1.49345,
|
||||
"skewness": -0.455794,
|
||||
"entropy": 0.704115
|
||||
},
|
||||
"blue": {
|
||||
"min": 0,
|
||||
"max": 100,
|
||||
"mean": 62.8818,
|
||||
"median": 80,
|
||||
"standardDeviation": 29.5594,
|
||||
"kurtosis": -1.51232,
|
||||
"skewness": -0.389386,
|
||||
"entropy": 0.673587
|
||||
}
|
||||
},
|
||||
"renderingIntent": "Perceptual",
|
||||
"gamma": 0.454545,
|
||||
"chromaticity": {
|
||||
"redPrimary": {
|
||||
"x": 0.64,
|
||||
"y": 0.33
|
||||
},
|
||||
"greenPrimary": {
|
||||
"x": 0.3,
|
||||
"y": 0.6
|
||||
},
|
||||
"bluePrimary": {
|
||||
"x": 0.15,
|
||||
"y": 0.06
|
||||
},
|
||||
"whitePrimary": {
|
||||
"x": 0.3127,
|
||||
"y": 0.329
|
||||
}
|
||||
},
|
||||
"matteColor": "#BDBDBDBDBDBD",
|
||||
"backgroundColor": "#FFFFFFFFFFFF",
|
||||
"borderColor": "#DFDFDFDFDFDF",
|
||||
"transparentColor": "#000000000000",
|
||||
"interlace": "None",
|
||||
"intensity": "Undefined",
|
||||
"compose": "Over",
|
||||
"pageGeometry": {
|
||||
"width": 1920,
|
||||
"height": 1080,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"dispose": "Undefined",
|
||||
"iterations": 0,
|
||||
"compression": "Undefined",
|
||||
"orientation": "Undefined",
|
||||
"properties": {
|
||||
"signature": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
|
||||
},
|
||||
"tainted": false,
|
||||
"filesize": "51106B",
|
||||
"numberPixels": "2.0736M",
|
||||
"pixelsPerSecond": "23.1706MB",
|
||||
"userTime": "0.080u",
|
||||
"elapsedTime": "0:01.089",
|
||||
"version": "ImageMagick 7.1.1-11 Q16-HDRI x86_64 f04a7eb33:20230528 https://imagemagick.org"
|
||||
}
|
||||
}]
|
93
src/magick/tests.rs
Normal file
93
src/magick/tests.rs
Normal file
|
@ -0,0 +1,93 @@
|
|||
use super::{Details, DetailsOutput};
|
||||
|
||||
fn details_tests() -> [(&'static str, Details); 8] {
|
||||
[
|
||||
(
|
||||
"avif",
|
||||
Details {
|
||||
mime_type: super::image_avif(),
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
frames: None,
|
||||
},
|
||||
),
|
||||
(
|
||||
"gif",
|
||||
Details {
|
||||
mime_type: mime::IMAGE_GIF,
|
||||
width: 414,
|
||||
height: 261,
|
||||
frames: Some(17),
|
||||
},
|
||||
),
|
||||
(
|
||||
"jpeg",
|
||||
Details {
|
||||
mime_type: mime::IMAGE_JPEG,
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
frames: None,
|
||||
},
|
||||
),
|
||||
(
|
||||
"jxl",
|
||||
Details {
|
||||
mime_type: super::image_jxl(),
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
frames: None,
|
||||
},
|
||||
),
|
||||
(
|
||||
"mp4",
|
||||
Details {
|
||||
mime_type: super::video_mp4(),
|
||||
width: 414,
|
||||
height: 261,
|
||||
frames: Some(17),
|
||||
},
|
||||
),
|
||||
(
|
||||
"png",
|
||||
Details {
|
||||
mime_type: mime::IMAGE_PNG,
|
||||
width: 497,
|
||||
height: 694,
|
||||
frames: None,
|
||||
},
|
||||
),
|
||||
(
|
||||
"webm",
|
||||
Details {
|
||||
mime_type: super::video_webm(),
|
||||
width: 112,
|
||||
height: 112,
|
||||
frames: Some(27),
|
||||
},
|
||||
),
|
||||
(
|
||||
"webp",
|
||||
Details {
|
||||
mime_type: super::image_webp(),
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
frames: None,
|
||||
},
|
||||
),
|
||||
]
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_details() {
|
||||
for (case, expected) in details_tests() {
|
||||
let string =
|
||||
std::fs::read_to_string(format!("./src/magick/magick_7_1_1_{case}_details.json"))
|
||||
.expect("Read file");
|
||||
|
||||
let json: Vec<DetailsOutput> = serde_json::from_str(&string).expect("Valid json");
|
||||
|
||||
let output = super::parse_details(json).expect("Parsed details");
|
||||
|
||||
assert_eq!(output, expected);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue