使用Fitz替换PDF文本后字体显示异常的问题及解决方法
解决Fitz替换PDF文本后数字显示方框/字符重叠问题
问题现象
使用Fitz替换PDF中的文本时,出现以下异常:
- 替换后的数字(如9)显示为方框
- 尝试将字体引用从"F1"改为"F2"后,所有数字均变为方框且字符重叠
解决方法
只需添加字体文件的完整路径即可。
问题根源在于代码中直接通过字体名创建fitz.Font对象时,Fitz无法正确定位到对应的字体文件,导致使用了缺少数字字形的替代字体,最终出现方框或重叠问题。指定字体文件的完整路径后,就能加载包含所有所需字符的字体,解决显示异常。
修正后的代码
import fitz def adjust_matrix(font, bbox, text, fontsize): """Compute matrix performing a horizontal scale. Args: font: Font object bbox: bbox of the text to fill text: text fontsize: fontsize to use Returns: Horizontal scaling matrix """ tl = font.text_length(text, fontsize=fontsize) width = bbox[2] - bbox[0] scale = width / tl return fitz.Matrix(scale, 1) def get_fontlist(page): """Make a dictionary for existing fonts.""" flist = {} for f in page.get_fonts(): # extract xref, full font name and reference name xref, fullname, refname = f[0], f[3], f[4] # subset fonts have a "+" in string position 7 fullname = fullname[6:] if "+" in fullname else fullname ff = doc.extract_font(xref) # extract font buffer font = fitz.Font(fontbuffer=ff[-1]) # store reference name and the Font object flist[font.name] = (refname, font) return flist doc = fitz.open("relatorio_premissas.pdf") page = doc[0] page.clean_contents() # page needs cleaning for correct positions of inserts # make a dictionary of fonts used on this page fontlist = get_fontlist(page) print("Font list:", fontlist) # Debug: Print the font list # 替换所有"[demanda_pta]"为"12.8798 kW" bboxes = page.search_for("[demanda_pta]") spans = [] # 存储匹配到的文本块 for bbox in bboxes: # 提取每个匹配项的文本元信息 for b in page.get_text("dict", clip=bbox)["blocks"]: for l in b["lines"]: spans.extend(l["spans"]) # Debug: 打印文本块信息 print("Spans:", spans) # 标记需要删除的文本区域 for s in spans: page.add_redact_annot(s["bbox"]) if s["font"] == "1": s["font"] = "1 Regular" # 关键修改:替换为你的字体文件实际路径 fontlist['1 Regular'] = ("F1", fitz.Font(fontfile="/path/to/figo.ttf")) print(s) page.apply_redactions(images=0, graphics=0, text=0) # 在清空的区域插入新文本 for s in spans: point = fitz.Point(s["origin"]) # 插入位置 text = s["text"] # 原始文本([demanda_pta]) fsize = s["size"] # 字体大小 font = s["font"] # PDF中的字体名称 # Debug: 打印当前使用的字体 print("Processing span with font:", font) # 转换颜色为PDF格式 color = fitz.sRGB_to_pdf(s["color"]) # 替换文本 text = text.replace("[demanda_pta]", "12.8798 kW") # 匹配正确的字体 try: fontname, font_obj = fontlist[font] except KeyError: try: fontname, font_obj = fontlist[font.replace("-", " ")] except KeyError: print(f"Font '{font}' not found in font list. Skipping span.") continue # 计算横向缩放矩阵,让文本适配原区域宽度 matrix = adjust_matrix(font_obj, s["bbox"], text, fsize) print(f"Inserting text: '{text}' at point: {point} with font: {fontname} and size: {fsize}") page.insert_text( point, text, fontname=fontname, fontsize=fsize, color=color, morph=(point, matrix), # 应用横向缩放 ) doc.subset_fonts() doc.ez_save("trains-new2.pdf")
关键说明
- 将代码中的
/path/to/figo.ttf替换为你本地字体文件的实际路径(比如C:/fonts/figo.ttf或/home/user/fonts/figo.ttf) - 确保字体文件支持你需要显示的所有字符(包括数字、特殊符号等)
内容的提问来源于stack exchange,提问作者user24954473
相关产品推荐
相关产品推荐

