Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: SVG thumbnails with a fix to the ingredient thumbnail format detection #722

Open
wants to merge 14 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions sdk/src/assertions/labels.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,16 @@ pub const PNG_CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim.png";
/// See <https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_thumbnail>.
pub const PNG_INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient.png";

/// Label prefix for a SVG claim thumbnail assertion.
///
/// See <https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_thumbnail>.
pub const SVG_CLAIM_THUMBNAIL: &str = "c2pa.thumbnail.claim.svg";

/// Label prefix for a SVG ingredient thumbnail assertion.
///
/// See <https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_thumbnail>.
pub const SVG_INGREDIENT_THUMBNAIL: &str = "c2pa.thumbnail.ingredient.svg";

/// Label prefix for an actions assertion.
///
/// See <https://c2pa.org/specifications/specifications/1.0/specs/C2PA_Specification.html#_actions>.
Expand Down Expand Up @@ -194,6 +204,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" {
Expand Down
29 changes: 19 additions & 10 deletions sdk/src/ingredient.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand All @@ -43,7 +41,7 @@ use crate::{
jumbf_io::load_jumbf_from_stream,
resource_store::{skip_serializing_resources, ResourceRef, ResourceStore},
store::Store,
utils::xmp_inmemory_utils::XmpInfo,
utils::{mime::extension_to_mime, xmp_inmemory_utils::XmpInfo},
validation_status::{self, status_for_store, ValidationStatus},
};

Expand Down Expand Up @@ -600,8 +598,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();
Expand Down Expand Up @@ -691,11 +689,10 @@ impl Ingredient {
}

fn thumbnail_from_assertion(assertion: &Assertion) -> (String, Vec<u8>) {
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(),
)
}
Expand Down Expand Up @@ -1662,7 +1659,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(target_arch = "wasm32")]
wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser);

Expand Down Expand Up @@ -1959,4 +1956,16 @@ 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.len(), 22501);
}
}
Loading