[JS] Deep Zoom Image 規格の画像生成と表示

それは100MBくらいある巨大な画像をWebサイトで表示したいというオーダーだった。

今ならそれくらいあっても1枚で許されるか…?と思ったが、選択肢が色々増えたご時世だからこそ制限付きの4G回線しかない人もいるわけで、画像何度も見たらパケ死なんてことになったら笑えない。

そして細かいところまで見れるようにその超巨大な画像を拡大表示もしたいと言う。

そうなるともうGoogleMapのようにするしかないかなあ?と思ったがしばらくやってない芸当だったので最近どうなってるかがよくわからないのだった。
GoogleMapのAPIが出た時は無意味に地図画像を置き換えて遊んでたものじゃがのう…。

DZI画像生成

GoogleMapのようなやつ、もとい「画像をタイル分割して拡大できるようにするやつ」はマイクロソフトが開発した Deep Zoom というフォーマットである。
でかい画像を拡大率ごとに分割生成するので必要な所だけ読み込むことができる。

Deep Zoom Image でググると色々でてくるのだが、なにぶん流行が終わっているので結構死んでるやつもある。
表示先のWebサイトがGulp使ってたので、Node.jsで動かせるもので探してみた結果、Sharp に落ち着いた。

installしたらGulpタスク書きまして、

import gulp from 'gulp'
import sharp from 'sharp'

gulp.task('dzi', async () => {
  await sharp('assets/dzi/src.png')
      .jpeg()
      .tile()
      .toFile('assets/dzi/output.dz')
})

コマンド叩けば画像生成してくれる。

gulp dzi

これだけで超でかい画像からタイル生成してくれる上に処理が高速だからはちゃめちゃに楽だった。

DZI画像の表示(OpenSeadoragon)

GoogleMap APIだと左下にGoogleのロゴが表示されてしまう。
消したら怒られそうなので今回は使うのをやめた。

DZI表示ライブラリを探してみると、多くは2014〜2016年ごろで更新が止まっていて、
現状今もメンテされて生きてるのは OpenSeadoragon くらいだった。

表示されるコンテナ要素とスタイルを用意。

<div id="dzi" class="openseadragon"></div>
// SCSS
.openseadragon {
  width:100%;
  display: grid;

  &::before {
    content: "";
    display: block;
    padding-top: 56.25%;
    grid-area: 1/1;
  }

  & > .openseadragon-container {
    grid-area: 1/1;
  }
}

スマホの場合は16:9だと表示エリアが小さくなりすぎるので、画面サイズに合わせたheightにしておく方がよかった。

用意した要素に対してOpenSeadragonのinitializeをする。

OpenSeadragon({
      id:            "dzi",
      prefixUrl:     "/assets/dzi/",
      showNavigator:  true,
      tileSources:   [
        "/assets/dzi/output.dzi"
      ],
      defaultZoomLevel: 	1,
      minZoomLevel: 	1,
      visibilityRatio: 	1,
      constrainDuringPan: true
    });

オプションの指定はどういう表示をしたいかによるけれども、この設定は余白の無地背景を表示しないものである。他にもかなり細かく指定できるしプラグインも色々あるので大体の要望には答えられそうだ。

実働サイトはこちらだが、いずれ消えると思う。

おまけ:Sharpによる画像リサイズ

4000枚くらいの画像を同じサイズに変換するという依頼のため、ちょうど使ってたSharpとGulpでタスクを作った。分割せずにやったら2800枚くらいでMBPが落ちたw

https://github.com/Tenderfeel/image-resize

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください