Embedding
Embed provenance metadata into JPEG images using the JUMBF box structure.
How embedding works
The embedding process takes a JPEG image and a JSON metadata object, wraps the metadata in JUMBF box structures (a ContentBox inside a SuperBox), and injects the resulting APP11 marker segments into the JPEG file at the correct position.
Existing JPEG Trust metadata is automatically stripped before embedding new metadata, so re-embedding is safe.
Workflow
Embedding workflow
Input image + metadata/profile
↓
embed_image()
↓
embed_metadata()
↓
Build ContentBox from JSON
↓
Construct JUMBF SuperBox
↓
Strip existing APP11 segments
↓
Inject APP11 markers into JPEG
↓
Output: embedded JPEG
Python API
High-level: file paths
from jpegtrust import embed_image # From a metadata JSON file embed_image("photo.jpg", "metadata.json", "signed.jpg") # With IPTC digital source type (auto-injected into assertions) embed_image("photo.jpg", "metadata.json", "signed.jpg", digital_source_type="trainedAlgorithmicMedia") # From a dict metadata = { "@context": ["https://jpeg.org/jpegtrust/"], "declaration": { "claim": {"alg": "sha256"}, "assertions": {...} } } embed_image("photo.jpg", metadata, "signed.jpg")
Low-level: bytes
from jpegtrust import embed_metadata with open("photo.jpg", "rb") as f: image_bytes = f.read() metadata = {"@context": ["https://jpeg.org/jpegtrust/"], ...} result_bytes = embed_metadata(image_bytes, metadata) # Or write directly to a file embed_metadata(image_bytes, metadata, output_path="signed.jpg")
CLI
# Basic embed jpegtrust embed photo.jpg metadata.json -o signed.jpg # With IPTC digital source type jpegtrust embed photo.jpg metadata.json -o signed.jpg --digital-source-type trainedAlgorithmicMedia # Default output: photo_embedded.jpg jpegtrust embed photo.jpg metadata.json # Batch embed all JPEGs in a directory jpegtrust batch embed ./photos metadata.json -o ./signed # List all valid digital source types jpegtrust profile list-source-types
Example metadata JSON
This is the structure of a JPEG Trust indicator that can be embedded into an image:
{
"@context": ["https://jpeg.org/jpegtrust/"],
"declaration": {
"claim": {
"alg": "sha256",
"claim_generator_info": [{"name": "Camera App"}],
"signature_status": "claimSignature.validated",
"content_status": "assertion.dataHash.match"
},
"assertions": {
"c2pa.actions": {
"actions": [{
"action": "c2pa.created",
"when": "2025-01-15T09:00:00Z",
"digitalSourceType": "http://cv.iptc.org/newscodes/digitalsourcetype/digitalCapture"
}]
}
}
},
"manifests": [{
"claim": {...},
"assertions": {
"cawg.metadata": {
"@context": {"exif": "http://ns.adobe.com/exif/1.0/", "dc": "http://purl.org/dc/elements/1.1/"},
"exif:GPSLatitude": "39,55.08N",
"dc:creator": ["Photographer Name"]
}
}
}]
}Key functions
Function Description
embed_image(image, metadata, output, digital_source_type=None) High-level: file path in, file path out. Optional IPTC digital source type.
embed_metadata(image_bytes, metadata_dict, digital_source_type=None) Low-level: bytes in, bytes out. Optional IPTC digital source type.
batch_embed(input_dir, metadata, output_dir) Embed into all images in a directory