如何在地理空间PDF的UTM坐标位置插入指定文本?
解决地理空间PDF中UTM坐标转页面坐标插入文本的问题
核心思路
要在UTM坐标对应位置插入文本,关键是将UTM坐标转换成PDF页面的点坐标——这需要先从地理空间PDF中提取地理参考信息,再通过坐标映射公式计算出对应的页面位置,最后替换你现有代码中的固定坐标即可。
步骤1:提取PDF的地理空间元数据
地理空间PDF会存储页面的地理范围(比如UTM坐标系下的左下角、右上角坐标)和页面尺寸信息,我们可以通过PyPDF2或pdfplumber提取:
import pdfplumber from PyPDF2 import PdfReader # 获取页面尺寸(单位:点pt) with pdfplumber.open("geo.pdf") as pdf: page = pdf.pages[0] page_width = page.width page_height = page.height # 获取UTM范围信息 reader = PdfReader("geo.pdf") page_dict = reader.pages[0].get_object() utm_min_x, utm_min_y = None, None utm_max_x, utm_max_y = None, None # 读取PDF中的地理参考元数据(常见存储路径) if "/PieceInfo" in page_dict: adobe_info = page_dict["/PieceInfo"].get("/Adobe", {}) dc_info = adobe_info.get("/DC", {}).get("/Subtype", {}).get("/Geo", {}) ll = dc_info.get("/LL", []) # 左下角UTM坐标 ur = dc_info.get("/UR", []) # 右上角UTM坐标 if len(ll) == 2 and len(ur) == 2: utm_min_x, utm_min_y = ll[0], ll[1] utm_max_x, utm_max_y = ur[0], ur[1]
步骤2:UTM坐标转PDF页面坐标
PDF的坐标原点在页面左下角,Y轴向上;而UTM坐标系的Y轴通常向北递增,所以需要反转Y轴映射。转换公式如下:
- 页面X坐标 =
((目标UTM X - utm_min_x) / (utm_max_x - utm_min_x)) * page_width - 页面Y坐标 =
((utm_max_y - 目标UTM Y) / (utm_max_y - utm_min_y)) * page_height
代码实现:
# 替换为你的目标UTM坐标 target_utm_x = 123456.789 target_utm_y = 987654.321 if all([utm_min_x, utm_min_y, utm_max_x, utm_max_y]): page_x = ((target_utm_x - utm_min_x) / (utm_max_x - utm_min_x)) * page_width page_y = ((utm_max_y - target_utm_y) / (utm_max_y - utm_min_y)) * page_height else: raise ValueError("无法从PDF中提取地理参考信息,请确认PDF为标准地理空间PDF")
步骤3:修改原代码插入文本
将计算好的页面坐标替换原代码中的固定值,完整代码如下:
import io from reportlab.pdfgen import canvas from PyPDF2 import PdfReader, PdfWriter import pdfplumber # 1. 提取地理参考和页面尺寸 with pdfplumber.open("geo.pdf") as pdf: page = pdf.pages[0] page_width = page.width page_height = page.height reader = PdfReader("geo.pdf") page_dict = reader.pages[0].get_object() utm_min_x, utm_min_y = None, None utm_max_x, utm_max_y = None, None if "/PieceInfo" in page_dict: adobe_info = page_dict["/PieceInfo"].get("/Adobe", {}) dc_info = adobe_info.get("/DC", {}).get("/Subtype", {}).get("/Geo", {}) ll = dc_info.get("/LL", []) ur = dc_info.get("/UR", []) if len(ll) == 2 and len(ur) == 2: utm_min_x, utm_min_y = ll[0], ll[1] utm_max_x, utm_max_y = ur[0], ur[1] # 替换为你的目标UTM坐标 target_utm_x = 123456.789 target_utm_y = 987654.321 # 2. 转换坐标 if all([utm_min_x, utm_min_y, utm_max_x, utm_max_y]): page_x = ((target_utm_x - utm_min_x) / (utm_max_x - utm_min_x)) * page_width page_y = ((utm_max_y - target_utm_y) / (utm_max_y - utm_min_y)) * page_height else: raise ValueError("无法从PDF中提取地理参考信息,请确认PDF为标准地理空间PDF") # 3. 插入文本并合并PDF input_pdf = PdfReader(open('geo.pdf', 'rb')) buffer = io.BytesIO() c = canvas.Canvas(buffer) c.drawString(page_x, page_y, "Hello, World!") c.save() buffer.seek(0) text_pdf = PdfReader(buffer) output_pdf = PdfWriter() for i in range(len(input_pdf.pages)): page = input_pdf.pages[i] if i == 0: page.merge_page(text_pdf.pages[0]) output_pdf.add_page(page) with open('output.pdf', 'wb') as f: output_pdf.write(f)
注意事项
- 如果上述代码无法提取地理信息,可以尝试用
PyMuPDF(fitz),它对地理PDF的支持更完善:import fitz doc = fitz.open("geo.pdf") page = doc[0] geo = page.get_geo() # 用geo.transform_point(x, y)直接转换坐标,x/y为UTM坐标 - 确保你的UTM坐标的zone和基准面(如WGS84)与PDF的地理参考完全一致,否则转换结果会偏移。
- 若PDF页面有旋转,需先处理页面旋转再计算坐标。
内容的提问来源于stack exchange,提问作者timp bill
相关产品推荐
相关产品推荐

