管道基础大数据平台系统开发-【CS】-ExportMap
13693261870
2024-07-19 402fdc4cb6f94016cf9749bb1f09a6c5ead5d6d3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
from osgeo import gdal
from PIL import Image
import numpy as np
import os
import datetime
 
def print_with_timestamp(message):
    # 获取当前时间
    current_time = datetime.datetime.now()
    # 格式化时间戳
    timestamp = current_time.strftime("%Y-%m-%d %H:%M:%S")
    # 打印带有时间戳的消息
    print(f"[{timestamp}] {message}")
 
def reproject_and_resample_tiff(tiff_path, output_tiff_path, target_epsg, factor):
    # 打开TIFF文件
    dataset = gdal.Open(tiff_path, gdal.GA_ReadOnly)
    if dataset is None:
        print_with_timestamp(f"无法打开TIFF文件: {tiff_path}")
        return
 
    # 获取TIFF文件的宽度和高度
    width = dataset.RasterXSize
    height = dataset.RasterYSize
 
    # 计算重采样后的宽度和高度
    new_width = int(width / factor)
    new_height = int(height / factor)
 
    # 设置重投影和重采样参数
    options = gdal.WarpOptions(
        format='GTiff',
        width=new_width,
        height=new_height,
        dstSRS=f'EPSG:{target_epsg}',
        resampleAlg=gdal.GRA_Bilinear
    )
 
    filename = os.path.basename(tiff_path)
    output_path = os.path.join(output_tiff_path,filename)
 
    # 执行重投影和重采样
    gdal.Warp(output_path, dataset, options=options)
    print_with_timestamp(f"已将TIFF文件重投影并重采样到: {output_path}")
    return output_path
 
def tiff_to_png(tiff_path, png_path, waterFlag, imageFlag):
    # 打开重投影和重采样后的TIFF文件
    dataset = gdal.Open(tiff_path, gdal.GA_ReadOnly)
    if dataset is None:
        print_with_timestamp(f"无法打开TIFF文件:{tiff_path}")
        return
 
    # 获取TIFF文件的宽度和高度
    width = dataset.RasterXSize
    height = dataset.RasterYSize
 
    # 获取TIFF文件的高度数据
    band = dataset.GetRasterBand(1)
    heights = band.ReadAsArray()
    # mask_a =  heights > -32766
    # heights = mask_a * heights
 
    # 最高高度,要比测试数据的最高处21高
    maxHeight = 23 
 
    # 创建一个空白的PNG图像
    image = Image.new("RGB", (width, height))
    # image = Image.new("L", (width, height))
 
    # 创建二维数组
    array = np.zeros((width, height), dtype="<i2")
 
    # 将每个像素的RGB值设置为高度的灰度值
    for y in range(height):
        for x in range(width):
            # 获取该位置的高度值
            height_value = heights[y, x]
            alpha = 255
            if height_value <= 0:
                height_value = 0  if waterFlag else maxHeight
            elif np.isnan(height_value):
                height_value = 0  if waterFlag else maxHeight
            else:
                height_value = height_value + 1.0  if waterFlag else height_value
            if imageFlag:
                # 将高度值映射到RGB值(灰度),最高值以30为准
                gray_value = int((height_value / maxHeight) * 255) 
                # 在PNG图像中设置像素的RGB值
                # image.putpixel((x, y), (gray_value, gray_value, gray_value, alpha))
                image.putpixel((x, y), (gray_value, gray_value, gray_value))
                # image.putpixel((x, y), gray_value)
            else:
                # 将数值精确到厘米,保存成二进制的二维数组, 高程及水面的厘米表示要控制在65535之内
                height_value = int(height_value * 100) # 精确到小数后两位,厘米
                array[x][y] = height_value
 
    # 保存PNG图像
    if imageFlag:
        image.save(png_path)
        print_with_timestamp(f"已将TIFF文件转换为PNG: {png_path}")
    else:
        # 将二维数组保存为二进制文件
        # 使用 'w' 模式写入文件,'b' 表示以二进制形式
        with open(png_path, 'wb') as f:
            # tobytes() 方法将数组元素按内存中的顺序转换成一个字节串
            f.write(array.tobytes())
        print_with_timestamp(f"已将TIFF文件转换为BIN: {png_path}")
 
def list_tif_files(directory,tif_files):
 
    # 遍历指定目录中的所有文件和子目录
    for root, dirs, files in os.walk(directory):
        for file in files:
            # 检查文件是否以.tif结尾
            if file.lower().endswith('.tif'):
                # 将完整路径添加到列表中
                path = os.path.join(root,file)
                print_with_timestamp(f"识别到tiff文件:{path}")
                tif_files.append(os.path.join(root, file))
    
    return tif_files 
 
def main(imageFlag):
    # 设置输入TIFF文件路径
    input_tiff_path = ".\\tiff28"
    # 设置重投影和重采样后的TIFF文件路径
    output_tiff_path = ".\\resample"
    # 设置目标EPSG代码
    target_epsg = 4326  # WGS84
    # 设置重采样因子
    factor = 10
 
    # 设置输出含水面高度图PNG文件路径
    output_water_png_path = ".\\waterImage"
    # 设置输出不含水面的地形、建筑高度图PNG文件路径
    output_terrain_png_path = ".\\terrainImage"
 
    # 创建一个空列表来存储所有的.tif文件
    tif_files = []
 
    # 遍历文件夹中的tiff
    list_tif_files(input_tiff_path, tif_files)
 
    for file in tif_files:
        print_with_timestamp(f"{file} 开始重投影")
 
        # 执行重投影和重采样
        out_path = reproject_and_resample_tiff(file, output_tiff_path, target_epsg, factor)
 
        print_with_timestamp(f"{out_path} 开始转换为png")
        # 使用os.path.basename方法获取路径中的文件名
        file_name = os.path.basename(out_path)
        # 使用os.path.splitext方法分离文件名和扩展名
        file_name_without_ext, _ = os.path.splitext(file_name)
        # 水面高度图路径
        out_water_png_file = os.path.join(output_water_png_path, file_name_without_ext)
        out_water_png_file = f"{out_water_png_file}.png" if imageFlag else f"{out_water_png_file}.bin"
        # 地形&建筑高度图路径
        out_terrain_png_file = os.path.join(output_terrain_png_path, file_name_without_ext)
        out_terrain_png_file = f"{out_terrain_png_file}.png" if imageFlag else f"{out_terrain_png_file}.bin"
        # 将重投影和重采样后的带水面的TIFF文件转换为高度图PNG
        tiff_to_png(out_path, out_water_png_file, True, imageFlag)
        # 将重投影和重采样后的不带水面的TIFF文件转换为高度图PNG
        # tiff_to_png(out_path, out_terrain_png_file, False, imageFlag)
    
if __name__ == "__main__":
    main(True)