在C#中读取存储float32高程值的非分块GeoTIFF像素数据
在C#(Unity)中读取非分块Float32 GeoTIFF高程值
目标GeoTIFF属性
- 灰度格式
- 存储float32类型数值
- 非分块结构
Python参考实现
tiffArray = numpy.array(tiffImage) elevation = tiffArray[0,0] # 返回值:39.66m
问题背景
尝试过libTiff库,但多数方案针对分块GeoTIFF,且因底层字节/二进制解码知识不足遇到无法排查的错误;GDAL难以集成到Unity,不考虑作为替代方案。
解决方案:使用LibTiff.Net实现
LibTiff.Net是纯.NET的TIFF处理库,适配Unity环境,针对非分块(条带存储)的Float32 GeoTIFF可以直接读取数据。
1. 集成到Unity
通过NuGet下载LibTiff.Net,或直接获取适配.NET Standard 2.0的编译DLL,将其放入Unity项目的Assets/Plugins目录中。
2. 读取高程值的代码实现
using System; using LibTiff.Net; using UnityEngine; public class GeoTiffElevationReader : MonoBehaviour { [SerializeField] private string tiffFilePath; // 赋值为GeoTIFF文件路径 private void Start() { ReadTargetElevation(); } private void ReadTargetElevation() { using (Tiff tiff = Tiff.Open(tiffFilePath, "r")) { if (tiff == null) { Debug.LogError("无法打开目标GeoTIFF文件"); return; } // 获取图像元数据 int width = tiff.GetField(TiffTag.IMAGEWIDTH)[0].ToInt(); int bitsPerSample = tiff.GetField(TiffTag.BITSPERSAMPLE)[0].ToInt(); int samplesPerPixel = tiff.GetField(TiffTag.SAMPLESPERPIXEL)[0].ToInt(); int sampleFormat = tiff.GetField(TiffTag.SAMPLEFORMAT)[0].ToInt(); int rowsPerStrip = tiff.GetField(TiffTag.ROWSPERSTRIP)[0].ToInt(); // 验证格式是否符合要求 if (bitsPerSample != 32 || samplesPerPixel != 1 || sampleFormat != 3) { Debug.LogError("仅支持单通道Float32类型的GeoTIFF"); return; } // 读取第一条带(非分块场景下,整幅图可能仅一个条带) int stripByteSize = width * 4 * rowsPerStrip; byte[] stripBytes = new byte[stripByteSize]; tiff.ReadEncodedStrip(0, stripBytes, 0, stripByteSize); // 字节数组转Float32数组 float[] elevationData = new float[width * rowsPerStrip]; Buffer.BlockCopy(stripBytes, 0, elevationData, 0, stripByteSize); // 获取(0,0)位置的高程值 float elevation = elevationData[0]; Debug.Log($"坐标(0,0)的高程值:{elevation:F2}m"); // 读取任意(row, col)位置的高程值 // int targetRow = 1; // int targetCol = 1; // int pixelIndex = targetRow * width + targetCol; // float targetElevation = elevationData[pixelIndex]; } } }
关键说明
- 格式验证:通过
SAMPLEFORMAT=3确认是浮点型,BITSPERSAMPLE=32对应float32,SAMPLESPERPIXEL=1确认是单通道灰度图 - 非分块TIFF用条带(Strip)存储,通过
ReadEncodedStrip直接读取字节数据 - 利用
Buffer.BlockCopy直接完成字节到float的转换,无需额外解码(匹配原生存储格式) - 像素索引计算规则:
行号 * 图像宽度 + 列号
内容的提问来源于stack exchange,提问作者PengWin
相关产品推荐
相关产品推荐

