第 10 章。網格數據管理、查詢與應用

目錄

10.1. 載入與建立網格

對於大多數使用案例,您將會使用封裝的 raster2pgsql 網格載入器載入現有的網格檔案來建立 PostGIS 網格。

10.1.1. 使用 raster2pgsql 載入網格

raster2pgsql 是一個網格載入器可執行檔,可將 GDAL 支援的網格格式載入到適合載入 PostGIS 網格表格的 SQL 中。它可以載入網格檔案資料夾,以及建立網格的概觀。

由於 raster2pgsql 通常是 PostGIS 的一部分編譯(除非您編譯自己的 GDAL 函式庫),因此可執行檔支援的網格類型將與 GDAL 相依性函式庫中編譯的類型相同。若要取得特定 raster2pgsql 支援的網格類型清單,請使用 -G 切換。

[Note]

當從一組對齊的網格建立特定因子的概觀時,概觀可能會不對齊。請造訪 http://trac.osgeo.org/postgis/ticket/1764 以取得概觀未對齊的範例。

10.1.1.1. 使用範例

使用載入器建立輸入檔案並將其以 100x100 圖塊分塊上傳的範例工作階段可能如下所示

# -s use srid 4326
# -I create spatial index
# -C use standard raster constraints
# -M vacuum analyze after load
# *.tif load all these files
# -F include a filename column in the raster table
# -t tile the output 100x100
# public.demelevation load into this table
raster2pgsql -s 4326 -I -C -M -F -t 100x100 *.tif public.demelevation > elev.sql

# -d connect to this database
# -f read this file after connecting
psql -d gisdb -f elev.sql
[Note]

如果您未將結構描述指定為目標表格名稱的一部分,則表格將會在資料庫或您連線的使用者的預設結構描述中建立。

使用 UNIX 管線,可以在一個步驟中完成轉換和上傳

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

將馬薩諸塞州平面公尺的航空圖塊載入名為 aerial 的結構描述,並建立完整檢視、2 和 4 層級概觀表,使用複製模式進行插入(不使用中間檔案,而是直接存入資料庫),以及 -e 不要強制將所有內容放入交易中(如果您希望立即在表格中查看資料,而不必等待,這會很有用)。將網格分解為 128x128 像素的圖塊並套用網格約束。使用複製模式,而不是表格插入。 (-F) 包含一個名為 filename 的欄位,以保留從中裁切圖塊的檔案名稱。

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
--get a list of raster types supported:
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 選項

-?

顯示說明畫面。如果您未傳入任何引數,也會顯示說明。

-G

列印支援的網格格式。

(c|a|d|p) 這些是互斥選項

-c

建立新表格並以網格填入,這是預設模式

-a

將網格附加到現有表格。

-d

捨棄表格,建立新表格並以網格填入

-p

準備模式,僅建立表格。

網格處理:套用約束以在網格目錄中正確註冊

-C

套用網格約束 - srid、像素大小等,以確保網格已在 raster_columns 檢視中正確註冊。

-x

停用設定最大範圍約束。只有在使用 -C 旗標時才會套用。

-r

為規則區塊設定約束(空間唯一性和涵蓋範圍圖塊)。只有在使用 -C 旗標時才會套用。

網格處理:用於操作輸入網格資料集的選用參數

-s <SRID>

使用指定的 SRID 指派輸出網格。如果未提供或為零,將會檢查網格的中繼資料以判斷適當的 SRID。

-b BAND

要從網格中擷取的頻帶索引(從 1 開始)。對於多個頻帶索引,請使用逗號 (,) 分隔。如果未指定,將會擷取網格的所有頻帶。

-t TILE_SIZE

將網格裁切成圖塊,以每個表格列插入一個。 TILE_SIZE 表示為 WIDTHxHEIGHT,或設定為「auto」值,以允許載入器使用第一個網格計算適當的圖塊大小,並套用到所有網格。

-P

填補最右邊和最底部的圖塊,以確保所有圖塊都具有相同的寬度和高度。

-R, --register

將網格註冊為檔案系統 (out-db) 網格。

只有網格的中繼資料和網格路徑位置會儲存在資料庫中(而非像素)。

-l OVERVIEW_FACTOR

建立網格概觀。對於多個因子,請使用逗號 (,) 分隔。概觀表名稱遵循 o_概觀因子_表格 模式,其中 概觀因子 是數值概觀因子的預留位置,而 表格 則會取代為基礎表名稱。建立的概觀會儲存在資料庫中,且不受 -R 的影響。請注意,您產生的 sql 檔案將會包含主表格和概觀表。

-N NODATA

在沒有 NODATA 值的頻帶上使用的 NODATA 值。

用於操作資料庫物件的選用參數

-f COLUMN

指定目的地網格欄的名稱,預設值為 'rast'

-F

新增一個包含檔案名稱的欄

-n COLUMN

指定檔案名稱欄的名稱。暗示 -F。

-q

將 PostgreSQL 識別碼以引號括住。

-I

在網格欄上建立 GiST 索引。

-M

分析網格表格。

-k

保留空白圖塊,並略過每個網格頻帶的 NODATA 值檢查。請注意,您可以節省檢查時間,但可能會在資料庫中產生更多垃圾列,而且這些垃圾列不會標記為空白圖塊。

-T tablespace

指定新表格的表格空間。請注意,索引(包括主索引鍵)仍將使用預設表格空間,除非也使用了 -X 旗標。

-X tablespace

指定表格新索引的表格空間。如果使用 -I 旗標,這會套用到主索引鍵和空間索引。

-Y max_rows_per_copy=50

使用複製陳述式,而不是插入陳述式。您可以選擇性地指定 max_rows_per_copy;如果未指定,預設值為 50。

-e

個別執行每個陳述式,不使用交易。

-E ENDIAN

控制網格產生的二進位輸出的位元組順序;為 XDR 指定 0,為 NDR 指定 1(預設值);目前僅支援 NDR 輸出

-V version

指定輸出格式的版本。預設值為 0。目前僅支援 0。

10.1.2. 使用 PostGIS Raster 函數建立網格

在許多情況下,您會想要在資料庫中直接建立網格和網格表。有很多函數可以執行此操作。以下是一般步驟。

  1. 建立一個具有網格欄的表格,以保留可以使用下列命令完成的新網格記錄

    CREATE TABLE myrasters(rid serial primary key, rast raster);
  2. 有很多函數可以協助您達成此目標。如果您建立的網格不是其他網格的衍生,您將會想要從以下項目開始:ST_MakeEmptyRaster,然後是 ST_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 的使用,因為大多數網格運算子都以網格的凸包為基礎。

    [Note]

    PostGIS Raster 2.0 之前的版本是以包絡而非凸包為基礎。為了使空間索引能正常運作,您需要捨棄這些索引,並以凸包為基礎的索引取代。

  4. 使用 AddRasterConstraints 套用網格約束

10.1.3. 使用「out db」雲端網格

raster2pgsql 工具使用 GDAL 來存取網格資料,並且可以利用 GDAL 的一個主要功能:從 遠端儲存在雲端「物件儲存體」(例如 AWS S3、Google Cloud Storage)中的網格讀取資料的能力。

有效率地使用雲端儲存的網格需要使用「雲端最佳化」格式。最著名且廣泛使用的是「雲端最佳化 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 內建了兩個柵格目錄檢視。這兩個檢視都利用了嵌入在柵格表格約束中的資訊。因此,目錄檢視始終與表格中的柵格資料保持一致,因為約束是強制執行的。

  1. raster_columns 這個檢視會編錄資料庫中所有柵格表格的欄位。

  2. raster_overviews 這個檢視會編錄資料庫中所有作為較細粒度表格概觀的柵格表格欄位。當您在載入期間使用 -l 參數時,會產生這種類型的表格。

10.2.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 柵格的空間參考識別碼。應該是 第 4.5 節,「空間參考系統」中的一個項目。

  • scale_x 幾何空間座標和像素之間的比例。僅當柵格欄中的所有圖塊都具有相同的 scale_x 並應用此約束時才可用。有關更多詳細資訊,請參閱 ST_ScaleX

  • scale_y 幾何空間座標和像素之間的比例。僅當柵格欄中的所有圖塊都具有相同的 scale_y 並應用 scale_y 約束時才可用。有關更多詳細資訊,請參閱 ST_ScaleY

  • blocksize_x 每個柵格圖塊的寬度(像素數)。有關更多詳細資訊,請參閱 ST_Width

  • blocksize_y 每個柵格圖塊的高度(像素數)。有關更多詳細資訊,請參閱 ST_Height

  • same_alignment 如果所有柵格圖塊都具有相同的對齊方式,則為布林值 True。有關更多詳細資訊,請參閱 ST_SameAlignment

  • regular_blocking 如果柵格欄具有空間唯一性和覆蓋圖塊約束,則值為 TRUE。否則,將為 FALSE。

  • num_bands 柵格集中每個圖塊中的波段數。這與 ST_NumBands 提供的資訊相同。

  • pixel_types 一個陣列,定義每個波段的像素類型。此陣列中的元素數與您擁有的波段數相同。像素類型是 ST_BandPixelType 中定義的以下類型之一。

  • nodata_values 一個雙精度數字陣列,表示每個波段的 nodata_value。此陣列中的元素數與您擁有的波段數相同。這些數字定義每個波段的像素值,該像素值在大多數操作中應忽略。這與 ST_BandNoDataValue 提供的資訊類似。

  • out_db 一個布林旗標陣列,表示柵格波段資料是否保存在資料庫之外。此陣列中的元素數與您擁有的波段數相同。

  • extent 這是柵格集中所有柵格列的範圍。如果您計劃載入更多會變更集合範圍的資料,您需要在載入之前執行 DropRasterConstraints 函式,然後在載入後使用 AddRasterConstraints 重新套用約束。

  • spatial_index 如果柵格欄具有空間索引,則為布林值 True。

10.2.2. 柵格概觀

raster_overviews 編錄用於概觀的柵格表格欄位的相關資訊,以及在使用概觀時有用的其他資訊。概觀表格會在 raster_columnsraster_overviews 中編錄,因為它們本身是柵格,但也具有作為較高解析度表格的較低解析度縮圖的特殊用途。當您在柵格載入中使用 -l 參數時,會與主要柵格表格一起產生這些表格,或者可以使用 AddOverviewConstraints 手動產生。

概觀表格包含與其他柵格表格相同的約束,以及特定於概觀的其他資訊性約束。

[Note]

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 個原始圖塊。因此,例如,如果您有一個 5000x5000 像素圖片檔案的資料夾,而您選擇將其分割為 125x125,則對於每個圖片檔案,您的基礎表格將有 (5000*5000)/(125*125) 筆記錄 = 1600,您的 (l=2) o_2 表格將有 ceiling(1600/Power(2,2)) = 400 列,您的 (l=3) o_3 將有 ceiling(1600/Power(2,3) ) = 200 列。如果您的像素不能被您的圖塊大小整除,您會得到一些殘餘圖塊(未完全填滿的圖塊)。請注意,raster2pgsql 產生的每個概觀圖塊都與其父圖塊具有相同的像素數,但解析度較低,其中它的每個像素代表原始像素的 (Power(2,overview_factor)) 個像素。

10.3. 使用 PostGIS 柵格建立自訂應用程式

PostGIS 柵格為您提供使用已知影像格式呈現柵格的 SQL 函式,這事實為您提供了許多呈現它們的選項。例如,您可以使用 OpenOffice/LibreOffice 進行呈現,如 使用 LibreOffice Base 報告呈現 PostGIS 柵格圖形 中所示。此外,您可以如本節所示使用各種語言。

10.3.1. PHP 範例,結合其他柵格函式使用 ST_AsPNG 輸出

在本節中,我們將示範如何使用 PHP PostgreSQL 驅動程式和 ST_AsGDALRaster 函式系列,將柵格的波段 1、2、3 輸出到 PHP 要求串流,然後可以將其嵌入 img src html 標籤中。

這個範例查詢示範如何結合一連串的柵格函數,以抓取與特定 WGS 84 邊界框相交的所有圖塊,然後使用 ST_Union 將相交的圖塊聯合在一起,返回所有波段,使用 ST_Transform 轉換為使用者指定的投影,然後使用 ST_AsPNG 將結果輸出為 PNG。

您可以使用以下方式呼叫下方程式碼:

http://mywebserver/test_raster.php?srid=2249

以取得麻薩諸塞州州平面英尺的柵格影像。

<?php
/** contents of test_raster.php **/
$conn_str ='dbname=mydb host=localhost port=5432 user=myuser password=mypwd';
$dbconn = pg_connect($conn_str);
header('Content-Type: image/png');
/**If a particular projection was requested use it otherwise use mass state plane meters **/
if (!empty( $_REQUEST['srid'] ) &amp;&amp; is_numeric( $_REQUEST['srid']) ){
		$input_srid = intval($_REQUEST['srid']);
}
else { $input_srid = 26986; }
/** The set bytea_output may be needed for PostgreSQL 9.0+, but not for 8.4 **/
$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.3.2. ASP.NET C# 範例:結合其他柵格函數使用 ST_AsPNG 輸出

在本節中,我們將示範如何使用 Npgsql PostgreSQL .NET 驅動程式和 ST_AsGDALRaster 系列函數,將柵格的波段 1、2、3 輸出到 PHP 請求串流,然後將其嵌入到 img src HTML 標籤中。

此練習需要 npgsql .NET PostgreSQL 驅動程式,您可以從 http://npgsql.projects.postgresql.org/ 取得最新版本。只需下載最新版本並放入您的 ASP.NET bin 資料夾即可。

這個範例查詢示範如何結合一連串的柵格函數,以抓取與特定 WGS 84 邊界框相交的所有圖塊,然後使用 ST_Union 將相交的圖塊聯合在一起,返回所有波段,使用 ST_Transform 轉換為使用者指定的投影,然後使用 ST_AsPNG 將結果輸出為 PNG。

這與 第 10.3.1 節「PHP 範例:結合其他柵格函數使用 ST_AsPNG 輸出」 的範例相同,只是以 C# 實作。

您可以使用以下方式呼叫下方程式碼:

http://mywebserver/TestRaster.ashx?srid=2249

以取得麻薩諸塞州州平面英尺的柵格影像。

 -- web.config connection string section --
<connectionStrings>
    <add name="DSN"
        connectionString="server=localhost;database=mydb;Port=5432;User Id=myuser;password=mypwd"/>
</connectionStrings>
// Code for 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 {
		    using (NpgsqlConnection conn = new NpgsqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DSN"].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.3.3. Java 主控台應用程式:將柵格查詢輸出為影像檔案

這是一個簡單的 Java 主控台應用程式,它接受一個返回單一影像的查詢,並將其輸出到指定的檔案。

您可以從 http://jdbc.postgresql.org/download.html 下載最新的 PostgreSQL JDBC 驅動程式

您可以使用類似以下的指令編譯以下程式碼:

set env CLASSPATH .:..\postgresql-9.0-801.jdbc4.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
// Code for 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://127.0.0.1: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.3.4. 使用 PLPython 透過 SQL 傾印影像

這是一個 plpython 儲存函數,它會為每個記錄在伺服器目錄中建立一個檔案。需要您安裝 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;
--write out 5 images to the PostgreSQL server in varying sizes
-- note the postgresql daemon account needs to have write access to folder
-- this echos back the file names created;
 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.3.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);
-- you'll get an output something like --
   oid   | num_bytes
---------+-----------
 2630819 |     74860

-- next note the oid and do this replacing the c:/test.png to file path location
-- on your local computer
 \lo_export 2630819 'C:/temp/aerial_samp.png'

-- this deletes the file from large object storage on db
SELECT lo_unlink(2630819);