IIIFの古地図をWMTSで配信する(Allmapsを土台に、Next.jsポートフォリオに統合)

IIIFの古地図をWMTSで配信する(Allmapsを土台に、Next.jsポートフォリオに統合)

iiifwmtsallmapsnextjsgeoreferencing

台本(フルテキスト)

動画の掛け合いを書き起こしたものです。音声を再生しづらい場合はこちらをお読みください。

オープニング

  • IIIF古地図をWMTSタイルサーバとして配信
  • Allmapsを土台にNext.js + SSRで実装
つむぎ
こんにちは。今日はIIIFの古地図をWMTSで配信する仕組みを実装した記録を紹介します。
そら
IIIFとWMTSは何ですか?
つむぎ
IIIFはInternational Image Interoperability Frameworkの略で、画像配信の国際相互運用仕様です。WMTSはOGCのWeb Map Tile Service、タイル画像配信の標準仕様です。
そら
古地図をOpenStreetMapの地図と重ねて表示できるんですか?
つむぎ
そうです。Allmapsというツールで地理参照したIIIF古地図を、OpenLayersで現代地図の上に重ねて表示できます。
そら
Allmapsというのは既存のツールですか?
つむぎ
そうです。Allmapsチームが開発したツール群で、アノテーション編集、タイル配信、レンダリングまで含みます。今回はそれを土台にして薄いラッパーを実装しました。

なぜ自前実装が必要だったか

  • 一部IIIFサーバにUAフィルタがありallmaps.xyzから取得できない
  • OGC WMTS正規仕様・POI統合・ローカル開発対応が必要
そら
Allmapsがあるなら自前で実装する必要はないんじゃないですか?
つむぎ
4つの理由があります。まず一部のIIIFサーバ、たとえばCloudFront配下のCantaloupeがUser-Agentフィルタで403を返すケースです。
そら
他には何がありますか?
つむぎ
OGC WMTSの正規仕様、CapabilitiesとGetFeatureInfoをQGISのようなクライアントに対応させたいこと、POIのアノテーション統合、ローカル開発で動作させたいことです。
そら
ローカル開発で動かないと困るんですか?
つむぎ
allmaps.xyzのCloudflare WorkersからはlocalHostに到達できないため、ローカル検証では空の透明タイルが返ってきます。細かな調整ができないので自前レンダリングが必要でした。

APIの構成とエンドポイント

  • ベースパス /api/iiif-wmts/ 配下に全エンドポイント
  • ピクセル空間WMTS・地理座標WMTS・Georef・IIIF proxyの4カテゴリ
そら
どんなAPIを実装したんですか?
つむぎ
Next.jsのApp Routerで/api/iiif-wmts/配下に複数のエンドポイントを実装しました。大きく分けるとピクセル空間WMTS、地理座標WMTS、アノテーション取得、IIIFリバースプロキシです。
そら
ピクセル空間WMTSと地理座標WMTSはどう違うんですか?
つむぎ
ピクセル空間は地理参照なしでIIIF画像のピクセル座標系でタイル配信します。地理座標はジオリファレンスされた古地図をWeb MercatorのPNGタイルで配信します。
そら
Swagger UIで確認できるそうですが、どこで見られますか?
つむぎ
nakamura196-projects.vercel.app/ja/iiif-georef/docsでSwagger UIを公開しています。全エンドポイントを対話的に確認できます。

座標変換のハマりどころ

  • GcpTransformerとProjectedGcpTransformerは別物
  • transformToGeoとtransformToResourceは独立な最小二乗fit
そら
実装中に難しかった点はありましたか?
つむぎ
座標変換のずれが主な問題でした。@allmaps/transformのGcpTransformerと@allmaps/projectのProjectedGcpTransformerを混在させると4隅でずれが出ます。
そら
なぜずれが出るんですか?
つむぎ
@allmaps/renderのWarpedMapはProjectedGcpTransformerを使ってMercator空間でfitしていますが、アノテーション側でGcpTransformerのlon/lat空間fitを使っていたのが原因でした。
そら
さらにtransformToGeoとtransformToResourceも別物なんですね。
つむぎ
そうです。この2つは独立に最小二乗fittingされていて数学的逆ではありません。renderがtransformToResourceを使っているので、annotation側にはその数学的逆行列を使う必要がありました。

自前ホストの位置付けとまとめ

  • 速度はallmaps.xyzが有利、自前はデータ主権・認証・ローカル開発に強み
  • Allmapsを再実装する必要はなく、薄いラッパーを置くスタイル
そら
allmaps.xyzと自前実装、どちらを使うべきですか?
つむぎ
速度面ではallmaps.xyzが有利です。コールドスタート時でも25ミリ秒程度で返ります。自前のNode RuntimeはコールドスタートがIIIF取得込みで10秒前後かかります。
そら
自前実装の強みはどんな点ですか?
つむぎ
データ主権、認証やUAフィルタ下のIIIFへの対応、WMTS正規仕様対応、POIとアノテーション統合、ローカル開発での検証ができる点です。
そら
Allmapsを再実装するわけではないんですね。
つむぎ
そうです。Allmapsの上に薄いラッパーを置くスタイルです。@allmaps/renderや@allmaps/projectをそのまま使い、足りない機能だけを追加しています。
そら
ポートフォリオサイトと合わせて公開されているんですね。
つむぎ
はい。nakamura196-projects.vercel.appで実際に動いているデモを確認いただけます。