IIIF画像同士を重ねてみるViewerを作りました:その1・機能の紹介

先週、数人の知り合いの人文系開発者の方々と、一緒に集中的に開発やデータ作成をしようということで、南房総の方で合宿をしてきました。年甲斐もなく、自分も開発に集中してしまったのですが、どうしてもよくわからなかった事柄の理解を中心に、かなり集中することができまして、ようやく、IIIFの画像同士をWebブラウザ上で重ねるという、これまで目指していたものの一つができました。

とにかく、見ているIIIF画像をピックアップしてためておいて、重ねたい対象に重ねて位置合わせをする、というだけのものです。が、言うは易し。誰かがこういうものを作ってくれるだろうなと ずっと待っていたのですが、なかなか出てこないので、結局自分で作ってみることにしたのがこちらです。

youtu.be

同じIIIFコンテンツ内でも、複数のIIIFコンテンツ同士でも、重ねて位置合わせをしたり透過度を調整したりすることができます。重ねた画像に関しては、まとめてJSONデータとして 出力するようになっていますので、これをテキストエディタに保存しておけば、同じビューを再現して、さらにそこから重なりや透過をいじることができます。

youtu.be

実際のサイトは以下のURLなのですが、これは全部Javascriptで書いてますので、サーバ上でなくてもパソコン上でも動作します。

http://candra.dhii.jp/nagasaki/iiifoverlay/viewer.html

たとえば、このサイトで、「Open JSON Window」ボタンをクリックしてウインドウを開いて、以下のJSONデータをコピペして「Load JSON」ボタン⇒「Set Positions」ボタン クリックしていくと、上記の曼荼羅+大日如来2つの透過重ねが再現できて、自分でも色々いじることができます。

{
    "@context": "http://iiif.io/api/presentation/2/context.json",
    "@type": "sc:Manifest",
    "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/12b02/manifest.json",
    "label": "大正新脩大藏經図像部第12b02巻",
    "metadata": [
        {
            "label": "Author",
            "value": "高楠順次郎"
        },
        {
            "label": "published",
            "value": [
                {
                    "@value": "大蔵出版",
                    "@language": "ja"
                }
            ]
        },
        {
            "label": "Source",
            "value": "大正新脩大藏經 図像部"
        },
        {
            "label": "manifest URI",
            "value": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/12b02/manifest.json"
        }
    ],
    "description": "大正新脩大藏經図像部",
    "viewingDirection": "right-to-left",
    "viewingHint": "paged",
    "license": "http://creativecommons.org/licenses/by-sa/4.0/",
    "attribution": "大蔵出版(Daizo shuppan) and SAT大蔵経テキストデータベース研究会(SAT Daizōkyō Text Database Committee) ",
    "logo": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/satlogo80.png",
    "sequences": [
        {
            "@id": "https://dzkimgs.l.u-tokyo.ac.jp/zuzoubu/12b02/sequence.json",
            "@type": "sc:Sequence",
            "label": "Current Page Order",
            "canvases": [
                {
                    "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/03/p0024",
                    "@type": "sc:Canvas",
                    "label": "p.24:図像抄",
                    "width": 6732,
                    "height": 8984,
                    "images": [
                        {
                            "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/03/ano0024",
                            "@type": "oa:Annotation",
                            "motivation": "sc:painting",
                            "resource": {
                                "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiifimgs/zuzoubu/03/0024.tif/full/full/0/default.jpg",
                                "@type": "dctypes:Image",
                                "format": "image/jpeg",
                                "width": 6732,
                                "height": 8984,
                                "service": {
                                    "@context": "http://iiif.io/api/image/2/context.json",
                                    "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiifimgs/zuzoubu/03/0024.tif",
                                    "profile": "http://iiif.io/api/image/2/level1.json"
                                }
                            },
                            "on": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/03/p0024"
                        },
                        {
                            "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/01/ano1000",
                            "@type": "oa:Annotation",
                            "motivation": "sc:painting",
                            "resource": {
                                "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiifimgs/zuzoubu/01/1000.tif/full/full/0/default.jpg",
                                "@type": "dctypes:Image",
                                "format": "image/jpeg",
                                "width": 6732,
                                "height": 8984,
                                "service": {
                                    "@context": "http://iiif.io/api/image/2/context.json",
                                    "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiifimgs/zuzoubu/01/1000.tif",
                                    "profile": "http://iiif.io/api/image/2/level1.json"
                                }
                            },
                            "on": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/03/p0024#xywh=2818,3699,985,1314",
                            "license": "undefined",
                            "attribution": "undefined"
                        },
                        {
                            "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/03/ano0024",
                            "@type": "oa:Annotation",
                            "motivation": "sc:painting",
                            "resource": {
                                "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiifimgs/zuzoubu/03/0024.tif/full/full/0/default.jpg",
                                "@type": "dctypes:Image",
                                "format": "image/jpeg",
                                "width": 6732,
                                "height": 8984,
                                "service": {
                                    "@context": "http://iiif.io/api/image/2/context.json",
                                    "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiifimgs/zuzoubu/03/0024.tif",
                                    "profile": "http://iiif.io/api/image/2/level1.json"
                                }
                            },
                            "on": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/03/p0024#xywh=2814,3708,1023,1366",
                            "license": "undefined",
                            "attribution": "undefined"
                        }
                    ],
                    "otherContent": [
                        {
                            "@id": "https://dzkimgs.l.u-tokyo.ac.jp/iiif/zuzoubu/03/list/p0024.json",
                            "@type": "sc:AnnotationList"
                        }
                    ]
                }
            ]
        }
    ]
}

まだまだ色んな機能を追加できる可能性がありますので、どなたか頑張ってくださったらありがたいとも思っております。

頑張ってくださるどなたかのために(企業の方でもぜひ挑戦・採用などしていただけるとありがたく思います)、今回苦労した部分を少しご紹介しておきたいと思います。

基本的に、苦労したことの大半は、IIIFのタイル画像表示をしてくれるOpenSeadragonのAPIの仕様を理解すること だったので、少しずつご紹介してみたいと思います。

まず、複数のIIIFタイル画像を一つのビューワで表示する関数なのですが、透過度0.7で左上位置をそろえて 表示させる場合、以下のようにしてできるようです。imgUriは、何か適当に info.jsonのURLを入れればOKです。

viewer.addTiledImage({
          tileSource: imgUri,
          opacity: 0.7,
          index:10,
          x:0,
          y:0
        });

重ねた画像の位置を変える際には

viewer.world.getItemAt(n).setPosition({x:0,y:0.5});

という感じにするのですが、タイル画像を重ねていくと、最初のタイル画像がn=0で、 それに一つ重ねるとn=1、二つ重ねるとn=2、という風に増えていきます。 同様に、nの値をあわせることで、透過度や画像のサイズも変えられます。ただし、縦横比を変えるのは ちょっと無理っぽい感じでした。

viewer.world.getItemAt(n).setOpacity(0.8);
viewer.world.getItemAt(n).setWidth(1.5);

OpenSeadragonのハマりやすいポイントの一つは、画像の横幅に対する相対値として縦横幅高さ(x,y,w,h)の値が表現されるという点です。 ですので、とにかく画像の横幅のサイズを取得する必要があります。これは以下のように getContentSize().x で取得できます。

viewer.world.getItemAt(n).getContentSize().x; 

なお、「重ねた画像の位置を動かす」際に、元の画像を動かさずに重ねた画像の位置だけをドラッグで動かす方法については 色々試したのですが、結局のところ、「重ねた画像を動かす際には viewer.setMouseNavEnabled(false); で 元画像や他の重ねた画像の動きを全部止めて重ねた画像の位置だけをjQueryで動かす」という風にしました。

とりあえず、今夜はこんなところにしておきます。