OpenLayers WebGL瓦片图层和样式

前言

       OpenLayers普通图层使用canvas渲染,样式配置使用Style相关API,若想进一步控制渲染过程,对于layer对象通常有postrender方法(示例见Custom Animation),使用RasterSource(示例见Color Manipulation),Style的renderer方法(示例见Custom Circle Render),source的tileLoadFunction方法也可以从参数中获取当前瓦片的image。
       此外,WebGLPoints,WebGLTileLayer图层使用WebGL进行渲染,不适用原来基于canvas的样式配置和操作。其中WebGLPoints用于海量点渲染,WebGLTileLayer用于渲染瓦片地图,比如COG(具体概念见Cloud Optimized GeoTIFF,在下面_GeoTIFF源介绍_这一节有简介)。基于目前最新的API版本(v6.13.0),WebGLPoints只有相关Example,但API文档并不完整;WebGLTileLayer既有API文档又有示例。
       本文简单介绍WebGLTileLayer的图层和数据源,重点介绍其样式配置,辅以基于当前版本API的一些示例。

WebGLTile:图层和数据源介绍

       该图层继承自BaseTileLayer,继承了一些通用属性,下图简单标注
在这里插入图片描述

       该图层的source数据源可以指定两种,DataTileSource和TileImage
在这里插入图片描述

       其中DataTileSource是GeoTIFFSource,也就是将要着重介绍的,用于加载COG的数据源的父类。该数据源没有常见的url参数,而是使用loader参数,将数组解析为瓦片。
在这里插入图片描述

       这里仅介绍该类原理,常用的是它的子类GeoTIFFSource。GeoTIFFSource用于加载COG网络地址,其原理简单介绍就是使用Geotiff.js解析tif原始图像信息,和范围、波段等元信息(metaData)。这里介绍原理是为了,若将来需要对此过程进行扩展修改,也可以手动将tif信息以此种方式转为数组,使用DataTileSource的loader方法加载。
       除DataTileSource外,还可以加载TileImage类的数据源。TileImage是各种瓦片地图数据源类的父类,很少直接使用,而是使用其子类,见下图
在这里插入图片描述

       根据地图服务类型自行选择。
       这里补充下。一般情况下,这些瓦片数据源可以使用瓦片图层(TileLayer)加载,使用WebGLTileLayer加载可以使用WebGLTileLayer的style,控制其曝光度、对比度、饱和度等,见示例WebGL Tile Layer Styles。至于常用于控制GeoTIFFSource波段渲染的color属性是否适用于瓦片地图源,并没有做测试,也暂时没想到要这样做的原因。

GeoTIFF源介绍

       GeoTIFF数据源的基础知识。这里先介绍几个概念
       遥感影像:可以简单理解为卫星照片,用像素值记录地面信息。不同的卫星、传感器产生不同的影像种类。
       波段:遥感影像分波段记录同一位置的像素。至少一个,常见3或4个,一般是红绿蓝和近红外,但也不一定。
单波段影像

       真/假彩色合成:对多波段影像,将波段进行组合显示的两类方式。由于屏幕等介质一般是按照R-G-B方式显现颜色,而波段只有序号数字,数量和顺序不一定对的上,所以需要人工设定。真彩色指合成出来的影像符合真实颜色,假彩色就是不符合。
真彩色合成

假彩色合成

       tif/geoTif:比较常见的遥感影像文件格式,里面有各波段图像像素信息,和坐标系、波段值、nodata(表达空值的像素值)等元信息。
       COG:云优化GeoTiff,对普通tif进行处理,内部生成切片、概览,经过压缩的tif文件。
COG可以放在nginx等云容器内,网络地址作为GeoTIFFSource的url参数,见下图
Cloud Optimized GeoTIFF (COG)
在这里插入图片描述

       若COG是按照R-G-B三个波段且值是0-255,可以不设置style直接渲染真彩色。若COG波段没有按照该标准或需要另设置样式,就需要设置Style参数。

Style API简介

       这里简单介绍WebGLTileLayer的style参数对象
在这里插入图片描述

       简单机翻了下。左侧为配置对象的key,右侧为值类型。这里可见,除variables(表达式变量)使用{key[字符串]:value[字符串|数字]}类型外,其他都使用ExpressionValue(样式表达式)。这里结合一个示例介绍下使用方法。
WebGL Tile Layer Styles
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

样式表达式

       API文档见ExpressionValue,最好结合下面例子看。
       这里先给出测试demo的主要代码,下面的几种例子都只是替换其中的style变量

// COG地址
const url = "";
// 这个获取元信息的方法附录里会解释
const metaData = await this.getGeoTifMetaData(url);
// 输出的元信息,见下图
console.log(metaData);
// 取出元信息里的波段最大最小值
const bands = metaData.bands.map((item) => {
  return {
    min: parseFloat(item.STATISTICS_MINIMUM),
    max: parseFloat(item.STATISTICS_MAXIMUM),
  };
});
// 先放个空的 下面例子里设置
const style = {};
// 声明source
const source = new GeoTIFFSource({
  // 是否均一化,下面会解释
  // normalize: false,
  sources: [
    {
      url,
      nodata: metaData.noData,
    },
  ],
});
// 一个获取source的范围,坐标系等信息的异步函数
source.getView().then((view) => {
  // 声明图层
  const layer = new WebGLTile({
    // class名,会有个该类名的canvas对象
    className: "WebGLTile",
    // 样式参数
    style,
    // 数据源
    source,
    // 范围,取自source
    extent: view.extent,
  });

  const map = new Map({
    target: "map",
    layers: [layer],
    view: new View({
      projection: view.projection,
    }),
  });
  // 将地图视窗移至source范围
  map.getView().fit(view.extent!, { padding: [50, 50, 50, 50] });
});

在这里插入图片描述

单波段拉伸

       输入影像为单波段,这里的拉伸指的是,指定该波段的最小值和最大值,同时指定这两个值对应的颜色,对处于两极值中间的像素值按照两端颜色进行插值渲染。注意,最大值最小值可以不是真实的最大最小值,目的是放大中间像素值的颜色细节,进行强化显示。
       注意,下面例子里,band和颜色数组中间的0和1,代表像素值比例(范围-1~1,0是最小值,1最大值,-1为最大值的负数),不是真实值。若想使用真实值,需要设置source的normalize属性为false。

const style = {
  // 对波段1进行线性拉伸,像素值最小值设置为0,0,0,1(RGBA),最大值为255,255,255,1
  color: ["interpolate", ["linear"], ["band", 1], 0, [0, 0, 0, 1], 1, [255, 255, 255, 1]],
}

在这里插入图片描述

单波段分级

       对像素值分级渲染,指定一个级别的上下限(像素范围),设置一个颜色,最后设置一个默认颜色用于渲染范围外像素。

const style = {
  color: [
    "case",
    // 波段1 像素位于色带0~0.3范围的
    ["between", ["band", 1], 0, 0.3],
    // 使用该颜色渲染
    ["color", 255, 255, 255],
    // 0.3~0.6
    ["between", ["band", 1], 0.3, 0.6],
    ["color", 125, 125, 125],
    // 0.6~0.9
    ["between", ["band", 1], 0.6, 0.9],
    ["color", 0, 0, 0],
    // 默认颜色
    ["color", 0, 0, 0],
  ],
};

在这里插入图片描述

多波段拉伸/分级

       多波段的拉伸或分级和单波段差不多,这里设置了normalize为false,根据上面取得的各波段最大最小值真实值,进行拉伸。
       使用的是一个4波段影像。

const style = {
  color: [
    // 多波段组合需要设置为数组
    "array",
    // 这里123波段对应RGB,分别做线性拉伸,最大值*0.3为了效果比较好
    // 不同于单波段需要指定颜色,多波段可以指定颜色或数字(该波段颜色的显示比例)
    ["interpolate", ["linear"], ["band", 1], bands[0].min, 0, bands[0].max * 0.3, 1],
    ["interpolate", ["linear"], ["band", 2], bands[1].min, 0, bands[1].max * 0.3, 1],
    ["interpolate", ["linear"], ["band", 3], bands[2].min, 0, bands[2].max * 0.3, 1],
    // 这个1删掉就报错,猜测是数组长度需要符合波段数量
    1,
  ],
};

在这里插入图片描述

       多波段分级的就不放了,就是把分级的array里的单个波段做分级。

波段运算

       上面的波段组合是将1-2-3波段对应的像素值,直接组合放进R-G-B的位置显示,做的真彩色合成。有时候,为了更好的显示效果,不仅可以调换波段顺序,还可以对波段进行运算,比如使用(近红外波段-红波段)/(近红外波段+红波段)计算NDVI(归一化植被指数)。

const style = {
  color: [
    "interpolate",
    ["linear"],
    // 计算NDVI
    ["/", ["-", ["band", 4], ["band", 1]], ["+", ["band", 4], ["band", 1]]],
    // 根据计算出来的像素值做拉伸渲染
    0,
    [191, 191, 191],
    0.65,
    [0, 69, 0],
  ],
};

在这里插入图片描述

附录

获取元信息

       一般情况可以使用均一化比例拉伸或分级波段像素值,但有时候确实需要真实值,可以使用geotiff.js解析COG获取元信息。库可以通过NPM自行安装,这里是getGeoTifMetaData函数的内容

import { fromUrl } from 'geotiff';

async function getGeoTifMetaData(url: string) {
  const tiff = await fromUrl(url);

  const image = await tiff.getImage();
  const bands = [];
  const samples = image.getSamplesPerPixel();
  for (let i = 0; i < samples; i++) {
    const element = image.getGDALMetadata(i);
    bands.push(element);
  }
  const noData = image.getGDALNoData();
  return { noData, bands };
}
其他

       由于表达式变量只能赋值数字或字符串,对于颜色等数组信息就很麻烦,当变量多起来就会很繁复;还有分级渲染的分级数量要么一开始就定死,要么按照最大数量设置,不需要的再往变量里设空值,目前还没比较好的方法。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值