Skip to main content

pdf-sign-kit

PyPI version Python License: MIT

English | 中文文档


English

A framework-agnostic Python toolkit for stamping signatures and text onto PDF files. It is extracted from the core of a production paperless-approval system and works with plain files — no Django, no database, no network required.

Features

  • Image stamps — place any PNG (signature, seal) at a click point.
  • Automatic table-cell detection — finds the enclosing cell from a single grayscale raster and scales the stamp proportionally; rotated pages are handled transparently.
  • Handwriting mode — loose-fit scaling for handwritten signatures.
  • Raster text (600 DPI) — mixed Chinese/Latin text, e.g. 编号 BZ-001, rendered with auto-detected CJK and Latin fonts; supports automatic wrapping.
  • Built-in stamps — "同意" (agree) and a check mark.
  • Background removal — turn near-white backgrounds into transparent PNGs.
  • Page preview — render any page to a PIL image / PNG bytes.
  • Integrity hashing — SHA-256 / SHA-512 / MD5 digest and verification.
  • Workflow rule engine — pure functions deciding who may sign now and whether every participant has finished; supports personal, personal countersign and department countersign levels.
  • Configurable signing schemes — define any number of levels, name each one, mark a level as personal / countersign / department countersign; schemes round-trip through JSON, with a built-in 8-level default.
  • Signature log tables — render the sign/rejection log as a PNG or a data: URL, with Chinese keyword extraction from rejection reasons.
  • Text-anchor placement — locate a stamp position by searching visible text ("签字:") instead of table borders; supports "after / below / over" the matched text, for borderless contracts and blank templates.
  • Seam stamps (骑缝章) — slice one seal into N strips placed on the edges of N consecutive pages; the strips reassemble when pages are fanned.
  • Diagonal watermarks — rotated "作废" / "草稿" / "保密" captions, single centered mark or tiled grid, with RGBA opacity control.
  • Placement templates — save reusable signature positions as JSON and instantiate them with a ref -> image mapping for batch signing of files sharing one layout.
  • Bitmap composition — horizontal/vertical concatenation of images with alignment, gaps and proportional scaling.

Installation

pip install pdf-sign-kit

Quickstart

import pdf_sign_kit as psk

# Stamp a signature image at (x, y), editing the file in place.
psk.stamp("form.pdf", "signature.png", x=200, y=627)

# Built-in stamps
psk.stamp_agree("form.pdf", x=200, y=627)
psk.stamp_checkmark("form.pdf", x=200, y=627)

# Mixed Chinese/Latin machine text
psk.stamp_text("form.pdf", "编号 BZ-001", x=200, y=627)

# Make a handwriting scan transparent
img = psk.remove_background("scan.png", threshold=235)
img.save("stamp.png")

# Render a preview / compute integrity hash
preview = psk.render_page("form.pdf", page=0, zoom=3)
digest = psk.hash_file("form.pdf")

Define a signing scheme

from pdf_sign_kit import FlowScheme, Initiator, build_metadata
from pdf_sign_kit import GROUP, DEPARTMENT

# Any number of levels, custom names; level 2 is personal countersign and
# level 3 is department countersign (each department needs one signer).
scheme = FlowScheme.create(
    3,
    names={1: "起草", 2: "会签", 3: "部门会签"},
    modes={2: GROUP, 3: DEPARTMENT},
)

metadata = build_metadata(
    scheme,
    {
        1: [{"id": "A", "name": "甲"}],
        2: [{"id": "B"}, {"id": "C"}],          # any one signs -> done
        3: [
            {"id": "D", "group": "D1", "group_name": "技术部"},
            {"id": "E", "group": "D2", "group_name": "质保部"},
        ],
    },
    initiator=Initiator(id="I", name="initiator"),
)

# Ask the rule engine who may sign / whether the document is complete.
psk.workflow.can_sign(metadata, "A")
psk.workflow.all_completed(metadata)

# Schemes serialize to plain JSON for storage and reloading.
restored = FlowScheme.from_dict(scheme.to_dict())

Text anchor, seam stamp, watermark

# Find visible text and stamp next to it (no table borders needed)
anchor = psk.find_text("contract.pdf", "签字:")
psk.stamp_at_anchor("contract.pdf", "signature.png", anchor)

# Seam stamp across all pages (right edges)
psk.stamp_seam("contract.pdf", "seal.png")

# Diagonal watermark on every page; RGBA color controls opacity
psk.stamp_watermark(
    "contract.pdf", "作废",
    pages=[0, 1],
    color=(220, 38, 38, 90),
    tile=True,
)

# Compose a name + date strip before stamping
combined = psk.hconcat([name_img, date_img], gap=8)

Save and reuse placement templates

from pdf_sign_kit import PlacementTemplate

# Capture positions from stamp_batch operations and store as JSON
template = PlacementTemplate.capture(operations, name="Form-A")
psk.save_template("form_a.json", template)

# Later: reuse the same positions on a new file of the same layout
template = psk.load_template("form_a.json")
operations = template.instantiate({"signature": "sig.png", "date": "date.png"})
psk.stamp_batch("another_file.pdf", operations)

Coordinate system

  • x / y are PDF points (1 pt = 1/72 inch) measured from the page's bottom-left corner in its display orientation.
  • page indices are zero-based.
  • Page rotation is handled internally.

Notes & limitations

  • These are visual ("electronic") signatures — raster images placed on the page — not PKI/certificate-based ("digital") signatures with legal non-repudiation guarantees.
  • Raster text is flattened (not selectable), which matches the print-first quality requirement.
  • No fonts are bundled: CJK/Latin fonts are auto-detected on the system; you may always pass an explicit font_path. On Debian/Ubuntu: apt-get install fonts-noto-cjk.

License

MIT © 兰衣


中文文档

一个与 Web 框架无关的 Python 工具包,用于在 PDF 文件上加盖签名图章与机打 文字。代码提炼自一套生产环境无纸化审批系统的核心内核,只操作本地文件 ——不依赖 Django、数据库或网络。

功能特性

  • 图片盖章:在指定坐标放置任意 PNG(签名、印章)。
  • 表格单元格自动检测:通过一次灰度渲染识别点击位置所在的表格格子, 并按格子比例自动缩放;自动处理页面旋转。
  • 手写模式:为手写签名提供宽松缩放策略。
  • 机打文字(600 DPI):支持中英混排(如 编号 BZ-001),自动匹配中/英 字体,支持自动换行。
  • 内置图章:"同意" 章与打勾(check mark)。
  • 去背景:将近白背景转为透明 PNG。
  • 页面预览:把任意页面渲染为 PIL 图像 / PNG 字节。
  • 完整性哈希:支持 SHA-256 / SHA-512 / MD5 计算与校验。
  • 签署流程规则引擎:以纯函数判断当前谁可以签、是否全部签署完成,支持 个人签署、个人会签与部门会签。
  • 签署等级方案可配置:可自定义任意数量的等级、为每个等级命名,标记某级 为个人签署/会签/部门会签;方案支持 JSON 序列化,并内置一套 8 级默认方案。
  • 签字日志表格:将签字/驳回日志渲染为 PNG 或 data: URL,并支持从驳回 原因中提取中文关键词。
  • 文本锚点定位:通过搜索可见文字(如「签字:」)确定盖章位置,而非依赖 表格线;支持在匹配文字「其后/其下/覆盖」定位,适用于无表格线的合同与空白 模板。
  • 骑缝章:将一枚印章切成 N 条,分别盖在连续 N 页的边缘,展开拼合后还原 完整印章。
  • 斜向水印:「作废」「草稿」「保密」等旋转文字,支持单个居中章或整页平铺, RGBA 颜色直接控制透明度。
  • 签署位置模板:把可复用的签署位置保存为 JSON,通过「引用名 → 图片」映射 实例化,用于同版式文件的批量签署。
  • 位图拼接:多图水平/垂直拼接,支持对齐、间距与等比缩放。

安装

pip install pdf-sign-kit

快速上手

import pdf_sign_kit as psk

# 在 (x, y) 处加盖签名图片,原地修改文件
psk.stamp("表单.pdf", "签名.png", x=200, y=627)

# 内置图章
psk.stamp_agree("表单.pdf", x=200, y=627)
psk.stamp_checkmark("表单.pdf", x=200, y=627)

# 中英混排机打文字
psk.stamp_text("表单.pdf", "编号 BZ-001", x=200, y=627)

# 将手写扫描件去背景
img = psk.remove_background("扫描件.png", threshold=235)
img.save("图章.png")

# 渲染预览图 / 计算完整性哈希
preview = psk.render_page("表单.pdf", page=0, zoom=3)
digest = psk.hash_file("表单.pdf")

定义签署等级方案

from pdf_sign_kit import FlowScheme, Initiator, build_metadata
from pdf_sign_kit import GROUP, DEPARTMENT

# 任意等级数量、自定义名称;第2级为个人会签,第3级为部门会签(每个部门
# 任一人签署即完成该部门)。
scheme = FlowScheme.create(
    3,
    names={1: "起草", 2: "会签", 3: "部门会签"},
    modes={2: GROUP, 3: DEPARTMENT},
)

metadata = build_metadata(
    scheme,
    {
        1: [{"id": "A", "name": "甲"}],
        2: [{"id": "B"}, {"id": "C"}],          # 任一人签即完成
        3: [
            {"id": "D", "group": "D1", "group_name": "技术部"},
            {"id": "E", "group": "D2", "group_name": "质保部"},
        ],
    },
    initiator=Initiator(id="I", name="发起人"),
)

# 由规则引擎判断谁可签 / 文件是否全部完成
psk.workflow.can_sign(metadata, "A")
psk.workflow.all_completed(metadata)

# 方案可序列化为普通 JSON 存储后再恢复
restored = FlowScheme.from_dict(scheme.to_dict())

文本锚点、骑缝章、水印

# 搜索可见文字并在其后盖章(无需表格线)
anchor = psk.find_text("合同.pdf", "签字:")
psk.stamp_at_anchor("合同.pdf", "签名.png", anchor)

# 对所有页加盖骑缝章(右边缘)
psk.stamp_seam("合同.pdf", "印章.png")

# 在指定页加盖斜向水印;RGBA 颜色控制透明度
psk.stamp_watermark(
    "合同.pdf", "作废",
    pages=[0, 1],
    color=(220, 38, 38, 90),
    tile=True,
)

# 盖章前先拼接姓名 + 日期
combined = psk.hconcat([name_img, date_img], gap=8)

保存与复用签署位置模板

from pdf_sign_kit import PlacementTemplate

# 从 stamp_batch 操作中提取位置并存为 JSON
template = PlacementTemplate.capture(operations, name="表单A")
psk.save_template("表单_a.json", template)

# 之后在同版式的新文件上复用相同位置
template = psk.load_template("表单_a.json")
operations = template.instantiate({"signature": "签名.png", "date": "日期.png"})
psk.stamp_batch("另一个文件.pdf", operations)

坐标系说明

  • x / y 单位为 PDF 点(1 pt = 1/72 英寸),以页面显示方向的 左下角为原点。
  • page 页码从 0 开始。
  • 页面旋转由库内部处理。

注意与限制

  • 本包提供的是可视化("电子")签名——即放置到页面上的图片,而非基于 PKI/证书、具备法律防抵赖能力的"数字签名"。
  • 机打文字以栅格方式写入(不可选中复制),以满足高打印质量要求。
  • 包不携带字体:会自动探测系统中的中/英字体,也可显式传入 font_path; Debian/Ubuntu 可执行 apt-get install fonts-noto-cjk。

许可证

MIT © 兰衣

Metadata

Release files for pdf-sign-kit 0.5.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pdf-sign-kit 0.5.0
File Size Uploaded
pdf_sign_kit-0.5.0.tar.gz 49.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pdf-sign-kit 0.5.0
File Interpreter ABI Platform
pdf_sign_kit-0.5.0-py3-none-any.whl Python 3 none any Details

Total release size: 96.5 kB

Release files / pdf_sign_kit-0.5.0.tar.gz

Download URL pdf_sign_kit-0.5.0.tar.gz
Size 49.1 kB
Tags Source
SHA-256 checksum
How to use checksums
97c04dfbe54e75e17dea4d182a9944bc7668bad9fb30e88db6423361773df8fa
BLAKE2b-256 checksum
How to use checksums
6c88234a334d5f38626eadc2605e68397483a5a9d03f4956755c41d206bc772b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release files / pdf_sign_kit-0.5.0-py3-none-any.whl

Download URL pdf_sign_kit-0.5.0-py3-none-any.whl
Size 47.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
26131a4c4bf43836adc9c42e996917f21b130d69597748ddeda2065f25d8466e
BLAKE2b-256 checksum
How to use checksums
4a9ad29cda0b00030369750ca5849dbcbf5508d87d302f9dbc9b4cb4bcce398b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.10

Release history Release notifications | RSS feed

0.5.2

2 release files

0.5.1

2 release files

This release

0.5.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page