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

使用fitz(PyMuPDF)将PDF转SVG时图片尺寸位置调整问题求助

解决PyMuPDF转换PDF到SVG时图片尺寸与位置错误的问题

核心问题分析

你的代码存在三个关键问题导致图片位置和尺寸异常:

  • 硬编码固定的图片尺寸(400x400),未使用图片在PDF中的实际显示尺寸或原始尺寸
  • 错误获取图片位置参数,且未处理PDF与SVG的坐标系差异(PDF原点在页面左下角,SVG原点在左上角)
  • 未获取图片在页面中的精确边界框(bbox),导致位置偏移

修正后的完整代码

import fitz  # PyMuPDF
import base64
import zipfile

def pdf_to_svg_with_text_and_images(pdf_path, output_zip_path):
    document = fitz.open(pdf_path)
    num_pages = len(document)
    with zipfile.ZipFile(output_zip_path, 'w') as zipf:
        for page_index in range(num_pages):
            page = document.load_page(page_index)
            page_width = page.rect.width
            page_height = page.rect.height
        
            svg_header = '''<?xml version="1.0" encoding="UTF-8"?>
            <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
            "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
            <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  
            version="1.1" id="main1" width="{width}" height="{height}">
            <g>
            '''.format(width=int(page_width), height=int(page_height))
        
            svg_content = ""
            # 处理文本部分(保留原逻辑)
            text_instances = page.get_text("dict")["blocks"]
            for instance in text_instances:
                if "lines" in instance:
                    for line in instance["lines"]:
                        for span in line["spans"]:
                            svg_content += f'<text style="fill:#000000;font-family:{span["font"]};font-size:{span["size"]}px;" fill-opacity="1" x="{span["bbox"][0]}" y="{span["bbox"][3]}">{span["text"]}</text>\n'
        
            # 处理图片部分(修正逻辑)
            image_list = page.get_images(full=True)
            if image_list:
                for img_index, img in enumerate(image_list):
                    xref = img[0]  
                    base_image = document.extract_image(xref)
                    # 获取图片在页面中的精确边界框
                    img_bbox = page.get_image_bbox(xref)
                    if not img_bbox:
                        continue  # 跳过无法获取位置的图片
                    
                    # SVG坐标系转换:PDF y轴从下往上,SVG从上往下
                    svg_x = img_bbox.x0
                    svg_y = page_height - img_bbox.y1
                    # 使用图片在页面中的实际显示尺寸
                    svg_width = img_bbox.width
                    svg_height = img_bbox.height
                    
                    img_base64 = base64.b64encode(base_image["image"]).decode("utf-8")
                    # 生成正确的image标签
                    svg_content += f'<image x="{svg_x}" y="{svg_y}" width="{svg_width}" height="{svg_height}" xlink:href="data:image/{base_image["ext"]};base64,{img_base64}"/>\n'
        
            svg_footer = '''
            </g>
            </svg>'''

            svg_filename = f'page{page_index + 1}.svg'
            full_svg_content = svg_header + svg_content + svg_footer
            zipf.writestr(svg_filename, full_svg_content)
            print(f"SVG file {svg_filename} added to zip")

    document.close()


input_pdf_path = 'testing_new.pdf'
output_zip_path = 'output_svgs.zip'
pdf_to_svg_with_text_and_images(input_pdf_path, output_zip_path)

关键修改说明

  1. 获取精确图片边界框:使用page.get_image_bbox(xref)获取图片在PDF页面上的准确位置和显示尺寸,替代原代码中错误的位置参数
  2. 坐标系转换:通过page_height - img_bbox.y1将PDF的左下角原点转换为SVG的左上角原点,确保图片位置正确
  3. 使用实际尺寸:直接使用边界框的width和height作为SVG图片的尺寸,避免硬编码固定值,保证图片显示比例和大小与PDF一致

内容的提问来源于stack exchange,提问作者ahmad tayyab

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:32:09