フリーダムの日記

GIS(地理情報システム)を中心に技術的なことを書いています。

ArcGIS で Cloud Optimized GeoTIFF (COG) を触ってみる

はじめに

私の感覚として、FOSS4G などの OSS の世界では Cloud Optimized GeoTIFF(COG)というラスター データ フォーマットの利用に関しての記事が多く、業務などでも利用されているのだろうと感じています。実際に Qiita などの技術記事のなかでも紹介している例を多く見ます。 いっぽう ArcGIS では、イメージ サービスと呼ばれるサービスが以前から対応しており、Web 配信に対応した画像サービスがあります。最近は、ArcGIS Image for ArcGIS Online と呼ばれる SaaS の画像配信サービスもあり、サービスとしては充実してそうです。
そんななか ArcGIS での Cloud Optimized GeoTIFF(COG)の対応はどうなのか、ArcGIS でも幾つか対応しているのですが、今回は ArcGIS Maps SDK for JavaScript で COG 化したラスタータイルを表示した結果を紹介したいと思います。

ArcGIS での対応状況の詳細については ArcGIS ブログでも紹介していますので、ご確認ください。

blog.esrij.com

その他、Esri community でも ArcGIS の対応状況を確認することができます。

community.esri.com

Cloud Optimized GeoTIFF (COG) とは

Cloud Optimized GeoTIFF (COG) は、クラウドに最適化された GeoTIFF で、クラウド上で効率的なワークフローを可能にする内部構造を持ち、HTTP ファイルサーバー上でホストされることを目的としています。

Cloud Optimized GeoTIFF (COG) については、すでに多くの記事で紹介されていますが、個人的には以下の記事がとても分かりやすかったです。

sorabatake.jp

COG の作成

JavaScript APIArcGIS Maps SDK for JavaScript で表示するために、まずは、COG 化する必要があります。サンプルデータとして、オルソ画像 令和4年度撮影版【北海道室蘭市】のデータを使用しました。

www.harp.lg.jp

手順としては、該当の写真地図(デジタルオルソ画像)と位置情報ファイルから GDAL を使用して GeoTIFF を作成します。GeoTIFF から COG の作成を行います。GDAL 自体のインストールは、色々なライブラリに依存するので、Docker の環境を使用しました。

Windows PowerShell を起動して、以下のコマンドを実行します。

PS C:\Work\data> docker run -v ${PWD}:/data osgeo/gdal:latest gdal_translate -of "GTiff" -a_srs EPSG:6680 /data/12QB243B.tif /data/output.tif
Input file size is 6667, 5000
0...10...20...30...40...50...60...70...80...90...100 - done.

今回は 12QB243B.tif と 12QB243B.tfw のデータを使用しました。2つのファイルを作業ディレクトリに配置します。GDLA の gdal_translate を使用して GeoTiff を作成します。ここで大事なのが、空間座標系(座標参照系)の設定で、日本測地系 2011(JGD 2011)の平面直角座標系を使用します。室蘭市は Ⅻ(12)系になるため、EPSG:6680 を指定します。

空間座標系(座標参照系)は、以下のサイトを参考にしました。 lemulus.me

実際に GeoTIFF が作成されているか、gdalinfo から地理空間情報データ形式を確認します。以下のコマンドを実行します。

PS C:\Work\data> docker run -v ${PWD}:/data osgeo/gdal:latest gdalinfo /data/output.tif
Driver: GTiff/GeoTIFF
Files: /data/output.tif
Size is 6667, 5000
Coordinate System is:
PROJCRS["JGD2011 / Japan Plane Rectangular CS XII",
    BASEGEOGCRS["JGD2011",
        DATUM["Japanese Geodetic Datum 2011",
            ELLIPSOID["GRS 1980",6378137,298.257222101,
                LENGTHUNIT["metre",1]]],
        PRIMEM["Greenwich",0,
            ANGLEUNIT["degree",0.0174532925199433]],
        ID["EPSG",6668]],
    CONVERSION["Japan Plane Rectangular CS zone XII",
        METHOD["Transverse Mercator",
            ID["EPSG",9807]],
        PARAMETER["Latitude of natural origin",44,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8801]],
        PARAMETER["Longitude of natural origin",142.25,
            ANGLEUNIT["degree",0.0174532925199433],
            ID["EPSG",8802]],
        PARAMETER["Scale factor at natural origin",0.9999,
            SCALEUNIT["unity",1],
            ID["EPSG",8805]],
        PARAMETER["False easting",0,
            LENGTHUNIT["metre",1],
            ID["EPSG",8806]],
        PARAMETER["False northing",0,
            LENGTHUNIT["metre",1],
            ID["EPSG",8807]]],
    CS[Cartesian,2],
        AXIS["northing (X)",north,
            ORDER[1],
            LENGTHUNIT["metre",1]],
        AXIS["easting (Y)",east,
            ORDER[2],
            LENGTHUNIT["metre",1]],
    USAGE[
        SCOPE["Cadastre, engineering survey, topographic mapping (large and medium scale)."],
        AREA["Japan - onshore - Hokkaido between approximately 141°E and 143°E - Sapporo city; Asahikawa city; Wakkanai city; Rumoi city; Bibai city; Yubari city; Iwamizawa city; Tomakomai city; Muroran city; Shibetsu city; Nayoro city; Ashibetsu city; Akabira city; Mikasa city; Takikawa city; Sunagawa city; Ebetsu city; Chitose city; Utashinai city; Fukagawa city; Monbetsu city; Furano city; Noboribetsu city; Eniwa city; Ishikari-shicho; Monbetsu-gun of Abashiri-shicho; Kamikawa-shicho; Soya-shicho; Hidaka-shicho; Iburi-shicho (except Usu-gun and Abuta-gun); Sorachi-shicho; Rumoi-shicho."],
        BBOX[42.15,140.89,45.54,143.61]],
    ID["EPSG",6680]]
Data axis to CRS axis mapping: 2,1
Origin = (-103200.000000000000000,-187800.000000000000000)
Pixel Size = (0.120000000000000,-0.120000000000000)
Metadata:
  AREA_OR_POINT=Area
  TIFFTAG_RESOLUTIONUNIT=1 (unitless)
  TIFFTAG_SOFTWARE=Inpho GmbH
  TIFFTAG_XRESOLUTION=1
  TIFFTAG_YRESOLUTION=1
Image Structure Metadata:
  INTERLEAVE=PIXEL
Corner Coordinates:
Upper Left  ( -103200.000, -187800.000) (140d59'53.97"E, 42d18' 9.24"N)
Lower Left  ( -103200.000, -188400.000) (140d59'54.35"E, 42d17'49.79"N)
Upper Right ( -102399.960, -187800.000) (141d 0'28.89"E, 42d18' 9.62"N)
Lower Right ( -102399.960, -188400.000) (141d 0'29.28"E, 42d17'50.17"N)
Center      ( -102799.980, -188100.000) (141d 0'11.62"E, 42d17'59.71"N)
Band 1 Block=6667x1 Type=Byte, ColorInterp=Red
Band 2 Block=6667x1 Type=Byte, ColorInterp=Green
Band 3 Block=6667x1 Type=Byte, ColorInterp=Blue

GeoTIFF としては問題はないので、いよいよ COG を作成していきます。 GDAL を使用して GeoTIFF ファイルから COG ファイルを作成していきます。以下のステップで作成してきます。

1.タイル化

PS C:\Work\data> docker run -v ${PWD}:/data osgeo/gdal:latest gdal_translate data/output.tif data/tem_output.tif -co TILED=YES
Input file size is 6667, 5000
0...10...20...30...40...50...60...70...80...90...100 - done.

2.overview を用意

PS C:\Work\data> docker run -v ${PWD}:/data osgeo/gdal:latest gdaladdo -r nearest data/tem_output.tif 2 4 8 16 32 64
0...10...20...30...40...50...60...70...80...90...100 - done.

3.COG 化

PS C:\Work\data> docker run -v ${PWD}:/data osgeo/gdal:latest gdal_translate data/tem_output.tif data/cog_output.tif -co TILED=YES -co COPY_SRC_OVERVIEWS=YES
Input file size is 6667, 5000
0...10...20...30...40...50...60...70...80...90...100 - done.

GDAL を使用した GeoTIFF ファイルから COG ファイルの作成は、以下の記事を参考にさせていただきました。 sorabatake.jp

公式の GDAL の COG についてのガイドは以下になります。

GDAL の COG についてのドキュメント gdal.org

GDAL を使用した COG 化のパフォーマンス検証 trac.osgeo.org

ArcGIS Maps SDK for JavaScript で表示

作成した COG ファイルは ArcGIS Maps SDK for JavaScript を使用してラスタータイルとして表示します。ArcGIS Maps SDK for JavaScript は Web 用のマッピングや空間解析のアプリケーションを開発するための JavaScript の ライブラリになります。

ArcGIS Maps SDK for JavaScript で COG をラスタータイルとして表示するには、ImageTileLayer クラスを使用します。

COG を表示しているサンプルもあります。 developers.arcgis.com

ImageryTileLayer クラスの パラメータの URL には COG を配信しているサービス URL を指定しますが、ローカルに置いたファイルでも直接参照して表示することができます。作成した COG ファイルの cog_output.tif を指定します。

const layer = new ImageryTileLayer({
  url: "./cog_output.tif"
});

全体のソースです。

<html>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="initial-scale=1,maximum-scale=1,user-scalable=no"
    />
    <title>ImageryTileLayer with COG | Sample | ArcGIS Maps SDK for JavaScript 4.27</title>

    <link rel="stylesheet" href="https://js.arcgis.com/4.27/esri/themes/light/main.css" />
    <script src="https://js.arcgis.com/4.27/"></script>

    <style>
      html,
      body,
      #viewDiv {
        padding: 0;
        margin: 0;
        height: 100%;
        width: 100%;
      }
    </style>

    <script>
      require([
        "esri/Map",
        "esri/views/MapView",
        "esri/layers/ImageryTileLayer",
        "esri/Graphic"
      ], (
        Map,
        MapView,
        ImageryTileLayer,
        Graphic
      ) => {
        
        // API キー
        esriConfig.apiKey = "AAPKaccc0b5f2dcf4f4e8c1adc5d2cbdd2d2gaw3u-Y5awzEH5KK04kv1dKs5tluamN6YYWGn0nKOM6Ac8NpaVBicKBvCGu9uLN1";

        const layer = new ImageryTileLayer({
          //url: "https://ss6imagery.arcgisonline.com/imagery_sample/landsat8/Bolivia_LC08_L1TP_001069_20190719_MS.tiff",
          url: "./cog_output.tif"
        });

        const map = new Map({
          basemap: "arcgis-topographic",
          layers: [layer]
        });
        const view = new MapView({
          container: "viewDiv",
          map: map
        });

        view.whenLayerView(layer).then(() => {
          // zoom to the fullExtent of the layer when layer loads
          view.goTo(layer.fullExtent);
        });

      });
    </script>
  </head>

  <body>
    <div id="viewDiv"></div>
  </body>
</html>

COG 化した GeoTIFF を ArcGIS Maps SDK for JavaScript で表示

ArcGIS Maps SDK for JavaScript


www.youtube.com

最後に

GDAL を使用することで簡単に GeoTIFF ファイルから COG ファイルを作成することができました。さらに作成した COG ファイルは ArcGIS Maps SDK for JavaScript でラスタータイルとして簡単に表示することができました。今回使用した COG 化したGeoTIFF は137 MB でしたが、快適に表示することができました。Tellus(テルース)などの衛星画像サービスでも COG を配信しているので、次回はそれらを触ってみたいと思います。