Working With Assets

Many of the functions in the v5 interface to libc2pa accept and return Asset objects. Assets abstract the source of the data being passed into the library. This is an improvement over the v4 interface, which had different versions of every function, depending on what type of input data was being passed in or returned.

Types of Assets

These Asset objects represent the data in an asset and take the following forms:

  • Buffer - Buffer assets contain either a reference to a std::vector<unsigned char> or an actual std::vector<unsigned char>, depending on how the Asset was created.
  • Stream - Stream assets contain a reference to a std::istream or std::iostream.
  • File - File assets contain the path to a file on disk.

Read-Only vs Read/Write

File and stream assets can be either read-only or read/write. Assets that are created as read-only can not be passed in to library functions that accept a read/write asset. However, read/write assets may be passed in to functions that accept read-only assets.

When a file or stream asset is passed in to a function or object that will modify the content of that asset, that modification will always be made to the original asset (in-place) and any returned asset will reference the exact same file or stream as the input asset.

Buffer assets are always read/write in that they can be passed in to functions that require a read/write asset. But they differ from file and stream assets in that the original buffer data is never modified. Instead, modifications are made to a copy of the input buffer. Any returned buffer asset will reference that modified copy of the buffer, not the original buffer.

Creating Assets

Assets are created with the C2PAFactory object. They are passed around as std::shared_ptr<> smart pointers.

#include "C2PA/C2PAFactory.hpp"

// Create a read/write asset from a file
auto jpeg_file_asset = c2pa::C2PAFactory::new_file_asset("image.jpg");

// Create a read-only asset from a file
auto jpeg_ro_file_asset = c2pa::C2PAFactory::new_read_only_file_asset("image2.jpg");

// Create a read/write stream asset
std::fstream rw_jpeg_file("image3.jpg",
  std::ios::binary | std::ios::in | std::ios::out);
auto jpeg_stream_asset = c2pa::C2PAFactory::new_stream_asset(rw_jpeg_file);

// Create a read-only stream asset
std::ifstream ro_jpeg_file("image4.jpg", std::ios::binary);
auto jpeg_ro_stream_asset =
  c2pa::C2PAFactory::new_read_only_stream_asset(ro_jpeg_file);

// Create a buffer asset referencing a vector on the stack
common::byte_buf_t stack_jpeg_buffer = read_file("image5.jpg");
auto jpeg_ref_buffer_asset =
  c2pa::C2PAFactory::new_ref_buffer_asset(stack_jpeg_buffer);

// Create a buffer asset containing a moved vector
common::byte_buf_t jpeg_buffer_to_move = read_file("image6.jpg");
auto jpeg_buffer_asset =
  c2pa::C2PAFactory::new_move_buffer_asset(std::move(jpeg_buffer_to_move));

// Create a buffer asset containing a copy of a vector
common::byte_buf_t jpeg_buffer_to_copy = read_file("image7.jpg");
auto jpeg_buffer_copy_asset =
  c2pa::C2PAFactory::new_copy_buffer_asset(jpeg_buffer_to_copy);

new_file_asset()

Creates a read/write file-type Asset object from the provided file path.

  • std::string asset_path - A path to a file on disk containing media data.

new_read_only_file_asset()

Creates a read-only file-type Asset object from the provided file path.

  • std::string asset_path - A path to a file on disk containing media data.

new_stream_asset()

Creates a read/write stream-type Asset object from the provided stream.

  • std::iostream& stream - A reference to an I/O stream containing media data.

new_read_only_stream_asset()

Creates a read-only stream-type Asset object from the provided stream.

  • std::istream& stream - A reference to an input stream containing media data.

new_ref_buffer_asset()

Creates an Asset object that contains a reference to a std::vector<unsigned char>. The referenced vector object must not be deleted before libc2pa is done working with it. Only use this if you are comfortable with managing C++ object lifetimes and you want to avoid the overhead of copying data.

  • const std::vector<unsigned char>& buffer - A data buffer containing media data.

new_move_buffer_asset()

Creates an Asset object that contains the passed in std::vector<unsigned char>. The provided vector object will be invalid in its original context after calling this function. Only use this if you are comfortable with C++ move semantics and you want to avoid the overhead of copying data.

  • const std::vector<unsigned char>&& buffer - A data buffer containing media data.

new_copy_buffer_asset()

Creates an Asset object that contains a copy of the passed in std::vector<unsigned char>. The provided vector object will be copied into the Asset, and so the caller may delete the original vector at any time after calling this function. This is the easiest of the buffer-type functions to work with, but it does incur the cost of making a copy of the vector.

  • const std::vector<unsigned char>& buffer - A data buffer containing media data.

Retrieving Data From Assets

You need to know what type of Asset you have in order to retrieve data from it. For many operations, this should be well known. For example, when signing a media file, if the media was passed to the ClaimGenerator as a file-type asset, then the value returned from the sign_media() function will also be a file-type asset.

get_type()

All Asset objects support the get_type() method, for cases where the type of the asset isn't already known. It returns a common::AssetDataType enumeration with one of the following values:

  • common::AssetDataType::Buffer
  • common::AssetDataType::ReadOnlyStream
  • common::AssetDataType::ReadWriteStream
  • common::AssetDataType::ReadOnlyFile
  • common::AssetDataType::ReadWriteFile
auto asset = c2pa::C2PAFactory::new_copy_buffer_asset(jpeg_buffer);
// Returns `common::AssetDataType::Buffer`
auto asset_type = asset->get_type();

as<type>()

Attempts to cast the Asset to the specified type. If the cast fails, then it will throw an exception.

  • common::AssetDataType type - The type to try to cast to.
c2pa::AssetPtr asset = c2pa::C2PAFactory::new_copy_buffer_asset(jpeg_buffer);
// Will fail
auto file_asset = asset->as<common::AssetDataType::ReadOnlyFile>();
// Will succeed
auto buffer_asset = asset->as<common::AssetDataType::Buffer>();

get_data()

Retrieves the data buffer from a buffer-type Asset object. You must cast the Asset first to be able to call this method. It returns a reference (not a copy) to the vector contained (or referenced) in the Asset.

auto output_asset = cg->sign_media(signature);
common::byte_buf_t& output_data = output_asset
	->as<common::AssetDataType::Buffer>()
  ->get_data();

get_stream()

Retrieves a reference to the stream (either std::istream or std::iostream) referred to in a stream-type Asset object. You must cast the Asset first to be able to call this method.

auto output_asset = cg->sign_media(signature);
std::istream& ro_stream = output_asset
	->as<common::AssetDataType::ReadOnlyStream>()
  ->get_stream();
std::iostream& rw_stream = output_asset
  ->as<common::AssetDataType::ReadWriteStream>()
  ->get_stream();

get_path()

Retrieves a std::string representing a path to the disk file referenced by the Asset object. You must cast the Asset first to be able to call this method.

auto output_asset = cg->sign_media(signature);
auto file_path = output_asset
	->as<common::AssetDataType::ReadOnlyFile>()
  ->get_path();