c2pa_view

A Flutter plugin for reading and displaying C2PA (Coalition for Content Provenance and Authenticity) content credentials. It extracts embedded C2PA manifests from media files using the official c2pa-rs Rust library and renders provenance data as interactive Flutter widgets.

  • 🗃️ Read C2PA manifests from files or raw bytes.
  • 🌳 Display an interactive provenance tree with a detail panel
  • 📜 Show manifest details as a popup overlay from any button
  • 🔍 Access structured provenance data: actions, ingredients, signatures, EXIF, AI generation info, and more
  • ✅ Full validation with trust-list checking

Setup

Version compatibility note

This package intentionally pins flutter_rust_bridge to a specific tested version (2.12.0) instead of a broad range.

If you need a different FRB version, update it together with regenerated bindings and verify all target platforms before publishing.

Initialization

Before any C2PA operations, initialize the Rust library once at app startup:

import 'package:c2pa_view/c2pa_view.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await RustLib.init();
  runApp(const MyApp());
}

Loading a ManifestStore

A ManifestStore is the root object containing all C2PA manifests found in a file. Create one from any source:

// From a local file path
final store = ManifestStore.fromLocalPath('/path/to/image.jpg');

// From raw bytes and MIME type
final store = ManifestStore.fromBytes(imageBytes, 'image/jpeg');

// From a URL (async)
final store = await ManifestStore.fromUrl('https://example.com/image.jpg');

All methods return null if no C2PA manifest is found.

Usage: Full Viewer

C2paManifestViewer shows an interactive provenance tree on the left and a detail panel on the right. Clicking a tree node updates the detail panel.

import 'package:c2pa_view/c2pa_view.dart';

// 1. Load the manifest store
final store = ManifestStore.fromBytes(imageBytes, 'image/jpeg');
if (store == null) return const Text('No manifest found');

// 2. Build the provenance graph (DAG of all manifests)
final graph = ProvenanceMapper.mapToGraph(store);

// 3. Display the full viewer wrapped in a theme
C2paViewerTheme(
  data: const C2paViewerThemeData(),
  child: C2paManifestViewer(
    graph: graph,
    mimeType: 'image/jpeg',
    mediaImage: MemoryImage(imageBytes), // fallback when no embedded thumbnail
  ),
);

See testfiles_app/lib/main.dart — the ManifestViewerPage class demonstrates this pattern with network-loaded images.

Usage: Popup from an Icon Button

showManifestDetailPopup opens a positioned overlay anchored to any widget. This is useful for adding a "content credentials" button to image thumbnails.

import 'package:c2pa_view/c2pa_view.dart';

// 1. Load the manifest store
final store = ManifestStore.fromBytes(imageBytes, 'image/jpeg');
if (store == null) return;

// 2. Get the active manifest and map it to a view model
final manifest = store.manifests[store.activeManifest]!;
final viewData = ManifestViewDataMapper.map(manifest);

// 3. Use a Builder to get a BuildContext anchored to the button
Builder(
  builder: (buttonContext) {
    return IconButton(
      icon: const Icon(Icons.verified_user),
      onPressed: () {
        showManifestDetailPopup(
          buttonContext,
          data: viewData,
          mimeType: 'image/jpeg',
          mediaImage: MemoryImage(imageBytes),
        );
      },
    );
  },
);

See testfiles_app/lib/main.dart — the _PopupDemoCard class demonstrates this pattern with a thumbnail and icon button.

Theming

Wrap your widget tree with C2paViewerTheme to customize the appearance. All c2pa_view widgets read from this theme, falling back to defaults when absent.

C2paViewerTheme(
  data: const C2paViewerThemeData(
    validColor: Color(0xFF1B8D3E),
    invalidColor: Color(0xFFD93025),
    sidebarWidth: 400,
  ),
  child: C2paManifestViewer(graph: graph),
);

// Dark mode
C2paViewerTheme(
  data: C2paViewerThemeData.dark(),
  child: C2paManifestViewer(graph: graph),
);

C2paViewerThemeData controls: validation status colors, surface/border/text colors, six text style tiers, layout dimensions (sidebar width, thumbnail size, node spacing), and border radii.

Data-Only Usage

You can use the package purely for data extraction without any widgets:

final store = ManifestStore.fromLocalPath('/path/to/image.jpg');
if (store == null) return;

final manifest = store.manifests[store.activeManifest]!;

// Access structured data
print(manifest.title);
print(manifest.signatureInfo?.issuer);
print(manifest.ingredients.length);
print(manifest.actions?.map((a) => a.action));

// Or get the raw JSON string
final json = C2paBridgeService.getManifestJsonFromFile('/path/to/image.jpg');

Platforms

This is an FFI plugin with native Rust code compiled for all platforms:

Platform Status
Android Supported
iOS Supported
Linux Supported
macOS Supported
Windows Supported

Libraries

api
c2pa_view
core/bridge/c2pa_bridge_service
core/theme/c2pa_theme
domain/entities/action
domain/entities/claim_generator_info
domain/entities/creative_work
domain/entities/custom_field
domain/entities/entities
domain/entities/exif_data
domain/entities/ingredient
domain/entities/manifest
domain/entities/manifest_assertion
domain/entities/manifest_store
domain/entities/signature_info
domain/entities/thumbnail_data
domain/entities/training_mining
domain/entities/validation_status
domain/mappers/manifest_view_data_mapper
domain/mappers/provenance_mapper
domain/models/manifest_summary
domain/models/manifest_view_data
domain/models/provenance_node
domain/models/validation_result
features/custom_fields/custom_fields_table
features/manifest_detail/manifest_detail_content
features/manifest_detail/manifest_detail_panel
features/manifest_detail/manifest_detail_popup
features/manifest_detail/sections/about_section
features/manifest_detail/sections/camera_capture_section
features/manifest_detail/sections/content_summary_section
features/manifest_detail/sections/custom_fields_section
features/manifest_detail/sections/detail_header
features/manifest_detail/sections/error_banner
features/manifest_detail/sections/process_section
features/manifest_detail/sections/thumbnail_section
features/manifest_viewer/manifest_viewer
features/provenance_tree/provenance_tree_viewer
features/provenance_tree/widgets/tree_edge_painter
features/provenance_tree/widgets/tree_node_card
features/provenance_tree/widgets/zoom_controls
features/shared/widgets/c2pa_thumbnail
features/shared/widgets/collapsible_section
features/shared/widgets/credential_indicator
features/shared/widgets/ingredient_card
features/shared/widgets/manifest_summary_card
features/shared/widgets/sub_section