[Astro] #123 GDAL Converter — gdal3.js WASM によるブラウザ完結型 GISデータ変換・可視化ツール

[Astro] #123 GDAL Converter — gdal3.js WASM によるブラウザ完結型 GISデータ変換・可視化ツール

概要

GDAL(Geospatial Data Abstraction Library)のWASMビルド「gdal3.js」を使い、GeoTIFF・Shapefile・GeoJSON・KML・GeoPackage等のGISデータをブラウザ内で変換・可視化するツールを構築した。

サーバーへのファイルアップロードは一切不要で、すべてブラウザ内で完結する。QGISやデスクトップGISツールをインストールせずに、フォーマット変換・座標系変換・データプレビューが可能。

スクリーンショット

GDAL Converter — ベクタデータ表示 GDAL Converter — ラスタデータ表示 GDAL Converter

動画 (GIF)

GDAL Converter — ベクタデータ表示 GDAL Converter — ベクタデータ表示 GDAL Converter — ベクタデータ表示

サンプルデータ

今回の実装内容

機能・モジュール概要
gdal3.js統合GDAL C/C++ライブラリのWASMビルドをブラウザに組み込み(128ラスタ+53ベクタドライバ)
ベクタ変換ogr2ogrでGeoJSON/Shapefile/KML/GML/GeoPackage/FlatGeobuf/CSV/DXF/XLSX間の相互変換
ラスタ変換gdal_translateでGeoTIFF/PNG/JPEG/WebP/Cloud Optimized GeoTIFF間の変換
CRS再投影gdalwarpによる座標系変換(WGS84/Web Mercator/UTM/JGD2011等)
ベクタプレビューogr2ogrでGeoJSON変換 → MapLibre GL JSでダークマップ上にオーバーレイ表示
ラスタプレビューgdal_translateでPNG変換 → Canvas描画
メタデータ表示フォーマット・CRS・範囲・フィーチャ数・レイヤー数・ピクセルサイズ・バンド数
マルチレイヤー対応GeoPackage等のマルチレイヤーファイルで最大フィーチャ数レイヤーを自動選択
Shapefile対応.shp+.dbf+.shxの複数ファイル一括ドロップ、.prjなしでも動作
変換ログGDAL処理の各ステップ・経過時間をログパネルにリアルタイム表示

背景

GIS(Geographic Information System)データのフォーマットは用途・組織・時代によって乱立している。ベクタデータだけでもShapefile(ESRI、1990年代〜)、GeoJSON(WebGIS標準)、KML(Google Earth)、GeoPackage(OGC後継標準)、GML(XML系)と多数あり、ラスタデータはGeoTIFF(衛星画像・DEM)が主流だが派生形式も多い。

これらの変換にはGDALが事実上の標準ライブラリとして使われているが、通常はQGISやコマンドラインでの利用が前提。gdal3.jsはGDALをEmscriptenでWASMビルドしたもので、128のラスタドライバと53のベクタドライバをブラウザ内で利用可能にする。

技術実装の詳細

1. アーキテクチャ

[ ブラウザ ]
│  ファイルドロップ(Shapefile複数ファイル対応)
│  → File[] をGdal.open()に渡す

[ gdal3.js WASM ]
│  Gdal.open(files) → dataset
│  Gdal.getInfo(dataset) → メタデータ(CRS/Extent/レイヤー/バンド)
│  Gdal.ogr2ogr(dataset, options) → ベクタ変換
│  Gdal.gdal_translate(dataset, options) → ラスタ変換
│  Gdal.gdalwarp(dataset, options) → CRS再投影

[ プレビュー ]
├─ ベクタ → GeoJSON → MapLibre GL JS(Polygon/Line/Point自動判定)
└─ ラスタ → PNG → Canvas描画

[ エクスポート ]
   Gdal.getFileBytes(output) → Blob → ダウンロード

2. gdal3.jsの組み込み

gdal3.jsはCDN(jsDelivr)から読み込み。WASMモジュール(.wasm)とデータファイル(.data、座標系定義等)の2ファイルをpathオプションで指定。

const script = document.createElement('script');
script.src = 'https://cdn.jsdelivr.net/npm/[email protected]/dist/package/gdal3.js';
script.onload = () => {
  initGdalJs({
    path: 'https://cdn.jsdelivr.net/npm/[email protected]/dist/package',
    useWorker: false
  }).then(resolve);
};

useWorker: falseでメインスレッド実行。Web Worker使用時はCDNのCORS制約でロードが不安定なため、メインスレッド+UIブロック対策(setTimeout 50ms)で対応。

3. ベクタ変換パイプライン

ogr2ogrのオプションをそのまま配列で渡す設計。GDALのコマンドラインと同じ感覚で使える。

// Shapefile → GeoJSON + CRS変換
const options = ['-f', 'GeoJSON', '-t_srs', 'EPSG:4326'];
const output = await Gdal.ogr2ogr(dataset, options);
const bytes = await Gdal.getFileBytes(output);

CRSが未定義のデータ(.prjなしのShapefile等)では-t_srsを省略し、座標値をそのまま出力する安全設計。

4. マルチレイヤー対応

GeoPackageやKMLは複数レイヤーを含むことがある。GeoJSON(単一レイヤー形式)へのプレビュー変換時は、featureCount最大のレイヤーを自動選択し、-skipfailuresで非ジオメトリレイヤー(スタイル定義等)のエラーをスキップ。

if (info.layers.length > 1) {
  let bestLayer = null, maxFeatures = 0;
  for (const layer of info.layers) {
    if ((layer.featureCount || 0) > maxFeatures) {
      maxFeatures = layer.featureCount;
      bestLayer = layer.name;
    }
  }
  options.push(bestLayer);
}

5. ラスタプレビュー

GeoTIFF等のラスタデータはgdal_translateでPNGに変換し、Canvas要素に描画。大きなラスタは-outsize 2048 0でリサイズしてプレビュー。

const options = ['-of', 'PNG', '-outsize', '2048', '0'];
const output = await Gdal.gdal_translate(dataset, options);
const bytes = await Gdal.getFileBytes(output);
// → Blob → Image → Canvas描画

6. MapLibreによるベクタ可視化

MapLibre GL JSをダーク背景スタイルで初期化し、GeoJSONオーバーレイを表示。ジオメトリタイプ(Polygon/LineString/Point)を自動判定し、fill/line/circleレイヤーを適切に追加。

// Polygon → fill + outline
map.addLayer({ type: 'fill', paint: { 'fill-color': '#00ff88', 'fill-opacity': 0.15 } });
// LineString → line
map.addLayer({ type: 'line', paint: { 'line-color': '#00ccff', 'line-width': 2 } });
// Point → circle
map.addLayer({ type: 'circle', paint: { 'circle-color': '#ffcc00', 'circle-radius': 4 } });

bounding boxを算出してmap.fitBoundsで自動ズーム。

対応フォーマット

ベクタ(入力・出力)

入力: GeoJSON, Shapefile (.shp+.dbf+.shx), KML, GML, GeoPackage (.gpkg), FlatGeobuf (.fgb), DXF, CSV, XLSX, PMTiles 等

出力: GeoJSON, Shapefile, KML, GML, GeoPackage, FlatGeobuf, CSV, DXF, XLSX

ラスタ(入力・出力)

入力: GeoTIFF, PNG, JPEG, WebP, MBTiles 等

出力: GeoTIFF, PNG, JPEG, WebP, GeoPackage, Cloud Optimized GeoTIFF (COG)

座標系(CRS)

EPSG:4326 (WGS84), EPSG:3857 (Web Mercator), EPSG:32654 (UTM 54N), EPSG:6668 (JGD2011), EPSG:6677 (JGD2011 / Japan Zone 9)

技術スタック

  • Astro — ページ構築
  • gdal3.js v2.8.1 — GDAL C/C++ライブラリのEmscripten WASMビルド(128ラスタ+53ベクタドライバ)
  • MapLibre GL JS v4.7.1 — ベクタデータの地図表示
  • vanilla JavaScript — DOM操作、ドラッグ&ドロップ、ファイル処理

更新履歴

  • [v1.0]:
    • gdal3.js統合
    • ベクタ/ラスタ読み込み・変換・プレビュー
    • CRS変換
    • マルチレイヤー対応
    • Shapefile複数ファイル対応