Presentation APIの役割と概要
IIIF Image APIが「画像そのものの配信」を担うのに対し、IIIF Presentation APIは「画像をどのように提示するか」を記述するためのAPIです。書籍であれば、どのページがどの順番で並ぶのか、各ページにどのようなメタデータが紐づくのか、目次構造はどうなっているのか、といった「構造的な情報」をJSON-LD形式で表現します。
Presentation APIが提供する情報は、ビューア(MiradorやUniversal Viewerなど)が画像を正しく表示するために不可欠です。例えば、巻物のように右から左へ読む資料であればviewingDirectionをright-to-leftに設定し、複数ページからなる書籍であれば各ページをCanvas(キャンバス)として定義します。このように、Presentation APIは画像の「見せ方」を機関やプロジェクトを超えて標準化する役割を持っています。
Presentation APIの仕様はJSON-LDで記述されるため、Linked Dataとしての特性も備えています。各リソースにはURIが割り当てられ、他の機関が公開するリソースとも相互参照が可能です。
Manifestの構造
Presentation APIの中心となるリソースがManifest(マニフェスト)です。マニフェストは1つのデジタルオブジェクト(書籍1冊、絵巻1巻など)を記述するJSON-LDファイルであり、以下のような階層構造を持ちます。
Manifest > Canvas > Annotation
- Manifest: デジタルオブジェクト全体を表すトップレベルのリソース。ラベル、メタデータ、権利情報、表示方向などを含む
- Canvas: 個々のページや画面に相当する仮想的な空間。幅と高さを持ち、ここに画像やテキストなどのコンテンツが配置される
- Annotation: Canvas上に配置されるコンテンツ。画像の場合は
motivationがpaintingのAnnotationとして記述される
v3における基本的なManifestの構造は以下のようになります。
{
"@context": "http://iiif.io/api/presentation/3/context.json",
"id": "https://example.org/iiif/manifest.json",
"type": "Manifest",
"label": { "ja": ["資料タイトル"] },
"items": [
{
"id": "https://example.org/iiif/canvas/p1",
"type": "Canvas",
"width": 6642,
"height": 4990,
"items": [
{
"id": "https://example.org/iiif/canvas/p1/page",
"type": "AnnotationPage",
"items": [
{
"id": "https://example.org/iiif/canvas/p1/page/imageanno",
"type": "Annotation",
"motivation": "painting",
"body": {
"id": "https://example.org/iiif/image/full/max/0/default.jpg",
"type": "Image",
"format": "image/jpeg",
"service": [
{
"id": "https://example.org/iiif/image",
"type": "ImageService2",
"profile": "level2"
}
],
"width": 6642,
"height": 4990
},
"target": "https://example.org/iiif/canvas/p1"
}
]
}
]
}
]
}
注目すべき点として、Canvas自体は「仮想的な空間」であり、画像はpaintingモチベーションのAnnotationとしてCanvas上に配置されます。この設計により、1つのCanvas上に複数の画像を重ねたり、テキストや音声などのメディアを組み合わせたりすることが可能になっています。
また、v3ではAnnotation以外にもannotationsプロパティを通じて、コメントなどの注釈を付与できます。SVGセレクタを使った自由形状のアノテーション記述も可能で、SvgSelectorのvalueにSVGパスを指定することで、矩形以外の任意の形状で領域を指定できます。
v2とv3の違いと移行のポイント
Presentation APIにはv2(2.1.1)とv3(3.0)の2つのメジャーバージョンが広く使われています。v3はW3C Web Annotation Data Modelとの整合性を高めるために大幅に設計が見直されました。移行にあたって把握しておくべき主な変更点は以下の通りです。
プロパティ名の変更
| v2 | v3 |
|---|---|
@id | id |
@type | type |
sc:Manifest | Manifest |
sc:Canvas | Canvas |
sc:Range | Range |
sequences | items |
ラベル・メタデータの多言語対応
v2ではlabelは単純な文字列でしたが、v3では言語マップ形式に変更されました。
// v2
{ "label": "資料タイトル" }
// v3
{ "label": { "ja": ["資料タイトル"] } }
metadataについても同様に、labelとvalueの両方が言語マップ形式で記述される必要があります。
// v3のmetadata
{
"metadata": [
{
"label": { "none": ["Persistent ID"] },
"value": { "none": ["info:ndljp/pid/3437686"] }
}
]
}
serviceの記述
v3ではserviceプロパティは配列として記述し、@idはidに変更されます。また、typeプロパティが必須になりました。
// v3のservice
{
"service": [
{
"@context": "http://iiif.io/api/search/1/context.json",
"id": "https://example.org/search/12345",
"profile": "http://iiif.io/api/search/1/search",
"type": "SearchService1"
}
]
}
rightsプロパティの制限
v3ではrightsに指定できるURLは、Creative Commons(https://creativecommons.org/...)またはRightsStatements.org(https://rightsstatements.org/...)のURLのみに制限されています。独自のライセンスページURLを設定したい場合は、metadata内に記述する必要があります。
structuresの変更
目次構造を定義するstructures内のRangeについても、@idをidに、@typeをtypeに変更し、値からsc:プレフィクスを除く必要があります。
Collectionの構造とページネーション
Collectionは複数のManifestやサブCollectionをまとめるリソースです。図書館の蔵書目録のように、多数の資料を階層的に整理して提示するために使用します。
v2のCollectionの基本構造は以下の通りです。
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@id": "http://example.org/iiif/collection/top",
"@type": "sc:Collection",
"label": "コレクション名",
"manifests": [
{
"@id": "http://example.org/iiif/book1/manifest",
"@type": "sc:Manifest",
"label": "Book 1"
}
]
}
対象とするManifestが数千件、数万件に及ぶ場合、1つのCollectionファイルにすべてを含めると配信が困難になります。v2ではページネーション機能が仕様として定義されており、totalでコレクション全体の件数を示し、firstで最初のページへのリンクを提示します。各ページはnextで次のページを参照します。
// トップレベル
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@id": "http://example.org/iiif/collection/top",
"@type": "sc:Collection",
"label": "大規模コレクション",
"total": 9316290,
"first": "http://example.org/iiif/collection/c1"
}
// 各ページ
{
"@context": "http://iiif.io/api/presentation/2/context.json",
"@id": "http://example.org/iiif/collection/c1",
"@type": "sc:Collection",
"within": "http://example.org/iiif/collection/top",
"startIndex": 0,
"next": "http://example.org/iiif/collection/c2",
"manifests": [ ... ]
}
なお、ページネーション関連のプロパティ(total、first、next、startIndex)はPresentation API Validatorで警告が出る場合があり、一部のビューアでは正しく認識されないこともあります。大規模コレクションを扱う際は、ビューア側の対応状況も確認しておくとよいでしょう。
Content State APIの概要
IIIF Content State APIは、IIIFリソースの特定の表示状態を共有するためのAPIです。「この資料のこのページのこの領域を、この角度で表示している」という状態をURLとして表現できます。
具体的には、以下の手順でContent State URLを生成します。
- 対象とするCanvasのURIと表示領域(xywh座標)を特定する
- Manifestの情報と合わせてJSON形式で記述する
- そのJSONをBase64エンコードする
- エンコード結果をURLパラメータとして付与する
{
"id": "https://example.org/canvas/2#xywh=2148,813,312,304",
"type": "Canvas",
"partOf": [{
"id": "https://example.org/manifest.json",
"type": "Manifest"
}]
}
このJSONをBase64エンコードした文字列を?target=パラメータなどに付与することで、特定のページの特定の領域にフォーカスしたリンクを生成できます。研究者間で画像上の注目箇所を正確に共有したい場合や、検索結果から特定箇所へのディープリンクを提供したい場合に有用です。
バリデーション方法
マニフェストファイルがPresentation APIの仕様に準拠しているかを検証するには、IIIF Presentation Validatorを使用します。
オンラインバリデータ
IIIF公式のオンラインバリデータ(https://presentation-validator.iiif.io/)にアクセスし、マニフェストURLを入力してバージョンを選択すれば、即座に検証結果が得られます。エラーがあればその内容と該当箇所が表示され、問題がなければ「Validated successfully」と表示されます。
バリデータが検出する典型的なエラーには以下のようなものがあります。
idが配列になっている(文字列であるべき)labelやvalueが言語マップ形式になっていない(v3の場合)rightsに許可されていないURLが指定されているserviceが配列ではなくオブジェクトとして記述されている- v2の記法(
@id、@type)がv3のマニフェスト内に残っている
ローカル環境でのバリデーション
開発中のマニフェストファイルを検証したい場合、ローカル環境でバリデータを起動することもできます。
git clone https://github.com/IIIF/presentation-validator.git
cd presentation-validator
pip install -r requirements.txt
python iiif-presentation-validator.py
これでlocalhost:8080にバリデータが起動します。別ターミナルでマニフェストファイルのあるディレクトリに移動し、python -m http.serverでローカルサーバを起動すれば、http://localhost:8000/manifest.jsonのようなURLで検証対象にアクセスできます。
また、REST APIとしてhttp://localhost:8080/validate?version=3.0&url=http://localhost:8000/manifest.jsonにアクセスすることで、検証結果をJSON形式で取得することも可能です。CI/CDパイプラインに組み込む際に便利です。
@iiif/parserの活用
@iiif/parserはIIIF-Commonsが提供するnpmモジュールで、IIIF関連のデータ解析・変換を行うためのライブラリです。特に有用な機能として、Presentation API v2のマニフェストをv3形式に変換するconvertPresentation2関数があります。
import { convertPresentation2 } from "@iiif/parser/presentation-2";
const response = await fetch(manifestUrl);
const manifestJson = await response.json();
const convertedManifest = convertPresentation2(manifestJson);
このライブラリを活用することで、v2形式で公開されている既存のマニフェストをv3に変換した上で処理できます。例えば、マニフェストから画像URLの一覧を抽出するツールを開発する際、入力がv2であってもv3であっても統一的に処理できるようになります。
v2のマニフェストを提供している機関はまだ多く存在するため、v2とv3の両方を扱う必要がある場面では、このライブラリが大いに役立ちます。
実践的なJSON-LDの読み方
Presentation APIのマニフェストを読み解く際のポイントをまとめます。
@contextを確認する: まず@context(v2)または"@context": "http://iiif.io/api/presentation/3/context.json"(v3)を見て、バージョンを確認します。v2とv3ではプロパティの命名規則が異なるため、バージョンの把握が最初のステップです。
Manifest > items(またはsequences > canvases)を辿る: v3ではManifestのitemsがCanvasの配列、各CanvasのitemsがAnnotationPageの配列となっています。v2ではManifestのsequences[0].canvasesがCanvasの配列です。
serviceプロパティに注目する: Image APIのエンドポイントは、Canvas内のAnnotation bodyのserviceプロパティに記述されています。ここから画像配信サーバのベースURLを読み取ることで、任意のサイズや領域の画像URLを組み立てることができます。
structuresで目次構造を確認する: structuresプロパティにRange(範囲)として目次構造が定義されている場合があります。各Rangeにはlabel(章名や巻名)と、その範囲に含まれるCanvasへの参照が含まれます。
annotationsとitemsの違いを理解する: v3ではCanvasのitemsに含まれるのが画像などの本体コンテンツ(paintingモチベーション)であり、annotationsに含まれるのが注釈やコメント(commentingモチベーション)です。この区別を理解しておくと、マニフェストの構造が明確になります。
まとめ
Presentation APIはIIIFの核となるAPIの1つであり、デジタルオブジェクトの構造と提示方法を記述する重要な役割を担っています。v2からv3への移行が進む中で、言語マップ形式への変更やWeb Annotation Data Modelとの統合など、仕様はより厳密かつ表現力豊かになっています。バリデータや@iiif/parserといったツールを活用しながら、仕様に準拠したマニフェストを作成・管理していくことが、IIIFエコシステムへの円滑な参加につながります。