c2pa-test-image-service is a Node.js service (built using Express, c2pa-node and the awesome sharp image-processing library) intended to provide on-the-fly generation of C2PA-enabled images for testing purposes.
- Node.js (v18 or later)
- Rust (optional if pre-built binaries don't exist for c2pa-node on your system)
Before installation, ensure that you are in an active node project with a package.json
file. If you are not, run npm init
to create one. Then, install the package:
npm install c2pa-test-image-service
To start the server, run:
npx c2pa-test-image-service
If all is successful, you should be greeted with:
Listening on port 1337
Navigating to http://localhost:1337 should display a single image - a red square. Check it out on Verify to inspect the C2PA data embedded within.
This is a great start, but the power of this service is in its ability to provide custom C2PA images. To do so, a configuration file must be provided. Read on...
To get started, create a configuration file in your project directory. This file should export a single default object.
// c2pa-test-image-service.config.js
export default {
port: 8080,
fixtures: {
default: {
image: { r: 0, g: 0, b: 255, width: 100, height: 100 },
manifest: {
title: "test-image.jpg",
claim_generator: "test-image-service",
format: "image/jpeg",
},
},
},
};
TypeScript is strongly recommended, as it will provide type-checking and auto-completion for your configuration file. You can add TypeScript to your project with:
npm install typescript
// c2pa-test-image-service.config.ts
import { C2paTestImageServiceConfig } from "c2pa-test-image-service";
export default {
port: 8080,
fixtures: {
default: {
image: { r: 0, g: 0, b: 255, width: 100, height: 100 },
manifest: {
title: "test-image.jpg",
claim_generator: "test-image-service",
format: "image/jpeg",
},
},
},
} satisfies C2paTestImageServiceConfig;
Specify this configuration file when starting the server by using the --config
flag and a path to the file:
npx c2pa-test-image-service --config c2pa-test-image-service.config.js
This bare-bones configuration file specifies a port for the service to listen on and a single basic fixture. In general, the "fixtures" property is an object with keys corresponding to fixture names and values representing the details of the asset to generate and sign. The default
fixture is special, and will be used if no fixture name is provided in the request URL. To add another fixture, simply add another key-value pair to the fixtures
object:
export default {
port: 8080,
fixtures: {
default: {
/* ... */
},
"another-fixture": {
image: { r: 255, g: 0, b: 255 },
manifest: {
title: "yet-another-fixture.jpg",
claim_generator: "test-image-service",
format: "image/jpeg",
},
ingredients: [
{
title: "ingredient.jpg",
image: { r: 255, g: 0, b: 255 },
manifest: {
title: "ingredient-asset.jpg",
claim_generator: "test-image-service",
format: "image/jpeg",
assertions: [
{
label: "stds.schema-org.CreativeWork",
data: {
author: [
{
"@type": "Person",
name: "Jane Smith",
},
],
},
},
],
},
},
],
},
},
};
This asset is available at http://localhost:8080/another-fixture – note the fixture name in the URL.
Additionally, this fixture configuration demonstrates two important features of the service: the ability to specify multiple ingredients, and the ability to specify custom assertions. Assertions can be provided to any manifest
, not just within ingredients. More information on ingredients and assertions can be found in the C2PA specification.
While specifying fixture configuration as a raw javascript object works, it is easy to see how such a configuration could quickly become unwieldy. To help with this, c2pa-test-image-service provides a fixture builder utility.
Here is the above configuration re-written using the fixture builder:
const defaultFixtureData = createAsset({
title: "test-image.jpg",
image: { r: 0, g: 0, b: 255, width: 100, height: 100 },
}).toJpeg();
const ingredientData = createAsset({
title: "ingredient-asset.jpg",
image: { r: 255, g: 0, b: 255 },
})
.addAssertion("stds.schema-org.CreativeWork", {
author: [
{
"@type": "Person",
name: "Jane Smith",
},
],
})
.toJpeg();
const complexFixtureData = createAsset({
title: "yet-another-fixture.jpg",
image: { r: 0, g: 255, b: 255 },
})
.addIngredient("ingredient.jpg", ingredientData)
.toJpeg();
const fixtureStore = createFixtureStore()
.addDefaultFixure(defaultFixtureData)
.addFixture("another-fixture", complexFixtureData)
.toFixtureData();
export default {
port: 1337,
fixtures: fixtureStore,
};
Creates the top-level fixture store to be provided in the configuration object.
Returns
Returns an object with the following methods:
addDefaultFixture(signedAssetDescriptor)
- Adds a default fixture to the store.
signedAssetDescriptor
should be an asset, as returned by thecreateAsset()
method.
- Adds a default fixture to the store.
addFixture(name, signedAssetDescriptor)
- Adds a fixture to the store with a given
name
.signedAssetDescriptor
should be an asset, as returned by thecreateAsset()
method.
- Adds a fixture to the store with a given
toFixtureData()
- Exports the fixture store as a fixture data object in the format expected by the configuration file. Call this method when you are done adding fixtures to the store.
Utility for creating signedAssetDescriptor
objects.
Parameters
assetData
is an object with the following properties:
title
(required)- The title of the asset.
image
(optional)- An object describing the image to be generated. If not provided, the asset will be a 100x100 white square. If provided, it should be an object with the following properties:
r
(required)- The red component of the image's color.
g
(required)- The green component of the image's color.
b
(required)- The blue component of the image's color.
width
(optional)- The width of the image. Defaults to 100.
height
(optional)- The height of the image. Defaults to 100.
- An object describing the image to be generated. If not provided, the asset will be a 100x100 white square. If provided, it should be an object with the following properties:
Returns
Returns an object with the following methods:
addAssertion(label, data)
- Adds an assertion to the asset.
label
should be a string representing the assertion's label, anddata
should be an object representing the assertion's data.
- Adds an assertion to the asset.
addAssertions(assertions)
- Accepts an array of assertions as objects with
label
anddata
properties and adds them to the asset.
- Accepts an array of assertions as objects with
addIngredient(title, signedAssetDescriptor)
- Adds an ingredient to the asset.
title
should be a string representing the ingredient's title, andsignedAssetDescriptor
should be an asset, as returned by thecreateAsset()
method.
- Adds an ingredient to the asset.
toJpeg()
- Exports the asset as a signed asset descriptor for a JPEG image. Call this method when you are done adding assertions and ingredients to the asset.