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

能否通过编程复现zathura的recolor功能并开发PDF处理工具?

编程复现Zathura的Recolor功能并生成转换后PDF

Zathura的recolor功能核心是在渲染阶段对PDF内容进行颜色映射(默认是反转颜色,也支持自定义深浅色替换),要实现输入PDF、输出处理后PDF的程序,可按以下思路操作:

1. 明确Zathura的recolor逻辑

查看Zathura源码可知,其recolor通过修改渲染时的像素颜色实现:

  • 默认模式下,直接反转RGB通道值(黑↔白、浅↔深)
  • 自定义模式则通过配置的recolor-darkcolor和recolor-lightcolor做颜色替换,将原浅色区域映射为深色、深色区域映射为浅色

2. 两种实现方案

方案一:图像渲染转PDF(简单易实现)

利用PDF渲染库将每页转为图像,应用颜色映射后重新合成PDF。优点是逻辑简单,完全复现视觉效果;缺点是输出PDF为图像格式,丢失矢量可编辑性。

示例代码(Python):

import pypdfium2 as pdfium
from PIL import Image
import PyPDF2
import os

def zathura_recolor_pdf(input_path, output_path, custom_dark=(30,30,30), custom_light=(240,240,240)):
    pdf = pdfium.PdfDocument(input_path)
    writer = PyPDF2.PdfWriter()

    for page_idx in range(len(pdf)):
        # 渲染页面为高分辨率图像
        page = pdf.get_page(page_idx)
        bitmap = page.render(scale=2.0, rotation=0)
        img = bitmap.to_pil()

        # 实现Zathura自定义recolor逻辑:替换深浅色
        def color_map(pixel):
            r, g, b, *a = pixel
            # 判断原像素是否为浅色(亮度阈值可调整)
            if (r + g + b) / 3 > 200:
                return custom_dark + tuple(a) if a else custom_dark
            else:
                return custom_light + tuple(a) if a else custom_light

        img = img.convert("RGBA").point(color_map)

        # 临时保存图像
        temp_path = f"_temp_page_{page_idx}.png"
        img.save(temp_path)

        # 添加到输出PDF
        with open(temp_path, "rb") as f:
            img_pdf = PyPDF2.PdfReader(f)
            writer.add_page(img_pdf.pages[0])

    # 保存最终PDF
    with open(output_path, "wb") as f:
        writer.write(f)

    # 清理临时文件
    for page_idx in range(len(pdf)):
        os.remove(f"_temp_page_{page_idx}.png")

# 使用示例:默认反转风格
zathura_recolor_pdf("input.pdf", "output_recolored.pdf")
# 使用自定义深浅色
# zathura_recolor_pdf("input.pdf", "output_custom.pdf", (15,15,20), (230,230,240))

方案二:直接修改PDF矢量内容(复杂但保留矢量)

通过PDF解析库(如PyMuPDF)遍历页面中的文本、图形对象,直接修改其颜色属性。这种方法能保留PDF的矢量可编辑性,但需要处理PDF复杂的颜色空间(DeviceRGB、CMYK等)和内容流结构,适配不同类型的PDF内容难度较高。

示例思路(PyMuPDF):

import fitz

def recolor_vector_pdf(input_path, output_path):
    doc = fitz.open(input_path)
    for page in doc:
        # 遍历页面中的文本块,修改文本颜色
        for block in page.get_text("blocks"):
            if block[6] == 0:  # 标记为文本块
                rect = fitz.Rect(block[:4])
                # 用白色填充背景,黑色文本模拟反转效果
                page.add_redact_annot(rect, text=block[4], fill=(1,1,1), text_color=(0,0,0))
        page.apply_redactions()
        
        # 遍历页面中的图形对象,反转填充/描边颜色
        for shape in page.get_drawings():
            # 反转填充颜色
            if shape["fill"]:
                shape["fill"] = (1 - shape["fill"][0], 1 - shape["fill"][1], 1 - shape["fill"][2])
            # 反转描边颜色
            if shape["stroke"]:
                shape["stroke"] = (1 - shape["stroke"][0], 1 - shape["stroke"][1], 1 - shape["stroke"][2])
            page.draw_shape(shape)
    doc.save(output_path)

注:该示例仅处理简单文本和图形,实际需适配更多PDF元素类型和颜色空间。

3. 注意事项

  • 若需完全对齐Zathura的recolor效果,需严格复刻其源码中render.c内的recolor_pixel颜色转换公式
  • 图像渲染方案建议使用较高缩放比例,避免输出PDF模糊
  • 矢量修改方案需处理PDF中的透明层、渐变、嵌入图像等复杂元素,需多测试不同类型的PDF文件

内容的提问来源于stack exchange,提问作者Solal Baudoin

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 18:09:23