diff --git a/sdk/src/assertions/labels.rs b/sdk/src/assertions/labels.rs index 182a2e3da..438f0b16e 100644 --- a/sdk/src/assertions/labels.rs +++ b/sdk/src/assertions/labels.rs @@ -89,6 +89,16 @@ pub const PNG_CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim.png"; /// See . pub const PNG_INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient.png"; +/// Label prefix for a SVG claim thumbnail assertion. +/// +/// See . +pub const SVG_CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim.svg"; + +/// Label prefix for a SVG ingredient thumbnail assertion. +/// +/// See . +pub const SVG_INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient.svg"; + /// Label prefix for an actions assertion. /// /// See . @@ -199,6 +209,7 @@ pub fn add_thumbnail_format(label: &str, format: &str) -> String { match format { "image/jpeg" | "jpeg" | "jpg" => format!("{label}.jpeg"), "image/png" | "png" => format!("{label}.png"), + "image/svg+xml" | "svg" => format!("{label}.svg"), _ => { let p: Vec<&str> = format.split('/').collect(); if p.len() == 2 && p[0] == "image" { diff --git a/sdk/src/ingredient.rs b/sdk/src/ingredient.rs index f6dea3291..ca482ddf0 100644 --- a/sdk/src/ingredient.rs +++ b/sdk/src/ingredient.rs @@ -25,8 +25,6 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -#[cfg(feature = "file_io")] -use crate::utils::mime::extension_to_mime; #[cfg(doc)] use crate::Manifest; use crate::{ @@ -42,7 +40,7 @@ use crate::{ }, resource_store::{skip_serializing_resources, ResourceRef, ResourceStore}, store::Store, - utils::xmp_inmemory_utils::XmpInfo, + utils::{mime::extension_to_mime, xmp_inmemory_utils::XmpInfo}, validation_results::ValidationResults, validation_status::{self, ValidationStatus}, }; @@ -618,8 +616,8 @@ impl Ingredient { let format = hashed_uri .url() .rsplit_once('.') - .map(|(_, ext)| format!("image/{}", ext)) - .unwrap_or_else(|| "image/jpeg".to_string()); // default to jpeg?? + .and_then(|(_, ext)| extension_to_mime(ext)) + .unwrap_or("image/jpeg"); // default to jpeg?? let mut thumb = crate::resource_store::ResourceRef::new(format, &uri); // keep track of the alg and hash for reuse thumb.alg = hashed_uri.alg(); @@ -706,11 +704,10 @@ impl Ingredient { } fn thumbnail_from_assertion(assertion: &Assertion) -> (String, Vec) { + let thumbnail_format = + extension_to_mime(get_thumbnail_image_type(&assertion.label_root()).as_str()); ( - format!( - "image/{}", - get_thumbnail_image_type(&assertion.label_root()) - ), + thumbnail_format.unwrap_or("image/none").to_string(), assertion.data().to_vec(), ) } @@ -1715,7 +1712,7 @@ mod tests_file_io { use wasm_bindgen_test::*; use super::*; - use crate::utils::test::fixture_path; + use crate::{assertion::AssertionData, utils::test::fixture_path}; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi")))] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); @@ -2023,4 +2020,19 @@ mod tests_file_io { //let mut _data_ref = ResourceRef::new("image/jpg", "foo"); //data_ref.data_types = vec!["c2pa.types.dataset.pytorch".to_string()]; } + + #[test] + fn test_thumbnail_from_assertion_for_svg() { + let assertion = Assertion::new( + "c2pa.thumbnail.ingredient.svg", + None, + AssertionData::Binary(include_bytes!("../tests/fixtures/sample1.svg").to_vec()), + ); + let (format, image) = Ingredient::thumbnail_from_assertion(&assertion); + assert_eq!(format, "image/svg+xml"); + assert_eq!( + image, + include_bytes!("../tests/fixtures/sample1.svg").to_vec() + ); + } }