【代码】不借助numpy读取tif文件

本文将介绍一种 Python 实现,该实现不借助numpy读取tif文件。

平常使用gdal和numpy就可以轻松实现读写tif文件。

假设,在不使用numpy情况下,如何去读取tif的信息呢?

首先,介绍一下什么是gdal和numpy。

gdal是什么

GDAL(Geospatial Data Abstraction Library,地理空间数据抽象库)是一个开源的库,用于读取和写入栅格地理空间数据格式,它提供了一种统一的数据模型来处理这些格式的数据。GDAL支持40多种主流的栅格数据格式,包括GeoTIFF、JPEG、PNG等。

GDAL还提供了一系列的命令行工具来进行地理空间数据转换和处理。例如,gdal_translate可以用来转换栅格数据格式,gdalwarp可以用来重投影和裁剪栅格数据,gdalinfo可以用来查看栅格数据的元数据信息等。

除了栅格数据处理,GDAL的子项目OGR提供了对矢量地理空间数据格式的支持,包括ESRI Shapefiles、GeoJSON、KML等。

行业内的大型软件,如google earth、arcgis的底层都借用了大量的gdal的代码。

总的来说,GDAL是一个非常强大的库,对于地理空间数据的处理和分析工作有着广泛的应用。

numpy是什么

NumPy(Numerical Python的简称)是Python编程语言的一个开源库,用于处理大型多维数组和矩阵,以及一个大集合的高级(数学)函数库。NumPy是SciPy、Pandas等数据处理或科学计算库的基础。

NumPy的主要对象是同构多维数组。它是一个元素表(通常是数字),所有类型都相同,由非负整数元组索引。在NumPy中维度被称为轴。

例如:

import numpy as np

a = np.array([1, 2, 3])   # 创建一个一维数组
print(a)

输出:

array([1, 2, 3])

NumPy的数组类被称作ndarray。通常被称作数组。注意numpy.array和标准Python库类array.array并不相同,后者只处理一维数组和提供少量功能。而numpy.array是用来处理多维数组的。

NumPy提供了大量的数学函数库,如:三角函数、指数函数、对数函数、矩阵运算等,这对于科学计算非常有用。

Python 实现

具体代码如下:

#! /usr/bin/env python3
# -*- coding:utf-8 -*-
from osgeo import gdal, ogr
import struct

def read_tif_without_numpy(src_filename):
    # 使用GDAL库打开GeoTIFF文件
    src_ds = gdal.Open(src_filename)
    # 获取GeoTIFF文件的第一个光栅带
    rb = src_ds.GetRasterBand(1)
    # 获取光栅带的数据类型
    data_type = rb.DataType


    # 获取GeoTIFF文件的列数
    cols = src_ds.RasterXSize
    # 获取GeoTIFF文件的行数
    rows = src_ds.RasterYSize

    if data_type == gdal.GDT_Byte:
        # 如果数据类型是8位无符号整数
        structval = rb.ReadRaster(0, 0, cols, rows, buf_type=gdal.GDT_Byte)
        # 将读取的数据转换为Python的整数类型
        intval = struct.unpack('B' * cols * rows, structval)
        print("The GeoTIFF is 8-bit.")
    elif data_type == gdal.GDT_UInt16 or data_type == gdal.GDT_Int16:
        # 如果数据类型是16位无符号整数或16位有符号整数
        structval = rb.ReadRaster(0, 0, cols, rows, buf_type=gdal.GDT_Int16)
        # 将读取的数据转换为Python的整数类型
        intval = struct.unpack('h' * cols * rows, structval)
        print("The GeoTIFF is 16-bit.")
    else:
        # 如果数据类型既不是8位也不是16位
        print("The GeoTIFF is neither 8-bit nor 16-bit.")

    # 打印第一行第一列的数值
    print(intval[0])

if __name__ == '__main__':
    src_filename = r'test_16.tif'
    read_tif_without_numpy(src_filename)
    

image-20240412095506609

我们可以使用GDAL库中的Dataset或Band的ReadRaster方法来读取栅格数据。这些方法在GDAL和OGR的API教程中有详细的介绍。ReadRaster并不需要NumPy,它返回的是原始的二进制数据,这就需要我们使用Python的标准struct库来解析这些数据。