You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 22:09:52