Add support for SVG files to get_image_metadata (Fixes #769) (#1063)

* Add support for SVG files to `get_image_metadata`

* Add support for SVG files to `get_image_metadata`

* Update documentation after adding SVG support
This commit is contained in:
Matthias 2020-06-18 11:36:11 +02:00 committed by GitHub
parent 752716f292
commit 5e31a32166
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 60 additions and 5 deletions

View file

@ -4,6 +4,7 @@
- Add 2 syntax highlighting themes: `green` and `railsbase16-green-screen-dark` - Add 2 syntax highlighting themes: `green` and `railsbase16-green-screen-dark`
- Enable task lists in Markdown - Enable task lists in Markdown
- Add support for SVG in `get_image_metadata`
## 0.11.0 (2020-05-25) ## 0.11.0 (2020-05-25)

34
Cargo.lock generated
View file

@ -369,6 +369,12 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "doc-comment"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
[[package]] [[package]]
name = "dtoa" name = "dtoa"
version = "0.4.5" version = "0.4.5"
@ -1756,6 +1762,15 @@ dependencies = [
"winapi 0.3.8", "winapi 0.3.8",
] ]
[[package]]
name = "roxmltree"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5001f134077069d87f77c8b9452b690df2445f7a43f1c7ca4a1af8dd505789d"
dependencies = [
"xmlparser",
]
[[package]] [[package]]
name = "rust-stemmers" name = "rust-stemmers"
version = "1.2.0" version = "1.2.0"
@ -2042,6 +2057,18 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "svg_metadata"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fe5b1fbd62339f055704951dcaf2e757c460b9f6abe17f6de0d2563da821c57"
dependencies = [
"doc-comment",
"lazy_static",
"regex",
"roxmltree",
]
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.31" version = "1.0.31"
@ -2117,6 +2144,7 @@ dependencies = [
"reqwest", "reqwest",
"serde_json", "serde_json",
"sha2", "sha2",
"svg_metadata",
"tera", "tera",
"toml", "toml",
"url", "url",
@ -2668,6 +2696,12 @@ dependencies = [
"time", "time",
] ]
[[package]]
name = "xmlparser"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ccb4240203dadf40be2de9369e5c6dec1bf427528115b030baca3334c18362d7"
[[package]] [[package]]
name = "yaml-rust" name = "yaml-rust"
version = "0.4.4" version = "0.4.4"

View file

@ -21,6 +21,7 @@ utils = { path = "../utils" }
library = { path = "../library" } library = { path = "../library" }
config = { path = "../config" } config = { path = "../config" }
imageproc = { path = "../imageproc" } imageproc = { path = "../imageproc" }
svg_metadata = "0.4.1"
[dependencies.reqwest] [dependencies.reqwest]
version = "0.10" version = "0.10"

View file

@ -2,9 +2,11 @@ use std::collections::HashMap;
use std::path::PathBuf; use std::path::PathBuf;
use std::sync::{Arc, Mutex, RwLock}; use std::sync::{Arc, Mutex, RwLock};
use std::{fs, io, result}; use std::{fs, io, result};
use std::ffi::OsStr;
use sha2::{Digest, Sha256, Sha384, Sha512}; use sha2::{Digest, Sha256, Sha384, Sha512};
use tera::{from_value, to_value, Error, Function as TeraFn, Result, Value}; use tera::{from_value, to_value, Error, Function as TeraFn, Result, Value};
use svg_metadata as svg;
use config::Config; use config::Config;
use image; use image;
@ -279,15 +281,31 @@ impl TeraFn for GetImageMeta {
if !src_path.exists() { if !src_path.exists() {
return Err(format!("`get_image_metadata`: Cannot find path: {}", path).into()); return Err(format!("`get_image_metadata`: Cannot find path: {}", path).into());
} }
let img = image::open(&src_path) let (height, width) = image_dimensions(&src_path)?;
.map_err(|e| Error::chain(format!("Failed to process image: {}", path), e))?;
let mut map = tera::Map::new(); let mut map = tera::Map::new();
map.insert(String::from("height"), Value::Number(tera::Number::from(img.height()))); map.insert(String::from("height"), Value::Number(tera::Number::from(height)));
map.insert(String::from("width"), Value::Number(tera::Number::from(img.width()))); map.insert(String::from("width"), Value::Number(tera::Number::from(width)));
Ok(Value::Object(map)) Ok(Value::Object(map))
} }
} }
// Try to read the image dimensions for a given image
fn image_dimensions(path: &PathBuf) -> Result<(u32, u32)> {
if let Some("svg") = path.extension().and_then(OsStr::to_str) {
let img = svg::Metadata::parse_file(&path)
.map_err(|e| Error::chain(format!("Failed to process SVG: {}", path.display()), e))?;
match (img.height(), img.width(), img.view_box()) {
(Some(h), Some(w), _) => Ok((h as u32, w as u32)),
(_, _, Some(view_box)) => Ok((view_box.height as u32, view_box.width as u32)),
_ => Err("Invalid dimensions: SVG width/height and viewbox not set.".into())
}
} else {
let img = image::open(&path)
.map_err(|e| Error::chain(format!("Failed to process image: {}", path.display()), e))?;
Ok((img.height(), img.width()))
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct GetTaxonomyUrl { pub struct GetTaxonomyUrl {
taxonomies: HashMap<String, HashMap<String, String>>, taxonomies: HashMap<String, HashMap<String, String>>,

View file

@ -165,7 +165,8 @@ Whenever hashing files, whether using `get_file_hash` or `get_url(..., cachebust
### `get_image_metadata` ### `get_image_metadata`
Gets metadata for an image. Currently, the only supported keys are `width` and `height`. Gets metadata for an image. This supports common formats like JPEG, PNG, as well as SVG.
Currently, the only supported keys are `width` and `height`.
```jinja2 ```jinja2
{% set meta = get_image_metadata(path="...") %} {% set meta = get_image_metadata(path="...") %}