如何使用 gdal 对 Float32 光栅文件进行显着压缩
How to make a significant compression of a Float32 raster file with gdal
这个问题很模糊,但这就是我的意思。我有一个 110GB 的光栅文件,它是 20 个其他文件的组合,生成了整个欧洲的 .tif 文件。我想使用它的二进制类型来制作 3D 地形,例如 this blog,但问题是它的大小。我用 gdal 尝试了一些技巧,例如:
gdal_translate
-co COMPRESS=JPEG
-co TILED=YES
input.tif output.tif
但显然 JPEG 压缩不适用于 Float32 文件。我更喜欢保存 Float32 格式的负值,但 16 位整数也可以(不包括所有字节压缩)。到目前为止,我发现的 Float32 文件的最佳压缩是使用 PREDICTOR=3 作为压缩表达式,但这还远远不够。
是否有可能像我用 gdal 描述的那样实现这种压缩?其他技术呢?
如您所见,JPEG 压缩不适用于浮点数(事实上,它仅适用于整数 RGB,因为它有损地移除了视觉上不易察觉的部分)。
PREDICTOR=3
与 COMPRESS=ZSTD
和高 ZSTD_LEVEL
可能是你能做到的最好的真正无损。
但是,如果您可以容忍特定的不精确度,并且您的 GDAL 版本至少为 2.4,则可以使用 COMPRESS=LERC
或 LERC_ZSTD
并将 MAX_Z_ERROR
设置为最大不精确度您可以容忍的(通过压缩产生的错误)。
LERC 的实现在 GDAL 中略有错误,可能会因 NaN、NODATA 或 inf
s 而窒息。 https://github.com/OSGeo/gdal/issues/3055 声称此问题已于 2020 年 10 月修复,但至今仍影响着我。作为解决方法,您可以通过按比例放大固定乘数(表示 1)来转换为 Int16,以便 +-1 在您的目标精度范围内,然后使用 COMPRESS=ZSTD
和 PREDICTOR=2
。如果您愿意,甚至可以在具有整数最大 Z 误差的整数栅格上再次使用 LERC。
我刚刚做的例子:
gdal_calc -A "D2014 NDVI.tif" --outfile=out.tif --type=Int16 --calc=numpy.round(1000.0*A)
gdal_translate -co "COMPRESS=LERC_ZSTD" -co "ZSTD_LEVEL=15" -co "MAX_Z_ERROR=5" -co "PREDICTOR=2" -co "TILED=YES" out.tif "D2014 NDVI lerc.tif"
毫无疑问,您可以合并成一行。对我来说,这将 600 Mb Float32 TIF 减少为 120 Mb Int16,整数缩放 NDVIs -1000-1000,最大误差 5(即缩放前为 0.005)。这与我将 LERC_ZSTD 应用到 Float32 而没有阻塞所取得的成就一致。
这个问题很模糊,但这就是我的意思。我有一个 110GB 的光栅文件,它是 20 个其他文件的组合,生成了整个欧洲的 .tif 文件。我想使用它的二进制类型来制作 3D 地形,例如 this blog,但问题是它的大小。我用 gdal 尝试了一些技巧,例如:
gdal_translate
-co COMPRESS=JPEG
-co TILED=YES
input.tif output.tif
但显然 JPEG 压缩不适用于 Float32 文件。我更喜欢保存 Float32 格式的负值,但 16 位整数也可以(不包括所有字节压缩)。到目前为止,我发现的 Float32 文件的最佳压缩是使用 PREDICTOR=3 作为压缩表达式,但这还远远不够。
是否有可能像我用 gdal 描述的那样实现这种压缩?其他技术呢?
如您所见,JPEG 压缩不适用于浮点数(事实上,它仅适用于整数 RGB,因为它有损地移除了视觉上不易察觉的部分)。
PREDICTOR=3
与 COMPRESS=ZSTD
和高 ZSTD_LEVEL
可能是你能做到的最好的真正无损。
但是,如果您可以容忍特定的不精确度,并且您的 GDAL 版本至少为 2.4,则可以使用 COMPRESS=LERC
或 LERC_ZSTD
并将 MAX_Z_ERROR
设置为最大不精确度您可以容忍的(通过压缩产生的错误)。
LERC 的实现在 GDAL 中略有错误,可能会因 NaN、NODATA 或 inf
s 而窒息。 https://github.com/OSGeo/gdal/issues/3055 声称此问题已于 2020 年 10 月修复,但至今仍影响着我。作为解决方法,您可以通过按比例放大固定乘数(表示 1)来转换为 Int16,以便 +-1 在您的目标精度范围内,然后使用 COMPRESS=ZSTD
和 PREDICTOR=2
。如果您愿意,甚至可以在具有整数最大 Z 误差的整数栅格上再次使用 LERC。
我刚刚做的例子:
gdal_calc -A "D2014 NDVI.tif" --outfile=out.tif --type=Int16 --calc=numpy.round(1000.0*A)
gdal_translate -co "COMPRESS=LERC_ZSTD" -co "ZSTD_LEVEL=15" -co "MAX_Z_ERROR=5" -co "PREDICTOR=2" -co "TILED=YES" out.tif "D2014 NDVI lerc.tif"
毫无疑问,您可以合并成一行。对我来说,这将 600 Mb Float32 TIF 减少为 120 Mb Int16,整数缩放 NDVIs -1000-1000,最大误差 5(即缩放前为 0.005)。这与我将 LERC_ZSTD 应用到 Float32 而没有阻塞所取得的成就一致。