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

在MuPDF(C语言)中如何将路径绘制到PDF的指定现有页面?

在MuPDF(C语言)中如何将路径绘制到PDF的指定现有页面?

看起来你已经走对了创建路径的流程,但在MuPDF中修改现有PDF页面和新建页面的设备关联逻辑完全不同。核心问题是你需要用专门的PDF写入设备,并且必须先重放原页面内容(否则原有内容会被覆盖)。下面是完整的修正实现和关键步骤解析:

核心思路

MuPDF修改现有页面的正确流程是:

  1. 加载目标页面并获取其媒体框(MediaBox)
  2. 创建关联该页面的PDF写入设备(而非通用设备)
  3. 先将原页面的所有内容重放到设备上(保留原有内容)
  4. 在设备上绘制新的路径
  5. 完成页面写入并释放所有资源

修正后的完整代码

#include "mupdf/fitz.h"
#include "mupdf/pdf.h"

void DrawPathOnPage(fz_context* ctx, pdf_document* dst_doc, int dst_page_num) {
    // Draws a path in page #dst_page_num of the opened dst_doc.
    fz_path* path = NULL;
    pdf_page* page = NULL;
    fz_device* dev = NULL;

    // === 1. 创建要绘制的路径 ===
    path = fz_new_path(ctx);
    float x0 = 0;
    float y0 = 0;
    float x1 = 100;
    float y1 = 100;
    fz_rectto(ctx, path, x0, y0, x1, y1);
    fz_closepath(ctx, path); // 闭合路径(只需要调用一次)

    // === 2. 加载目标页面并获取媒体框 ===
    page = pdf_load_page(ctx, dst_doc, dst_page_num);
    fz_rect mediabox = pdf_page_bound_box(ctx, page, PDF_BOUND_MEDIA);

    // === 3. 关联设备与现有页面(解决你的(Q)问题) ===
    // 使用pdf_begin_page_write创建专用于修改页面的设备
    // 参数说明:上下文、目标文档、要修改的页面、页面媒体框、是否保留原页面资源(1=保留)
    dev = pdf_begin_page_write(ctx, dst_doc, page, mediabox, 1);

    // === 4. 重放原页面内容(必须!否则原有内容会丢失) ===
    fz_matrix ctm = fz_identity; // 用单位矩阵保持原页面的缩放比例
    pdf_run_page(ctx, page, dev, ctm, NULL);

    // === 5. 在设备上绘制新路径 ===
    float alpha = 0.9f;
    int even_odd = 0; // 填充规则:0=非零环绕,1=奇偶规则
    float color[3] = {0.75f, 0.75f, 0.75f}; // RGB灰色

    fz_fill_path(
        ctx,
        dev,
        path,
        even_odd,
        ctm, // 可根据需求调整变换矩阵(缩放、旋转等)
        fz_device_rgb(ctx), // 颜色空间设备
        color,
        alpha,
        fz_default_color_params
    );

    // === 6. 完成页面写入并释放所有资源 ===
    pdf_end_page_write(ctx, dst_doc, page, dev); // 提交页面修改
    fz_drop_device(ctx, dev);
    fz_drop_page(ctx, page);
    fz_drop_path(ctx, path);
}

关键细节说明

  1. 为什么要重放原页面?
    MuPDF的页面写入设备是基于"重建页面内容"的逻辑,它不会自动保留原有页面的内容。必须通过pdf_run_page将原页面的所有内容渲染到设备上,再叠加新内容,才能保证最终页面同时包含原有内容和你的新路径。

  2. pdf_begin_page_write的作用
    这个函数是MuPDF专门为修改现有页面设计的API,它会:

    • 创建一个关联目标页面的写入设备
    • 保留原页面的资源(字体、图片等),避免重复存储
    • 确保新内容的坐标系统与原页面一致
  3. 资源释放注意事项
    MuPDF采用手动内存管理,所有通过fz_new_*、pdf_load_*创建的对象,必须用对应的fz_drop_*、pdf_drop_*函数释放,否则会导致内存泄漏。

  4. 扩展说明

    • 如果你需要绘制描边路径而非填充,可以用fz_stroke_path替代fz_fill_path,并设置线宽、线帽等属性
    • 颜色空间可以切换为CMYK(fz_device_cmyk(ctx))或灰度(fz_device_gray(ctx)),对应的color数组长度需要调整(CMYK为4个元素,灰度为1个)
    • 修改完成后,记得调用pdf_save_document(ctx, dst_doc, NULL)将更改保存到磁盘(如果目标文档是从磁盘加载的)

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.08 10:48:08