@ 开发种子/ geotiff
用 TypeScript 为浏览器写作的快速、高水平的 GeoTIFF 读取器, 包 @cogeotiff/core。 。 。 .
- 方便地取用COG牌和减分辨率概览.
- 自动处理无数据掩码 .
- 图像解码出主线.
- 支持的压缩 :
- Deflate, LERC, LERC+Deflate, LERC+ZSTD, LZW, JPEG (只浏览器), WebP (只浏览器), ZSTD
- 支持用户定义的解压缩算法.
特征
完整类型脚本
整个项目——包括公共API和内部代码——在TypeScript中被强烈而详尽地打入.
图像数据获取返回一个强烈输入的对象。 随着类型缩小,我们可以推断数据是像素-interleaved还是带-分隔:
import { GeoTIFF } from "@developmentseed/geotiff";
const geotiff = await GeoTIFF.fromUrl(url);
const tile = await geotiff.fetchTile(10, 10);
const { array } = tile;
if ( array.layout === "pixel-interleaved" ) {
// array is narrowed to type RasterArrayPixelInterleaved
// TypedArray interleaved pixel data in a single array
const data = array.data; // RasterTypedArray
} else if ( array.layout === "band-separate" ) {
// array is narrowed to type RasterArrayBandSeparate
// TypedArray data per raster band
const bands = array.bands; // RasterTypedArray[]
}
无不必要的数据副本
图像取取API总是在原版式中返回数据,确保数据复制只有在用户明确同意的情况下才会发生.
方便访问 COG 牌
使用 GeoTIFF.fetchTile 要装入 Tile 实例.
import { GeoTIFF } from "@developmentseed/geotiff";
// RGB Sentinel-2 image over NYC
const url = "https://sentinel-cogs.s3.us-west-2.amazonaws.com/sentinel-s2-l2a-cogs/18/T/WL/2026/1/S2B_18TWL_20260101_0_L2A/TCI.tif"
const geotiff = await GeoTIFF.fromUrl(url);
// Read full-resolution tile from bottom right of image.
// tile ordering starts at top left.
const tile = await geotiff.fetchTile(10, 10);
const {
x, // 10
y, // 10
} = tile;
// tile.array holds data & relevant metadata
const {
count, // 3 (RGB)
height, // 1024
width, // 1024
transform, // [ 10, 0, 602380, 0, -10, 4497620 ]
crs, // 32618 (EPSG code)
mask, // null
nodata, // 0
} = tile.array;
// Pixel data is in `data` or `bands`, depending on the layout
if (tile.array.layout === "pixel-interleaved") {
const { data } = tile.array; // Uint8Array(3145728) [49, 51, 46, 42, ...]
}
方便查阅概览
这个 .overviews 属性 GeoTIFF 包含一系列从最高到最低的分辨率概览。 用这些来获取您想要的解析度 .
const geotiff = await GeoTIFF.fromUrl("https://example.com/image.tif");
// Read from the first overview
// (the next-highest resolution after the full-resolution image)
const overview = geotiff.overviews[0];
// Read top-left tile of the overview
const tile = await overview.fetchTile(0, 0);
读取任何像素窗口
使用 GeoTIFF.read 来读取一个矩形的像素,而无需自己处理瓦片。 它能把窗户接起的瓷砖 缝成一 RasterArray 完全覆盖窗口。 奥米 window 读取整个图像。 概览的方法相同.
const geotiff = await GeoTIFF.fromUrl("https://example.com/image.tif");
// Read a 512x512 window, starting at column 1024 and row 2048
const array = await geotiff.read({
window: { colOff: 1024, rowOff: 2048, width: 512, height: 512 },
});
// Read a whole overview
const overview = geotiff.overviews[0];
const overviewArray = await overview.read();
无法装入图像的窗口会扔出 WindowError。 。 。 .
元件转换处理
与 @developmentseed/affine 用于方便处理图像转换,将像素位置与空间坐标连接.
全部装入 RasterArray 实例包含 Affine,跟踪该特定图像窗口的相对图像转换.
无数据遮罩自动处理
有图书馆 geotiff.js 或基础 @cogeotiff/core,您必须做额外工作来跟踪哪些内部图像代表 数据 对 口罩。我们自动处理无数据值和掩码数组.
简易 CRS 处理
GeoTIFFs可以通过一个整数EPSG代码或用户定义的CRS来定义.
对于整数 EPSG 代码 GeoTIFF.crs 方法直接返回整数,允许下游应用程序决定如何将EPSG代码解入WKT或PROJJSON格式(例如通过查询) https://epsg.io) (中文(简体) ).
对于用户定义的 CRS,我们自动将 CRS 解析为 PROJJSON 对象,可直接传递到 proj4js。这是本地实施的 没有大量 PROJ 数据缓存。这样就不需要像 geotiff-geokeys-to-proj4,否则会给你的捆绑加1.5MB.
如果您有 CRS 无法解析的图像, 请创建一个问题 .
可配置的图像解码网络工作员池
A 类 DecoderPool 解码Web Workers中的图像数据,脱离主线. 传一个给 fetchTile, (中文(简体) ), fetchTiles 或者说 read数字 :
import { defaultDecoderPool, GeoTIFF } from "@developmentseed/geotiff";
const geotiff = await GeoTIFF.fromUrl("https://example.com/image.tif");
const tile = await geotiff.fetchTile(0, 0, { pool: defaultDecoderPool() });
没有游泳池,瓦片被解码到主线上.
defaultDecoderPool() 返回单个共享池 navigator.hardwareConcurrency 内地工人。 要设置工人人数或使用自己的工人脚本,通过 size 财务报告和审定财务报表 createWorker 页:1 DecoderPool 建筑师。 A 类 DecoderPool 无 createWorker 没有工人,所以它解码 在主线.
如果与Vite捆绑, 设置 worker.format 改为 "es"。解码器工人使用顶层等待和动态导入,这是Vite默认的 iife 工人格式不支持,所以 vite build 没有它失败 :
// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig({
worker: { format: "es" },
});
根据需要动态加载压缩
与其捆绑所有出框压缩的支持,不如按需要动态加载解压器.
直到你试图装入一个图像 压缩,比如, 地方资源中心,你不支付 捆绑大小的依赖.
您也可以通过使用 DECODER_REGISTRY。例如,使用自定义 zstd 解码器:
import { Compression } from "@cogeotiff/core";
import { DECODER_REGISTRY } from "@developmentseed/geotiff";
DECODER_REGISTRY.set(Compression.Zstd, () =>
import("your-zstd-module").then((m) => m.decode),
);
解码器是一种需要 ArrayBuffer (单位:千美元) DecoderMetadata 对象返回 a Promise 被解压的字节作为 ArrayBuffer 或解码的像素。 见 Decoder 用于完整类型定义.
带上你自己的线人
GeoTIFF.open 使用任意 chunkd
Source,因此磁盘上、内存中或自定义传输后面的文件可以是
以编组方式打开;块包是独立的安装。 给我
标题源块和缓存,因为 cogeotiff 读取相抵表
一次输入一个.
import { SourceCache, SourceChunk } from "@chunkd/middleware";
import { SourceView } from "@chunkd/source";
import { SourceFile } from "@chunkd/source-file";
import { GeoTIFF } from "@developmentseed/geotiff";
const file = new SourceFile("/data/scene.tif");
const headerSource = new SourceView(file, [
new SourceChunk({ size: 64 * 1024 }),
new SourceCache({ size: 16 * 1024 * 1024 }),
]);
const geotiff = await GeoTIFF.open({ headerSource, dataSource: file });
const tile = await geotiff.fetchTile(0, 0);
用于 HTTP, 使用 GeoTIFF.fromUrl (下一节):它通过一个
RangeReader,合并、流和缓存读取方式为块
堆栈不能.
接近相同的 API 到 Python async-geotiff
TypeScript API 与我们的 Python 项目几乎相同 async-geotiff。 。 。 .
当我们为Python和浏览器建立可视化项目时,这对我们极为有用.
读取 HTTP
GeoTIFF.fromUrl 读取通过
RangeReader:读取的cogeotiff为:
页眉( IFDs, 然后每平方块一个相抵表条目) 并读取平方块
字节合并为几个流化范围请求,每个瓦片解为其
字节到来,收到的东西都藏起来, 所以一个锅在瓷砖上
已经下载的不要求.
import { GeoTIFF } from "@developmentseed/geotiff";
import { PerOriginSemaphore, RangeReader } from "@developmentseed/range-reader";
// One reader per page: files that share it share its cache and its batching
// window. (The deck.gl layers do this for you.)
const reader = new RangeReader();
const concurrencyLimiter = new PerOriginSemaphore({ maxRequests: 6 });
const tiff = await GeoTIFF.fromUrl("https://example.com/scene.tif", {
reader,
concurrencyLimiter,
// Headers, credentials and mode for every request of this file.
requestInit: { headers: { authorization: "Bearer ..." } },
});
// Reads issued together are merged: these four tiles become one or two
// range requests, not four.
const tiles = await tiff.fetchTiles([
[0, 0],
[1, 0],
[0, 1],
[1, 1],
]);
告诉读者,而不是文件: maxGap, (中文(简体) ), maxOverfetchBytes, (中文(简体) ),
maxRequestBytes, (中文(简体) ), minMetadataReadBytes 以及缓存预算
RangeReader 选项(前者) chunkSize 财务报告和审定财务报表 cacheSize 选项
fromUrl 为: minMetadataReadBytes 财务报告和审定财务报表 cache.metadataBytes ) (中文(简体).
reader.stats 计算请求、字节和缓存点击数。 没有
concurrencyLimiter,每个合并请求立即发出; deck.gl
层通过一个共享的每源限制符,打开的页面也应该通过
许多文件本身。 打开时已替换文件, 其下次读取失败
带有 ETag conflict 错误,就像它通过块, 因为解析
布局不再适用;再次打开.
为什么不在Geotiff.js的上方建设呢?
使用甲板.gl-raster的初始实施 giotiff.js (英语)而Geotiff.js对快速启动是很好的。 但有些原因 这个项目转而 @cogeotiff/core。 。 。 .
- 完全输入数字 :
@cogeotiff/core在表达式TypeScript中被完全打入,使得在顶上再建起来更令人愉快. 即使是低层 @cogeotiff/core执行一系列优化, 如读取 使用 页:1 GDAL "鬼头" 从盒子里出来。 相对而言, Giotiff.js 可以解析 但不会自动使用鬼值.- 项目范围: geotiff.js有一个 数量 与甲板需要无关的代码 我们这里需要的就是 能够有效地从COG中 获得个人瓷砖。 giotiff.js 拥有一组我们不需要的功能:再生,瓷砖-并发,转换为RGB,基于目标分辨率的概览选择,或写出GeoTIFFs.
- 复杂性:这是主观的. 总的地理特征,js似乎... ... 但有些地方的地理特征让我暂停 卖出全1000行JPEG解码器? 也许这是因为他们需要支持JPEG在节点的解码(指项目范围的差异),但这并不让我相信,如果有必要的话,我可以在那里解决一个问题.
- 建立信心之上:这是主观的,但是地理上的. js不觉得专注, 喜欢的方式
@cogeotiff/core专注在目标明确、狭窄的API上. - JSDoc 很难阅读和帮助这很主观 但我觉得 多数 更难读取和贡献 giotiff.js 代码 联合来文文件 而不是纯类型脚本.
- 代码质量: geotiff.js的多个部分有代码只是. 评论出来。功能已经 无文档为什么它要正常化? 这个
needsNormalization函数 也没有任何文档,而且很难理解平等是检查什么,因为它没有使用TypeScript-standard enum,这将使代码本身可以读取.
总体来说,Geotiff.js似乎是一个很好的图书馆,开始证明我的概念证明是有益的。 但是如果我在读COG上建一整堆的书 我需要对我所建的 拥有巨大的信心 @cogeotiff/core 给人信心.