使用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)
关键修改说明
- 获取精确图片边界框:使用
page.get_image_bbox(xref)获取图片在PDF页面上的准确位置和显示尺寸,替代原代码中错误的位置参数 - 坐标系转换:通过
page_height - img_bbox.y1将PDF的左下角原点转换为SVG的左上角原点,确保图片位置正确 - 使用实际尺寸:直接使用边界框的
width和height作为SVG图片的尺寸,避免硬编码固定值,保证图片显示比例和大小与PDF一致
内容的提问来源于stack exchange,提问作者ahmad tayyab
相关产品推荐
相关产品推荐

