第 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 栅格函数创建栅格

在许多情况下,您需要在数据库中创建栅格和栅格表。有很多函数可以做到这一点。要遵循的一般步骤。

  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 栅格的 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 控制台应用程序,它接受一个返回一个图像的查询并输出到指定的文件。

您可以从 https://jdbc.postgresql.ac.cn/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 没有易于使用的内置功能来输出二进制文件。这有点像一个 hack,它利用了 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);