専門的な話から趣味の話まで、
様々なテーマでお届け

S2ファクトリーが日々のウェブサイトや
アプリの制作を通じて、
役に立ちそうな技術情報や趣味の話まで
幅広いテーマで発信しています。

2023/01/11

IIIF概説

IIIF概説アイキャッチ
今回は弊社の栗山が「IIIF」について話しました。 (ブログとしての公開時期が遅れてしまいましたが、実際に調べていたのは2021年秋あたりなのでその時点での情報です)

IIIF(トリプル・アイ・エフ)とは、International Image Interoperability Framework の略。
解説を直訳すると、高品質な属性付きのデジタルオブジェクトをスケーラブルに配布するためのオープンフレームワーク。というものらしいですが、昨今では図書館や美術館のデジタルアーカイブで、IIIF に対応した画像ビューアを使えるようにする仕組みなどに使われています。

下に挙げた 6 つの API が定義されており、これらをまとめて IIIF というフレームワークになります。

  • Image API
  • Presentation API
  • Authentication API
  • Content Search API
  • Change Discovery API
  • Content State API (draft)

JSON-LD

IIIF では JSON-LD に準拠した構造のレスポンスが返ってきます。
JSON-LD とは JSON for Linking Data の略で、情報同士を結合させて表現するための構造化データそのシンタックスの一種です。そのようなシンタックスには他に

  • Microformats
  • RDFa

といったものがあります。

JSON-LD は RDFa や Microformats と違い、記載する場所に制限がないのが特徴で、
Google によって現在使用が推奨されています。

やろうとしていることは RDFa や Microformats と同じで、例えば
{
  "@context": "http://schema.org/",
  "@type": "Product",
  ...
}
というデータ構造は、 http://schema.org で定義されている Product という型のものを表現しますが、後続する属性はその型定義によって変わります。
{
  "@context": "https://json-ld.org/contexts/person.jsonld",
  "@id": "http://dbpedia.org/resource/John_Lennon",
  "name": "John Lennon",
  "born": "1940-10-09",
  "spouse": "http://dbpedia.org/resource/Cynthia_Lennon"
}
だと @context に @type 相当の情報まで含まれているので @type は省略し、それ以外の属性はその @context で定義されている、という形式になります。

Content State API

後で説明する Presentation API のリソース、もしくはリソースの一部を、コンパクトな表現で参照するための規格です。
{
  "@context": "http://iiif.io/api/presentation/3/context.json",
  "id": "https://example.org/Annotation-server/bookmarks/b1",
  "type": "Annotation",
  "motivation": ["contentState"],
  "target": {
     "id": "https://example.org/iiif/item1/manifest",
     "type": "Manifest"
  }
}
これは完全に書き下す形の表現方法です。それ以外にも、URI を記述するだけ、上記target部分だけ、などの表現方法があります。

State は、REST(Representational State Transfer)でいうところの Resource State にあたります。

Change Discovery API

名前の通り、変更された記述を見つけるための API です。
どれぐらい詳しい情報を返すかによりレベルが変わります。

レベル 0
{
  "type": "Update",
  "object": {
    "id": "https://example.org/iiif/1/manifest",
    "type": "Manifest"
  }
}
何らかの変更があったことだけを伝えます。
あるオブジェクトが削除された場合には、一覧を見て判断する必要があります。


レベル 1
{
  "type": "Update",
  "object": {
    "id": "https://example.org/iiif/1/manifest",
    "type": "Manifest"
  },
  "endTime": "2017-09-20T00:00:00Z"
}
endTime という属性が増えていますが、ここには最終更新日、もしくは新規作成日が入ります。ここまではリソースの存在を別の手段で知っていて、その変更点を知る、というだけの情報です。


レベル 2
{
  "type": "Create",
  "object": {
    "id": "https://example.org/iiif/1/manifest",
    "type": "Manifest"
  },
  "endTime": "2017-09-20T00:00:00Z"
}
レベル 2 になると type のところに CreateDeleteMove といった状態が見られるようになります。レベルが上がるほど、参照する側としては便利になりますが、サーバー側の実装としては手間がかかりそうな感じです。

Content Search API

検索内容にコンテンツについた注釈からリストを取得する API です。
検索エンジンの URL は service という LD を使って定義し、そのリソースによって検索されるコンテンツの範囲を決めます。

こちらは service 記述の例になりますが、
{
  // ... the resource that the search service is associated with ...
  "service": {
    "@context": "http://iiif.io/api/search/1/context.json",
    "@id": "http://example.org/services/identifier/search",
    "profile": "http://iiif.io/api/search/1/search"
  }
}
検索 API は @contentprofile を上記で固定し、 @id が実際の検索 API URL を指しています。

Request の送り方は、 q= がクエリ文字列、さらに date=user= のようなリクエストも可能です。いずれも空白区切りにしなければなりません。検索できるパラメータについてはこちらをご覧ください。

また、AutoComplete 用の補助 API も定義されており、先ほどのコードを下のように拡張できます。
{
  // Resource that the services are associated with ...
  "service": {
    "@context": "http://iiif.io/api/search/1/context.json",
    "@id": "http://example.org/services/identifier/search",
    "profile": "http://iiif.io/api/search/1/search",
    "service": {
      "@id": "http://example.org/services/identifier/autocomplete",
      "profile": "http://iiif.io/api/search/1/autocomplete"
    }
  }
}
これは q= に「bir」という文字列を入れてリクエストを送った場合ですが、search:TermList というレスポンスで、それぞれ「bir」を含む検索結果が返ってきています。
{
  "@context": "http://iiif.io/api/search/1/context.json",
  "@id": "http://example.org/service/identifier/autocomplete?q=bir&motivation=painting",
  "@type": "search:TermList",
  "ignored": ["user"],
  "terms": [
    {
      "match": "bird",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=bird",
      "count": 15
    },
    {
      "match": "biro",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=biro",
      "count": 3
    },
    {
      "match": "birth",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=birth",
      "count": 9
    },
    {
      "match": "birthday",
      "url": "http://example.org/service/identifier/search?motivation=painting&q=birthday",
      "count": 21
    }
  ]
}

Authentication API

リソースへのアクセスに対して、認証が必要な形を提供するための規格です。
ただ、認証の具体的な仕組み自体は定義せず「どういうタイプの認証が必要で、どこをたどればいいか」を記述します。

例えば下記のコードでは、 @id でログイン用の URL が示され、 profile で対話ログインを示しています。
{
  // ...
  "service" : {
    "@context": "http://iiif.io/api/auth/1/context.json",
    "@id": "https://authentication.example.org/login",
    "profile": "http://iiif.io/api/auth/1/login",
    "label": "Login to Example Institution",
    "header": "Please Log In",
    "description": "Example Institution requires that you log in with your example account to view this content.",
    "confirmLabel": "Login",
    "failureHeader": "Authentication Failed",
    "failureDescription": "<a href=\"http://example.org/policy\">Access Policy</a>",
    "service": [
      // Access token and Logout services ...
    ]
  }
}
その他にもログインではなく、利用規約などを踏ませるパターンだと profile に http://iiif.io/api/auth/1/clickthrough を記述することで、対話なしの踏み台を作成することが可能です。

ここまでで説明した API はどちらかと言えばフレームワークとしての屋台骨であり、一度実装してしまえばそれほど使用頻度の高くないものです。画像を表示したりという用途では、これから説明する残りの二つが主に使用することになります。

Image API

画像と、それに付随するメタ情報をリクエストするための API です。
クエリパラメータではなくパスセグメントを使って情報を伝えます。というのも画像なので、キャッシュされやすいことを意識してそのようになっています。

ある画像を任意のサイズや回転などで取りたい時に、このようなルールでパスを作成すれば取得できると決められるのがこの API の肝です。


画像自体は、
{scheme}://{server}{/prefix}/{identifier}/{region}/{size}/{rotation}/{quality}.{format}
メタ情報は、
{scheme}://{server}{/prefix}/{identifier}/info.json
という構文でリクエストします。
これは画像処理の適用順序に合わせた順番になっています。

Request
{region}full・・・画像全体。
square・・・元画像の短辺合わせの矩形画像を返します。長辺位置はサーバー側が自由に決めるが、一般的には中央がデフォルト。
x,y,w,h・・・具体的な位置指定が可能。画像左上を 0,0とし、w,h で幅と高さを指定して画像を切り抜ける。単位はpx。
 pct:x,y,w,h・・・パーセントによる指定。例えば x に 50 を指定すると元画像の大きさから 50% な位置を指定という意味。
{size}max・・・別情報の maxWidthmaxHeigtmaxArea で示される最大サイズに。
w,  ,h ・・・幅が指定値になるよう、縦横比を維持して拡縮。
pct:n・・・n パーセントにスケーリングされる。100を超えてはいけない。
{rotation}n ・・・ 0 から 360 までの時計回りの回転角度。 
!n ・・・回転が適用される前に垂直軸に基づいて反転される。
{quality}color・・・フルカラー。
gray・・・グレースケール。
bitonal・・・二値画像。白か黒。 
default・・・サーバー任せ。
{format}拡張子。
 jpgtifpnggifjp2pdfwebp などが指定できる。
サポートされていないフォーマットがリクエストされた場合は 400 を返す。
これらのパラメータを構文の中に含めて任意の画像をリクエストすることができます。


※ここで紹介したパラメータはごく一部です。全てをご覧になりたい方はこちらのドキュメントをご覧ください。


画像のメタ情報は、applicaton/ld+json で JSON-LD 形式で返ってきます(サーバーがサポートしてなければ application/json でもOK)。
{
  "@context": "http://iiif.io/api/image/3/context.json",
  "id": "https://example.org/image-service/abcd1234/1E34750D-38DB-4825-A38A-B60A345E591C",
  "type": "ImageService3",
  "protocol": "http://iiif.io/api/image",
  "profile": "level2",
  "width": 6000,
  "height": 4000,
  "maxHeight": 2000,
  "maxWidth": 3000,
  "maxArea": 4000000
}
ずらっと画像情報が並んでいますが、@contexttypeprotocol は固定。 id には {identifier} までを含めた URI が入ります(末尾 / 無し)。

widthheight がオリジナルの画像サイズ(px)で、maxWidth , maxHeightそれ以上のサイズではリクエストできないということを表しています。

タイル化された情報も記述できます:
{
  "@context": "http://iiif.io/api/image/3/context.json",
  "id": "https://example.org/image-service/abcd1234/1E34750D-38DB-4825-A38A-B60A345E591C",
  "type": "ImageService3",
  "protocol": "http://iiif.io/api/image",
  "profile": "level2",
  "width": 6000,
  "height": 4000,
  "tiles": [
    { "width": 512, "scaleFactors": [ 1, 2, 4, 8, 16 ] }
  ]
}
というのも、例えばオリジナルの画像サイズが大きいため、サーバー側で分割した状態で保管されており、分割リクエストした上で、クライアント側で画像を繋げて一枚の画像として閲覧できるようにする、や、ズームインターフェイスを使って一部だけを拡大表示する仕組みなどが想定されているからです。
"scaleFactors": [ 1, 2, 4, 8, 16 ] 
と記述されているのは、サーバー側で幅高さが 1/1, 1/2, 1/4, 1/8, 1/16 の形でそれぞれ分割されたものが用意されているということを示しています。
ユーザーはこの情報を見て、どのように画像を見せるかを考えてリクエストを選択することができます。

Presentation API

仕様書には digitized physical objects とありましたが、つまりモノのコレクションの構造、レイアウト、表現方法などを JSON で記述するための規格です。 デジタイズしたものだけでなく、元々デジタルで作られたもの(bornd-digital object)も対象にしている様子。

この規格は、

  • ユーザーに画像、ビデオ、音声その他のモノを表示する。
  • ユーザーが複数のビュー、時間軸で(直線的、階層的に)遷移することを可能にする
  • モノ、ビュー、ナビゲーション構造についての情報をユーザーに提供する
  • モノの発行人とユーザーが追加情報を注釈して共有することを可能にする

これらを目的としており、図のような階層が組み合わさった JSON で表現されます。

Collection
ManifestCollection の順序付き集合。

Manifest
title などの属性で compound object の特徴を示すもの。

Canvas
object の一つの見え方を定義するもの。

Range
Canvas が複数ある時の順序付き集合。

Annotation Page
Annotation の順序付き集合。

Annotation
Canvas と Content をつなげて、かつメタ情報を記述するもの。

Content
実際の画像、音声、ビデオ、テキストなど。


駆け足になりましたが、以上が「IIIF」の概要です。

これを使うことで、汎用的なビューアーを作成することができます。
以下は実際に IIIF に基づいて実装されたものです。良かったら参考に見てみてください。

S2ファクトリー株式会社

様々な分野のスペシャリストが集まり、Webサイトやスマートフォンアプリの企画・設計から制作、システム開発、インフラ構築・運用などの業務を行っているウェブ制作会社です。

実績

案件のご依頼、ご相談、その他ご質問はこちらからお問い合わせください。

案件のご依頼、ご相談、
その他ご質問は
こちらから
お問い合わせください。

様々な分野のスペシャリストがお客様と
ともに「できそう」を導き出します。

S2ファクトリー株式会社

様々な分野のスペシャリストが集まり、Webサイトやスマートフォンアプリの企画・設計から制作、システム開発、インフラ構築・運用などの業務を行っているウェブ制作会社です。

実績

案件のご依頼、ご相談、その他ご質問はこちらからお問い合わせください。