第10章 ラスターデータの管理、クエリ、アプリケーション

目次

10.1. ラスターのロードと生成

raster2pgsqlラスターローダを使って PostGIS ラスターを既存のラスタファイルからロードするのは、最もよく行われます。

10.1.1. raster2pgsql を使ってラスターをロードする

raster2pgsqlは、GDAL がサポートするラスター書式を PostGIS ラスタテーブルにロードするのに適切な SQL にする実行ファイルです。ラスターのオーバビューの生成だけでなく、ラスターファイルのフォルダのロードも可能です。

かなり多くの場合、(ご自分の GDAL ライブラリをコンパイルしない限り) raster2pgsqlは PostGIS の一部としてコンパイルされるので、実行ファイルがサポートするラスタータイプは GDAL の依存ライブラリでコンパイルされたものと同じになります。お手持ちのraster2pgsqlがサポートするラスタータイプの一覧は、-Gスイッチで見ることができます。

[注記]

同じアラインメントを持つラスターの集合から特定の要素のオーバビューを生成する時、オーバビューが同じアラインメントを持たないことがあります。オーバビューが同じアラインメントを持たない例についてはhttp://trac.osgeo.org/postgis/ticket/1764をご覧下さい。

10.1.1.1. 使用例

ローダを用いて入力ファイルを 100x100のタイルで生成して、データベースにアップロードする例は、次の通りです。

ローダーが SRID を 4326にし、インデックスを作成し、標準の制約を作成し、ロードされたテーブルに ANALYZE をかけ、ソースファイル名を記録して、入力ラスターを 100x100 ピクセルのタイルで保存します。

コード
raster2pgsql -s 4326 -I -C -M -F -t 100x100 *.tif public.demelevation 
> elev.sql
psql -d gisdb -f elev.sql
[注記]

対象テーブル名の一部としてスキーマを指定しない場合には、テーブルはデータベースのデフォルトスキーマ内かユーザーが接続しているスキーマ内に作られます。

変換とアップロードは UNIX のパイプを使うと一回で実行できます。

コード
raster2pgsql -s 4326 -I -C -M -F -t 100x100 \
  *.tif public.demelevation |
  psql -d gisdb

マサチューセッツ州平面のメートル単位の空中写真タイルをaerialという名前のスキーマにロードします。 元の画像と 2, 4レベルのオーバビューのテーブルとを生成します。 データ格納に COPY を使用し (データベースに仲介ファイルなくまっすぐ入ります)、-e でトランザクションを指定しないようにします (待たずにテーブルのデータを見たい場合には良いです)。ラスターを 128x128ピクセルのタイルに分解してラスター制約を適用します。INSERT モードでなく COPY モードを使用します。-F で、カラム名をタイル切り出し元ファイルのファイル名にします。

コード
raster2pgsql -I -C -e -Y -F -s 26986 -t 128x128 -l 2,4 \
  bostonaerials2008/*.jpg aerials.boston |
  psql -U postgres -d gisdb -h localhost -p 5432

このコマンドが対応するラスターフォーマットの一覧:

コード
raster2pgsql -G

-G コマンドの出力は次のようになります:

出力
Available GDAL raster formats:
  Virtual Raster
  GeoTIFF
  National Imagery Transmission Format
  Raster Product Format TOC format
  ECRG TOC format
  Erdas Imagine Images (.img)
  CEOS SAR Image
  CEOS Image
  ...
  Arc/Info Export E00 GRID
  ZMap Plus Grid
  NOAA NGS Geoid Height Grids

10.1.1.2. raster2pgsql オプション

ロングオプションは値を取り、--option=value の書き方を受け取ります。

-?, --help

ヘルプを表示します。引数を全く指定しない場合にも表示されます。

-G, --gdal-formats

サポートされているラスター書式を印字します。

(c|a|d|p) 相互に排他的なオプションです。

-c

新しいテーブルを生成し、ラスターを入れます。これがデフォルトモードです

-a

既存のテーブルにラスターを追加します。

-d

テーブルを削除し、新しいテーブルを生成し、ラスターを入れます。

-p

準備モード、テーブルを作るだけです。

--if-not-exists

テーブル生成には IF NOT EXISTS を使います。-c-p モードが該当します。-I または --create-index も指定されている時は IF NOT EXISTS を使います。-d と併用できません。追加モードは明示的にテーブルなどの生成が必要です。

ローダーの個別処理

短形式のモードは明示的な処理をまとめたプリセットです。対応するロングオプションは --drop-table--create-table--load-data--create-index--add-constraints--vacuum--analyze--no-transaction です。--if-not-exists を追加すると、有効な生成処理で IF NOT EXISTS を使います。--drop-table は選択した処理の前に DROP TABLE IF EXISTS を出力します。モード指定をしない場合には、デフォルトの生成/ロード処理を行います。

ラスター処理: ラスターカタログに適切に登録するための制約の適用

-C, --add-constraints

SRID やピクセルサイズ等のラスター制約を適用して、raster_columnsビューで適切な登録ができるようにします。

-x, --no-extent

最大範囲制約を無効にします。-C または --add-constraints が併せて指定されている場合のみ適用されます。

-r, --regular-blocking

規則的なブロック配置に対して、空間的に一意かつカバレッジタイルである制約を課します。-C または --add-constraints が併せて指定されている場合のみ適用されます。

ラスター処理: 入力ラスターデータセットの操作に使われる追加的なパラメータ

-s, --srid [<FROM_SRID>:]<SRID>

出力ラスターに指定した SRID を割り当てます。FROM_SRID も与えられた時、raster2pgsql は入力ラスターに FROM_SRID を設定して、ラスターを指定 SRID に投影変換した SQL を出力します。元の SRID が省略されるか 0に設定される場合には、適切な SRID を決定するためにラスターのメタデータを確認します。投影変換は複写モードでは使うことができません。

-b, --band BAND

ラスターから抽出するバンドのインデックス (1始まり)。1より多いバンドを抽出するには、コンマ (,) で区切ります。指定しない場合、全てのバンドが抽出されます。

-t, --tile-size TILE_SIZE

行毎に挿入するラスターを切断します。TILE_SIZEは、「幅 x 高さ」で表現しますが、"auto"を指定すると、最初のラスターを使って適切なタイルサイズが計算され、全てのラスターに適用されます。

-P, --pad

全てのタイルが同じ幅と高さを持つことを保証するために、右端、下端のタイルに詰め物を施します。

-R, --register

ファイルシステム (データベース外) ラスターとして、ラスターを登録します。

データベースには、ラスターのメタデータとラスターのファイルパスのみ格納されます (ピクセルは格納されません)。

-l, --overview-factor OVERVIEW_FACTOR

ラスターのオーバービューを生成します。縮小係数が 2個以上の場合にはコンマ (,) 区切ります。オーバービュー用のテーブルの名前は o_overview factor_table のパターンに従います。ここで overview factor にはオーバービューの縮小係数が入り、table は元となるテーブル名に置き換わります。元ラスターが既に寸法の一致するオーバービューを持っている場合には、そのオーバービューは再利用されます。生成されたオーバービューはデータベース内に格納され、-R の影響を受けません。出力される SQL ファイルには主テーブルとオーバービューテーブルの両方が入ることにご注意下さい。

-N, --nodata NODATA

NODATA 値を持たないバンドで使用する NODATA 値を設定します。

テータベースオブジェクトの操作に使われる追加的なパラメータ

-f, --raster-column COLUMN

出力先ラスターカラムの名前を指定します。デフォルトは'rast'です。

-F, --filename

ファイル名でカラムを追加します。

-n, --filename-column COLUMN

ファイル名カラムの名前を指定します。-F を暗に含みます。

-q, --quote

PostgreSQL 識別子に引用符を付けます。

-I

--create-index の別名。

--create-index

この raster2pgsql の実行が終わる時にラスターカラムの GiST インデックスを生成します。-aによる追加実行を繰り返しても、最後の実行またはロード後にインデックスを生成します。 --if-not-existsでインデックスの存在を許容します。

-M

ラスターテーブルに vacuum analyze を行います。

-k, --skip-nodata-check

空タイルを保持してラスターバンドごとの NODATA 値のチェックを省きます。チェック時間を抑えることになりますが、データベース内の不要な行がずっと増えて、これらの行が空タイルとされないことに注意して下さい。

-T, --tablespace tablespace

生成されるテーブルのテーブルスペースを指定します。-X フラグを併用しない場合には、インデックス (主キーを含む) はデフォルトのテーブルスペースを使用することにご注意ください。

-X, --index-tablespace tablespace

テーブルの新しいインデックスに使うテーブル空間を指定します。主キーに適用され、-I フラグがある場合においては空間インデックスにも適用されます。

-Y, --copy [MAX_ROWS_PER_COPY]

COPY ステートメントを使い、INSERT を使いません。任意でmax_rows_per_copyを指定します。指定しない場合のデフォルト値は 50です。

-e, --no-transaction

ステートメント毎に実行して、トランザクションを使用しないようにします。

-E, --endian ENDIAN

生成されるラスターのバイナリ出力のエンディアンを制御します。XDR (訳注: ビッグエンディアン) の場合は 0を、NDR (訳注:リトルエンディアン) の場合は 1を、それぞれ指定します。デフォルトは 1です。現時点では NDR 出力のみサポートします。

-V, --wkb-version version

出力書式の版を指定します。デフォルトは 0です。現時点では 0のみサポートします。

10.1.2. PostGIS ラスター関数を用いたラスターの生成

データベース内でラスターやラスタテーブルを生成したい場合が多くあります。これを行うための関数が多数あります。一般的な手順は次の通りです。

  1. 新しいラスター行を保持するためのラスターカラムを持つテーブルを生成します:

    コード
    CREATE TABLE myrasters(rid serial primary key, rast raster);
  2. この目標で助けとなる関数は多数あります。他のラスターの派生でないラスターを生成する場合、ST_MakeEmptyRasterST_AddBandを順次実行して作業を開始します

    ジオメトリーからラスターを生成することもできます。ST_AsRasterを使います。ST_UnionST_MapAlgebraFctや、地図解析関数群等といった、他の関数を組み合わせる場合もあります。

    既存テーブルから新しいラスターテーブルを生成するための多数の選択肢があります。たとえば、ST_Transformを使って、既存テーブルから異なる投影法のラスターテーブルを生成します

  3. はじめにテーブルにデータを入れたら、ラスターカラムに空間インデックスを生成したくなるでしょう:

    コード
    CREATE INDEX myrasters_rast_st_convexhull_idx ON myrasters USING gist(ST_ConvexHull(rast));

    ST_ConvexHullを使用していることに注意して下さい。多くのラスター演算子はラスターの凸包を元にしています。

    [注記]

    2.0より前の PostGIS ラスターは、エンベロープを基本にして、凸包ではありませんでした。空間インデックスを適切に働かせるには、エンベロープを基本にしたインデックスを削除して、凸包を元にしたインデックスに置き換えます。

  4. AddRasterConstraintsを用いてラスター制約を適用します

10.1.3. 「データベース外」クラウドラスターの使用

raster2pgsqlツールは GDAL を使用してラスターデータにアクセスします。また、クラウドの「オブジェクト保存」 (AWS S3や Google Cloud Storage 等) にリモート格納されたラスターを読む能力という、重要なGDAL 機能の利点を享受することができます。

クラウドストレージの効率的な仕様には、「クラウド最適化」された書式の使用が必要です。最も知られて幅広く使われているものは、 "cloud optimized GeoTIFF"です。JPEGや非タイル化 TIFF などの非クラウド書式を使うと、発揮される能力は非常に貧弱になります。システムがラスターの一部分にアクセスする必要に迫られるたびに全体をダウンロードするためです。

まず、ラスターをあなたが選択したクラウドストレージに保存します。保存したら、アクセスに使う URI が得られます。"http"URI か、時々特別なサービスを示す URI ( "s3://bucket/object"等) です。非公開バケットにアクセスするには、接続認証のための GDAL コンフィギュレーションオプションが必要になります。このコマンドはクラウドラスターから読み、データベースに書きます。

コード
AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx \
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
raster2pgsql \
  -s 990000 \
  -t 256x256 \
  -I \
  -R \
  /vsis3/your.bucket.com/your_file.tif \
  your_table \
  | psql your_db

テーブルがロードされたら、データベースにリモートラスターらか読むためのアクセス許可を与えます。postgis.enable_outdb_rasterspostgis.gdal_enabled_driversの、二つのアクセス許可を設定します。

コード
SET postgis.enable_outdb_rasters = true;
SET postgis.gdal_enabled_drivers TO 'ENABLE_ALL';
    

確実に変更するには、データベースに直接設定します。新しい設定を使うには再接続が必要です。

コード
ALTER DATABASE your_db SET postgis.enable_outdb_rasters = true;
ALTER DATABASE your_db SET postgis.gdal_enabled_drivers TO 'ENABLE_ALL';
    

非公開ラスターの場合、クラウドラスターから読み取るアクセスキーを与えなければならない場合があります。raster2pgsqlの書き込みに使用したのと同じキーを、データベース内でpostgis.gdal_vsi_options設定と共に使用するように設定できます。key=valueペアをスペースで区切ることで、複数のオプションを設定できることに注意してください。

コード
SET postgis.gdal_vsi_options = 'AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

データをロードし、パーミッションが設定されると、ラスターテーブルは他のラスターテーブルとおなじように、同じ関数を使って、対話的処理が可能となります。データベースは、ピクセルデータの読み取りが必要なら、クラウドへの接続の全てを扱います。

10.2. ラスターカバレッジとラスター/ベクター解析

カバレッジは、空間データを解釈する手法の一つで、位置集合 から 値集合 に対応付けます。カバレッジの評価は、ある位置の値を尋ねることです。逆の問合せでは条件に合う値になる位置を尋ねます。PostGIS は包括的な ISO 19123 coverage SQL タイプを出していませんが、ジオメトリーテーブルとラスター値は順逆両方向のクエリーの構成要素となります。

カバレッジは連続系になることができ、任意位置の計算値または補間値を得ます。離散系になることもでき、格納された空間オブジェクトまたはグリッドセルから値を得ます。カバレッジモデルはどうやって位置を値に対応付けるかを示したもので、モデルは、これらの値が数式から来たのか、テーブルから来たのか、一つ以上のラスター値から来たのかは関係ありません。時刻型のカラムまたは関数引数によって連続/離散の区別の変更なしに時刻次元が追加できます。

ベクターカバレッジでは、ジオメトリーカラムは位置集合を提供し、他のカラムは属性値集合を提供します。ベクター値集合は、意味と型がカバレッジがどこで定義されても首尾一貫するなら、文字、数値、他の空間値を含むことができます。ラスターカバレッジでは、各セルの位置は位置集合の一部でセルのバンド値は値集合を構成します。同じテーブル行の他のカラムはラスター値またはタイル全体を記述するもので、個々のセルに個別の値を付けません。

論理的なラスターカバレッジは一つのラスターまたは一つのテーブルの多数のタイルとして保存することができます。一つのカバレッジに属するタイルは SRID、解像度、アラインメント、バンド数、ピクセル型、NODATA の扱いに互換性があるべきです。「ラスターカラムカタログ」 で見ることができる制約は、これらのプロパティを記録し、検証します。

ラスターテーブル構成。. ラスターカラムは画像ウェアハウス、タイル化されたカバレッジ、ラスター化されたオブジェクトのコレクションを表現できます。これらの構成はタイルサイズ、アラインメント、隙間、重なりに関する前提が異なります。PostGIS はカラムタイプだけから意図した構成を推論しません。

構成 行の関係 代表的な使用法
画像ウェアハウス 独立したラスター。サイズ、アラインメント、範囲は離れるか一部重複します 関連しない元画像のカタログ化
不規則タイルカバレッジ 一つの論理カバレッジ、隙間可、可変タイルサイズ、通常は重複箇所無し 逐次追加型またはソース駆動型モザイク
規則的タイルカバレッジ 一つのアラインメントとタイルサイズで重複箇所なし。隙間はカバレッジの境界または内部に残る可能性あり 大きなカバレッジの上でのインデックスを使った解析
規則的長方形カバレッジ 隙間も重複も無い長方形範囲を満たす同じサイズかつ同じアラインメントを持つタイル 予測可能なブロック処理とオーバービュー生成
分離タイル画像 個々の画像は内部では規則的だがそれぞれ別個のテーブルまたはパーティションに格納 元画像の識別性の維持と画像ごとの管理できる状態の維持
地物ラスター化カバレッジ 個々の行はラスター化された地物で、範囲とサイズは異なることがあり、かつオーバーラップすることがある セルがベクタージオメトリーを置き換えるか補完する地物モデル

共通の SRID、解像度、アラインメント、バンド、範囲、規則的ブロックのプロパティの記録には AddRasterConstraints を使います。カタログが表現できない関係のために空間インデックスとアプリケーション側の制約を使います。

タイルカバレッジに対するクエリーには通常は二つの段階があります:

  1. ラスター空間インデックスと ST_Intersects を使い候補タイルを選択します。

  2. ST_ValueST_ClipST_SummaryStatsAggST_DumpAsPolygons といった関数を使って、これらのタイルの内側の値を読み、切り取り、集約し、ベクター化します。

ST_DumpAsPolygons は、ジオメトリーとセル値の組合せとなる geomval の行を返します。これにより通常のジオメトリーのオーバーレイとフィルタによって逆カバレッジクエリーの答えを出せるようになりますが、多数のセルのポリゴン化は通常はラスターで処理を続ける場合よりも計算コストが高くなります。

境界の扱いを慎重に選択します。ラスターピクセルの切抜きと集約は通常は短く早い手順です。境界セルの一部を、そのセルに覆われる面積に比例して寄与させなければならない場合には、そのジオメトリーと geomval 行とでインターセクトさせて、適切な投影座標系上の面積で重みづけした結果を計算します。この正確な部分セル法は選択セルのベクター化を行うので、よりコストがかかります。

タイルサイズはインデックスを使うクエリーに影響を与えます: 小さいタイルでは、行とインデックスのオーバーヘッダが増える半面、個々の候補行で調査するラスターデーターの数が減ります。一つのタイルサイズを共通のデフォルトとして扱う代わりに、代表クエリーでベンチマークを行います。

現在の一連のラスター/ベクター処理パターンでは、「raster2pgsql を使ってラスターをロードする」 によるデータのロードとタイル化をし、ST_SummaryStats で建物の例を参照します。インターセクトするタイルを選択し、個々のポリゴンで切り抜き、タイルごとの統計情報を地物ごとの結果とまとめます。動物の位置情報といったポイント観察では、最初にポイントに対して適切な投影座標系の上でバッファーを施して、同じようにタイル選択、切抜き、集約のパターンを、標高や他の連続系ラスターカバレッジに適用します。

10.3. ラスターカタログ

PostGIS が生成する、二つのラスターカタログのビューがあります。両方ともラスターテーブルの制約の中に埋め込まれる情報を用いています。結果として、カタログビューは、テーブル内のラスターデータに制約が働くため、常にラスターデータとの矛盾がありません。

  1. raster_columns ラスタータイプのデータベースにおける全てのラスタテーブルカラムのカタログです。

  2. raster_overviews データベース内の、より詳細なテーブルのためのオーバビューを提供するラスターテーブルのカラム全てのカタログです。この種のテーブルは、ロード時に-lを指定した時に生成されます。

10.3.1. ラスターカラムカタログ

raster_columnsは、ラスタータイプのデータベースにおける全てのラスターテーブルカラムのカタログです。テーブルの制約を使ったビューなので、他のデータベースのバックアップからラスターテーブルをリストアしたとしても、情報は常に矛盾がありません。raster_columnsカタログには次のカラムがあります。

ローダを使わずにテーブルを生成したり、ロード時に-C フラグを忘れたりした場合には、事後にAddRasterConstraintsで制約を強制でき、raster_columnsカタログは、ラスタータイルの共通の情報を登録します。

  • r_table_catalog テーブルが存在するデータベースです。これは常に現在のデータベースを読みます。

  • r_table_schema ラスターテーブルが属するデータベーススキーマです。

  • r_table_name ラスターテーブルです。

  • r_raster_column ラスタータイプであるr_table_nameテーブルのカラムです。PostGIS には、一つのテーブルに複数のラスターカラムを持つことを妨げません。異なるラスターカラムを持つラスターテーブルが、ラスターカラム毎に複数回出現するテーブルを持つことができます。

  • srid ラスターの空間参照系識別番号です。「空間参照系」にあるエントリであるべきです。

  • scale_x 地理空間座標とピクセルの間の拡大縮小係数です。これは、ラスターカラムのすべてのタイルが同じscale_xを持ち、制約が適用されている場合のみ出現します。詳細情報についてはST_ScaleXを参照してください。

  • scale_y 地理空間座標とピクセルの間の拡大縮小係数です。これは、ラスターカラムのすべてのタイルが同じscale_yを持ち、scale_yの制約が適用されている場合のみ出現します。詳細情報についてはST_ScaleYを参照してください。

  • blocksize_x ラスタータイルごとの幅 (横方向のピクセル数) です。詳細情報についてはST_Widthを参照してください。

  • blocksize_y ラスタータイルごとの高さ (縦方向のピクセル数) です。詳細情報についてはST_Heightを参照してください。

  • same_alignment 全てのラスタータイルが同じアラインメントを持っているかを示す真偽値です。詳細情報についてはST_SameAlignmentを参照してください。

  • regular_blocking ラスターカラムが空間的に一意かつカバレッジタイルの制約を持つなら、TRUE となります。その他の場合は FALSE になります。。

  • num_bands ラスター集合のタイルごとのバンド数。これと同じ情報が得られる関数は ST_NumBands

  • pixel_types バンドごとのピクセルタイプを定義する配列です。この配列の要素数はバンド数と同じです。pixel_types は、ST_BandPixelTypeで定義されるピクセルタイプの一つを取ります。

  • nodata_values バンド毎のnodata_valueを示す倍精度浮動小数点数の配列です。バンド数と同じ配列数となります。これらの値は、バンド毎のほとんどの処理で無視されるべきピクセル値の定義です。これはST_BandNoDataValueで得られる情報と似ています。

  • out_db ラスターバンドデータがデータベース外で維持されているかを示す真偽値の配列です。この配列の添え字はバンド番号と同じです。

  • extent ラスター集合における全てのラスター行の範囲です。集合の範囲を変更するデータを別途ロードする予定である場合、ロード前にDropRasterConstraints関数を実行して、ロード後にAddRasterConstraintsで制約を再適用します。

  • spatial_index 空間インデックスを持っているかどうかを示す真偽値です。

10.3.2. ラスターオーバビュー

raster_overviewsは、オーバビューで使われるラスターテーブルカラムに関する情報のカタログで、オーバビューを用いる際に知っておくと便利な情報も持ちます。オーバビューテーブルはraster_columnsraster_overviewsの両方のカタログに入れられます。オーバビューもラスターの一つであるのは確かですが、より高い解像度テーブルの解像度を落としたカリカチュアになるという特殊な目的を満たすためでもあるからです。ラスターをロードする際に-lスイッチを使うと、オーバビューが主ラスターテーブルと一緒に生成されます。もしくは、AddOverviewConstraintsを使うと手動で生成できます。

オーバビューテーブルには、他のラスターテーブルと同じ制約と、オーバビュー特有の制約となる追加情報があります。

[注記]

raster_overviewsの情報はraster_columnsとは重複しません。raster_columnsにあるオーバビューテーブルに関する情報が必要な場合は、raster_overviewsraster_columnsとを結合すると、必要な情報の集合を完全に取得することができます。

オーバビューの主たる理由は次の二つです。

  1. ズームアウトした際の地図表示を早くするために、元のテーブルの低解像度表現が一般的に使われます。

  2. レコード数が少なく、ピクセル毎の適用範囲が広いため、高解像度の元テーブルより計算が一般的に早くなります。計算は高解像度テーブルより精度は落ちますが、大まかな計算には十分でありえます。

raster_overviewsカタログには、次の情報のカラムがあります。

  • o_table_catalog オーバビューテーブルが存在するデータベースです。常に現在のデータベースを読みます。

  • o_table_schema オーバビューラスターテーブルが属するデータベーススキーマです。

  • o_table_name ラスターオーバビューテーブル名です。

  • o_raster_column オーバビューテーブル内のラスターカラムです。

  • r_table_catalog このオーバビューの元となるラスターテーブルのデータベースです。常に現在のデータベースを読みます。

  • r_table_schema このオーバビューの元となるラスターテーブルが属するデータベーススキーマです。

  • r_table_name このオーバビューの元となるラスターテーブルです。

  • r_raster_column このオーバビューの元となるラスターカラムです。

  • overview_factor - オーバビューテーブルのピラミッドレベルです。高い数字ほど解像度が低くなります。raster2pgsql は、画像のフォルダを渡された場合は、分割して、イメージファイルのオーバビューの計算とロードを行います。レベル 1は元ファイルと同じです。レベル 2は、元ファイルの 4分の 1になります。たとえば、5000x5000ピクセルの画像ファイルのフォルダがあるとして、125x125に分ける場合、画像ファイルごとに(5000*5000)/(125*125) = 1600行のレコードを持ち、o_2テーブル (レベル 2) は ceiling(1600/Power(2,2)) = 400行、o_3(レベル 3) では ceiling(1600/Power(2,3) ) = 200行のレコードを持ちます。ピクセルがタイルサイズで割り切れない場合、スクラップタイル (完全には値が入っていない) が得られます。raster2pgsql によって生成される個々のオーバビュータイルは、元となるラスターと同じピクセル数を持ち、個々のピクセルの表現範囲 (オリジナルの Power(2,overview_factor) ピクセル分) が低い解像度になっている点に注意して下さい。

10.4. PostGIS ラスターを使ったカスタムアプリケーションの構築

PostGIS ラスターに知られている画像書式でラスターをレンダリングするための SQL 関数があります。このことから多数のレンダリングの選択肢が使えます。たとえば、OpenOffice/LibreOffice を使ってレンダリングが可能で、Rendering PostGIS Raster graphics with LibreOffice Base Reportsにデモンストレーションがあります。さらに、本節で示す通り、多種多様な言語を使用できます。

10.4.1. ST_AsPNG を他の関数とあわせて使った PHP 出力例

本節では、PHP の PostgreSQL ドライバーとST_AsGDALRaster等の関数を使って、HTML img タグに埋め込むことができる PHP リクエストストリームにラスターの 1、2、3バンドを出力する方法を示します。

サンプルクエリでは、 指定した WGS84バウンディングボックスにインタセクトするタイルを取って、 ST_Unionでインタセクトしたタイルを結合して全てのバンドを返し、ST_Transformでユーザー指定投影法に変換し、ST_AsPNGを使って PNG で結果を出力するためのラスター関数群全体をまとめる方法を示します。

このスクリプトは http://mywebserver/test_raster.php?srid=2249 で呼んで、フィート単位マサチューセッツ州平面座標系のラスター画像を得ます。

コード
<?php
$conn_str = 'dbname=mydb host=localhost port=5432 user=myuser password=mypwd';
$dbconn = pg_connect($conn_str);
header('Content-Type: image/png');

if (!empty($_REQUEST['srid']) &amp;&amp; is_numeric($_REQUEST['srid'])) {
    $input_srid = intval($_REQUEST['srid']);
} else {
    $input_srid = 26986;
}

$sql = "SET bytea_output = 'escape';
SELECT ST_AsPNG(
    ST_Transform(
        ST_AddBand(
            ST_Union(rast, 1),
            ARRAY[ST_Union(rast, 2), ST_Union(rast, 3)]
        ),
        $input_srid
    )
) AS new_rast
FROM aerials.boston
WHERE ST_Intersects(
    rast,
    ST_Transform(
        ST_MakeEnvelope(-71.1217, 42.227, -71.1210, 42.218, 4326),
        26986
    )
)";

$result = pg_query($sql);
$row = pg_fetch_row($result);
pg_free_result($result);
if ($row === false) return;
echo pg_unescape_bytea($row[0]);
?>

10.4.2. ST_AsPNG を他の関数とあわせて使った ASP.NET C#出力例

本節では Npgsql PostgreSQL.NET ドライバーと ST_AsGDALRaster 系の使い方を示します。1, 2, 3 バンドを HTTP 応答ストリームに出力するので、img タグに埋め込むことができます。

この例では Npgsql .NET PostgreSQL ドライバーが必要です。最新版はhttp://npgsql.projects.postgresql.org/にあります。最新版をダウンロードして、ASP.NET の bin フォルダに入れるだけでうまくいきます。

サンプルクエリでは、 指定した WGS84バウンディングボックスにインタセクトするタイルを取って、 ST_Unionでインタセクトしたタイルを結合して全てのバンドを返し、ST_Transformでユーザー指定投影法に変換し、ST_AsPNGを使って PNG で結果を出力するためのラスター関数群全体をまとめる方法を示します。

この例は C#で実装している点を除いては「ST_AsPNG を他の関数とあわせて使った PHP 出力例」と同じです。

http://mywebserver/TestRaster.ashx?srid=2249 でフィート単位マサチューセッツ州平面のラスター画像を得るための処理プログラムを呼び出します。

web.config の接続文字列設定部分:

コード
<connectionStrings>
    <add name="DSN"
        connectionString="server=localhost;database=mydb;Port=5432;User Id=myuser;password=mypwd"/>
</connectionStrings>

TestRaster.ashx のコード:

コード
<%@ WebHandler Language="C#" Class="TestRaster" %>
using System;
using System.Data;
using System.Web;
using Npgsql;

public class TestRaster : IHttpHandler
{
    public void ProcessRequest(HttpContext context)
    {
        context.Response.ContentType = "image/png";
        context.Response.BinaryWrite(GetResults(context));
    }

    public bool IsReusable {
        get { return false; }
    }

    public byte[] GetResults(HttpContext context)
    {
        byte[] result = null;
        NpgsqlCommand command;
        string sql = null;
        int input_srid = 26986;
        try {
            string connectionString = System.Configuration.ConfigurationManager
                .ConnectionStrings["DSN"].ConnectionString;
            using (NpgsqlConnection conn = new NpgsqlConnection(connectionString)) {
                conn.Open();

                if (context.Request["srid"] != null)
                {
                    input_srid = Convert.ToInt32(context.Request["srid"]);
                }
                sql = @"SELECT ST_AsPNG(
                            ST_Transform(
                                ST_AddBand(
                                    ST_Union(rast, 1),
                                    ARRAY[ST_Union(rast, 2), ST_Union(rast, 3)]
                                ),
                                :input_srid
                            )
                        ) As new_rast
                        FROM aerials.boston
                        WHERE ST_Intersects(
                            rast,
                            ST_Transform(
                                ST_MakeEnvelope(
                                    -71.1217, 42.227,
                                    -71.1210, 42.218,
                                    4326
                                ),
                                26986
                            )
                        )";
                command = new NpgsqlCommand(sql, conn);
                command.Parameters.Add(new NpgsqlParameter("input_srid", input_srid));


                result = (byte[]) command.ExecuteScalar();
                conn.Close();
            }

        }
        catch (Exception ex)
        {
            result = null;
            context.Response.Write(ex.Message.Trim());
        }
        return result;
    }
}

10.4.3. raster クエリを画像ファイルで出力する Java コンソールアプリケーション

これは、一つの画像を返すクエリを取り、指定したファイルに出力する、簡単な Javaコンソールアプリケーションです。

最新の PostgreSQL JDBC ドライバーはhttp://jdbc.postgresql.org/download.htmlからダウンロードできます。

後で示すコードは次のようなコマンドでコンパイルできます:

コード
CLASSPATH=".:../postgresql.jar" javac SaveQueryImage.java
jar cfm SaveQueryImage.jar Manifest.txt *.class

そしてコマンドラインから次のように実行します:

コード
java -jar SaveQueryImage.jar \
  "SELECT ST_AsPNG(ST_AsRaster(ST_Buffer(ST_Point(1, 5), 10, 'quad_segs=2'), 150, 150, '8BUI', 100));" \
  "test.png"

Manifest.txt:

コード
Class-Path: postgresql-9.0-801.jdbc4.jar
Main-Class: SaveQueryImage

SaveQueryImage.java のコード:

コード
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.io.*;

public class SaveQueryImage {
  public static void main(String[] argv) {
      System.out.println("Checking if Driver is registered with DriverManager.");

      try {
        //java.sql.DriverManager.registerDriver (new org.postgresql.Driver());
        Class.forName("org.postgresql.Driver");
      }
      catch (ClassNotFoundException cnfe) {
        System.out.println("Couldn't find the driver!");
        cnfe.printStackTrace();
        System.exit(1);
      }

      Connection conn = null;

      try {
        conn = DriverManager.getConnection("jdbc:postgresql://localhost:5432/mydb", "myuser", "mypwd");
        conn.setAutoCommit(false);

        PreparedStatement sGetImg = conn.prepareStatement(argv[0]);

        ResultSet rs = sGetImg.executeQuery();

        FileOutputStream fout;
        try
        {
            rs.next();
            /** Output to file name requested by user **/
            fout = new FileOutputStream(new File(argv[1]) );
            fout.write(rs.getBytes(1));
            fout.close();
        }
        catch(Exception e)
        {
            System.out.println("Can't create file");
            e.printStackTrace();
        }

        rs.close();
        sGetImg.close();
        conn.close();
      }
      catch (SQLException se) {
        System.out.println("Couldn't connect: print out a stack trace and exit.");
        se.printStackTrace();
        System.exit(1);
      }
  }
}

10.4.4. PLPython を使って SQL を介して画像をダンプする

これは、サーバディレクトリ内でレコードごとにファイルを生成する Python ストアド関数です。plpython が必要です。plpythonu と plpython3u の両方が正しく動作します。

コード
CREATE OR REPLACE FUNCTION write_file (param_bytes bytea, param_filepath text)
RETURNS text
AS $$
f = open(param_filepath, 'wb+')
f.write(param_bytes)
return param_filepath
$$ LANGUAGE plpythonu;

5個の画像を異なるサイズで PostgreSQL サーバーに書き込みます。PostgreSQL デーモンアカウントはフォルダーへの書き込み権限が必要です。この例では生成したファイル名が表示されます。

コード
SELECT write_file(
    ST_AsPNG(
        ST_AsRaster(
            ST_Buffer(ST_Point(1, 5), j * 5, 'quad_segs=2'),
            150 * j,
            150 * j,
            '8BUI',
            100
        )
    ),
    'C:/temp/slices' || j || '.png'
)
FROM generate_series(1, 5) AS j;
出力
write_file
---------------------
 C:/temp/slices1.png
 C:/temp/slices2.png
 C:/temp/slices3.png
 C:/temp/slices4.png
 C:/temp/slices5.png

10.4.5. PSQL でラスターを出力する

悲しいことに PSQL はバイナリー出力の使いやすい組込み機能がありません。ここで示すのは PostgreSQL の少しレガシーなラージオブジェクト機能に便乗するハッキングです。使用するにはデータベースへの psql コマンドライン接続が必要です。

この方法は Python の場合と違い、ローカル機にファイルが生成されます。

コード
SELECT
    oid,
    lowrite(lo_open(oid, 131072), png) AS num_bytes
FROM (VALUES (
    lo_create(0),
    ST_AsPNG((SELECT rast FROM aerials.boston WHERE rid = 1))
)) AS v(oid, png);
出力
oid   | num_bytes
---------+-----------
 2630819 |     74860

ラージオブジェクトの OID を記録して、例のパスを求めるファイルパスに入れ替えてローカルのファイルにエクスポートします。

コード
\lo_export 2630819 'C:/temp/aerial_samp.png'

これはデータベース内のラージオブジェクトストレージからファイルを削除します。

コード
SELECT lo_unlink(2630819);