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