# naaru-hammer **Repository Path**: leonscript/naaru-hammer ## Basic Information - **Project Name**: naaru-hammer - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-08-22 - **Last Updated**: 2025-09-03 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 纳鲁之锤 (Naaru Hammer) > 🔨 强大而优雅的PDF盖章工具库 - 专业实现骑缝章防篡改技术 纳鲁之锤是一个专门为Go语言开发的PDF文档盖章解决方案,以魔兽世界中传说武器命名,寓意着强大、可靠的工具力量。本项目专注于实现企业级的PDF盖章功能,特别是独创的骑缝章防篡改技术。 ## ✨ 核心特性 - 🎯 **普通盖章** - 支持9种位置锚点,灵活的样式配置 - 🔒 **骑缝章技术** - 真正的图像切分实现,提供文档防篡改保护 - 🏷️ **多印章支持** - 单次操作支持多个印章,支持不同页面、位置、样式配置 - 📄 **页面范围** - 支持所有页面、仅奇数页、仅偶数页的灵活选择 - 🎨 **丰富配置** - 透明度、缩放、旋转等多种视觉效果 - 🔗 **链式调用** - 流畅的API设计,支持方法链式调用 - 🛡️ **企业级** - 完善的错误处理、参数验证和单元测试 - 🚀 **高性能** - 基于pdfcpu库,处理速度快,内存占用低 - ⚠️ **注意** - 纳鲁之锤盖章不支持直接写宽高,只能靠 scale 控制。工具会根据用户给定的印章宽度自动计算scale(相对页宽/高) ## 🚀 快速开始 ### 安装 ```bash go get gitee.com/leonscript/naaru-hammer ``` ### 基础用法 ```go package main import ( "fmt" "gitee.com/leonscript/naaru-hammer/hotn" ) func main() { // 创建配置 config := hotn.NewStampConfig() config.SetInputFile("input.pdf") config.SetOutputFile("output.pdf") // 创建印章 stamp := hotn.NewStamp("stamp.png") stamp.SetPosition("tr") // 右上角 stamp.SetOpacity(0.5) // 50%透明度 stamp.SetWidth(113) // 设置宽度,高度自动计算 config.AddStamp(*stamp) // 执行盖章 err := hotn.AddStamp(config) if err != nil { fmt.Printf("盖章失败: %v\n", err) return } fmt.Println("盖章完成!") } ``` ### 多印章示例 ```go // 多印章示例 config := hotn.NewStampConfig() config.SetInputFile("document.pdf") config.SetOutputFile("multi_stamped.pdf") // 第一个印章:右上角,50%透明度 stamp1 := hotn.NewStamp("stamp1.png") stamp1.SetPosition("tr") stamp1.SetOpacity(0.5) stamp1.SetWidth(113) config.AddStamp(*stamp1) // 第二个印章:左下角,旋转45度 stamp2 := hotn.NewStamp("stamp2.png") stamp2.SetPosition("bl") stamp2.SetRotation(45) stamp2.SetWidth(100) config.AddStamp(*stamp2) // 第三个印章:中心位置,80%透明度 stamp3 := hotn.NewStamp("stamp3.png") stamp3.SetPosition("c") stamp3.SetOpacity(0.8) stamp3.SetWidth(120) config.AddStamp(*stamp3) err := hotn.AddStamp(config) ``` ## 📖 功能对比 | 功能 | 普通盖章 | 骑缝章 | 多印章 | |------|----------|--------|--------| | 适用场景 | 单页认证 | 防篡改保护 | 复杂业务场景 | | 技术实现 | 水印叠加 | 图像切分 | 多层叠加 | | 防篡改性 | 一般 | 强 | 中等 | | 处理复杂度 | 低 | 中 | 中 | | 推荐用途 | 证书、通知 | 合同、协议 | 多方签署文档 | | 印章数量 | 1个 | 1个 | 多个 | | 页面控制 | 支持 | 支持 | 精细控制 | | 配置灵活性 | 中等 | 中等 | 极高 | ## 🔧 高级配置 ### 多印章配置 #### 创建和管理多印章 ```go // 创建配置 config := hotn.NewStampConfig() config.SetInputFile("document.pdf") config.SetOutputFile("stamped.pdf") // 第一个印章 - 公司印章 companyStamp := hotn.NewStamp("company_seal.png") companyStamp.SetPosition("br") companyStamp.SetWidth(100) companyStamp.SetOpacity(0.7) companyStamp.SetPageRange(hotn.PageRangeAll) // 第二个印章 - 法人印章 legalStamp := hotn.NewStamp("legal_seal.png") legalStamp.SetPosition("bl") legalStamp.SetWidth(80) legalStamp.SetOpacity(0.8) legalStamp.SetPageRange(hotn.PageRangeFirst) // 仅首页 // 添加印章到配置 config.AddStamp(*companyStamp) config.AddStamp(*legalStamp) // 执行盖章 err := hotn.AddStamp(config) ``` #### 多印章管理方法 ```go // 获取印章数量 count := config.GetStampCount() fmt.Printf("共有 %d 个印章\n", count) // 获取指定印章 stamp := config.GetStamp(0) // 获取第一个印章 if stamp != nil { fmt.Printf("印章文件: %s\n", stamp.StampFile) } // 清空所有印章 config.ClearStamps() ``` #### 不同页面应用不同印章 ```go config := hotn.NewStampConfig() config.SetInputFile("contract.pdf") config.SetOutputFile("sealed_contract.pdf") // 首页印章 firstPageStamp := hotn.NewStamp("title_seal.png") firstPageStamp.SetPosition("tc") firstPageSelector := hotn.PageSelector{ PageNumbers: []int{1}, } firstPageStamp.SetPageSelector(firstPageSelector) // 签字页印章 signatureStamp := hotn.NewStamp("signature_seal.png") signatureStamp.SetPosition("br") signatureSelector := hotn.PageSelector{ PageNumbers: []int{10, 15, 20}, } signatureStamp.SetPageSelector(signatureSelector) // 所有页面水印 watermarkStamp := hotn.NewStamp("watermark.png") watermarkStamp.SetPosition("c") watermarkStamp.SetOpacity(0.3) watermarkStamp.SetPageRange(hotn.PageRangeAll) config.AddStamp(*firstPageStamp) config.AddStamp(*signatureStamp) config.AddStamp(*watermarkStamp) err := hotn.AddStamp(config) ``` #### 页面选择器示例 ```go // 页面选择器示例 config := hotn.NewStampConfig() config.SetInputFile("document.pdf") config.SetOutputFile("selective_stamped.pdf") stamp := hotn.NewStamp("stamp.png") stamp.SetPosition("tr") stamp.SetWidth(113) // 方式1:指定具体页面 selector := hotn.PageSelector{ PageNumbers: []int{1, 3, 5, 7}, // 只在第1,3,5,7页盖章 } stamp.SetPageSelector(selector) config.AddStamp(*stamp) // 方式2:使用页面范围 stamp2 := hotn.NewStamp("stamp.png") selector2 := hotn.PageSelector{ PageRanges: []hotn.PageRange{ {Start: 1, End: 5}, // 第1-5页 {Start: 10, End: 15}, // 第10-15页 }, } stamp2.SetPageSelector(selector2) config.AddStamp(*stamp2) // 方式3:混合使用 stamp3 := hotn.NewStamp("stamp.png") selector3 := hotn.PageSelector{ PageNumbers: []int{1, 20}, // 第1页和第20页 PageRanges: []hotn.PageRange{ {Start: 5, End: 10}, // 第5-10页 }, } stamp3.SetPageSelector(selector3) config.AddStamp(*stamp3) err := hotn.AddStamp(config) ``` ## 📋 API 参考 ### 位置锚点 ``` tl (top-left) tc (top-center) tr (top-right) l (left) c (center) r (right) bl (bottom-left) bc (bottom-center) br (bottom-right) ``` ### Stamp 印章结构体 ```go type Stamp struct { StampFile string // 印章图片文件路径 RidingStampPosition RidingStampPosition // 骑缝章位置(l, r, t, b) Position string // 位置锚点 (l,c,r,tl,tc,tr,bl,bc,br) Offset []int32 // 偏移量 [x, y] Width float64 // 印章宽度,单位:POINT(1点 = 1/72英寸)。会用来自动计算印章的大小 Opacity float64 // 透明度 (0.0-1.0) Rotation float64 // 旋转角度 (-180.0-180.0) RidingInterval int // 骑缝章间隔页数,0为单个覆盖全部 PageRangeType PageRangeType // 页面范围类型 PageSelector PageSelector // 自定义页面选择器 } // 链式配置方法 func (s *Stamp) SetPosition(pos string) *Stamp func (s *Stamp) SetOffset(x, y int32) *Stamp func (s *Stamp) SetOpacity(opacity float64) *Stamp func (s *Stamp) SetRotation(rotation float64) *Stamp func (s *Stamp) SetWidth(width float64) *Stamp func (s *Stamp) SetPageRange(rangeType PageRangeType) *Stamp func (s *Stamp) SetPageSelector(selector PageSelector) *Stamp // 工厂函数 func NewStamp(stampFile string) *Stamp ``` ### StampConfig 配置选项 ```go type StampConfig struct { InputFile string // 输入PDF文件路径 OutputFile string // 输出PDF文件路径 Stamps []Stamp // 印章配置列表(支持多印章) } // 多印章管理方法 func (c *StampConfig) AddStamp(stamp Stamp) *StampConfig func (c *StampConfig) ClearStamps() *StampConfig func (c *StampConfig) GetStampCount() int func (c *StampConfig) GetStamp(index int) *Stamp // 工厂函数 func NewStampConfig() *StampConfig ``` ### 页面选择类型 #### PageRangeType(基础范围类型) ```go type PageRangeType int const ( PageRangeAll PageRangeType = iota // 所有页面 PageRangeOdd // 仅奇数页 (1, 3, 5, 7...) PageRangeEven // 仅偶数页 (2, 4, 6, 8...) PageRangeFirst // 仅首页 PageRangeLast // 仅尾页 ) ``` #### PageRange(页面范围) ```go type PageRange struct { Start int // 起始页码(包含) End int // 结束页码(包含) } ``` #### PageSelector(自定义页面选择器) ```go type PageSelector struct { PageNumbers []int // 具体页面列表 PageRanges []PageRange // 页面范围列表 } // 方法 func (ps PageSelector) IsEmpty() bool // 检查是否为空选择器 ``` #### RidingStampPosition(骑缝章位置) ```go type RidingStampPosition string const ( RidingStampPositionTop RidingStampPosition = "t" // 顶部骑缝 RidingStampPositionBottom RidingStampPosition = "b" // 底部骑缝 RidingStampPositionLeft RidingStampPosition = "l" // 左侧骑缝 RidingStampPositionRight RidingStampPosition = "r" // 右侧骑缝 ) ``` **骑缝章位置偏移规则:** - `t` 或 `b`(顶部/底部骑缝):多组骑缝章向右偏移一个印章宽度 - `l` 或 `r`(左侧/右侧骑缝):多组骑缝章向下偏移一个印章高度 ### 核心函数 #### 普通盖章 ```go // 高级接口 func AddStamp(config *StampConfig) error ``` #### 骑缝章 ```go // 高级接口 func AddRidingStamp(config *StampConfig) error ``` ## 🎯 最佳实践 ### 印章设计建议 - **尺寸**: 建议高度为页面高度的1/3到1/2 - **格式**: 推荐PNG、JPG、JPEG、GIF、BMP格式,PNG支持透明背景 - **对比度**: 确保在各种背景下清晰可见 - **分辨率**: 建议300DPI以上,保证打印质量 - **自动缩放**: 使用`SetWidth()`设置宽度,高度自动计算 ### 骑缝章位置选择建议 - **RidingStampPositionTop/Bottom**: 适合横向文档,印章水平切分 - **RidingStampPositionLeft/Right**: 适合纵向文档,印章垂直切分 - **多组骑缝章**: 自动偏移避免重叠 - 顶部/底部骑缝:向右偏移一个印章宽度 - 左侧/右侧骑缝:向下偏移一个印章高度 ### 参数配置建议 ```go // 推荐配置 config := hotn.NewStampConfig() config.SetInputFile("input.pdf") config.SetOutputFile("output.pdf") stamp := hotn.NewStamp("seal.png") stamp.SetPosition("br") // 右下角,不影响阅读 stamp.SetWidth(100) // 适中大小 stamp.SetOpacity(0.7) // 既清晰又不遮挡内容 stamp.SetOffset(-20, 20) // 微调位置 stamp.SetPageRange(hotn.PageRangeAll) // 默认所有页面 config.AddStamp(*stamp) ``` ### 多印章使用建议 #### 印章层次规划 ```go // 推荐的印章层次结构 config := hotn.NewStampConfig() config.SetInputFile("document.pdf") config.SetOutputFile("stamped.pdf") // 1. 背景水印(最底层,透明度高) watermark := hotn.NewStamp("watermark.png") watermark.SetPosition("c") watermark.SetOpacity(0.2) // 低透明度,不影响阅读 watermark.SetWidth(200) // 大尺寸覆盖整页 watermark.SetPageRange(hotn.PageRangeAll) // 2. 公司印章(中间层) companyStamp := hotn.NewStamp("company_seal.png") companyStamp.SetPosition("br") companyStamp.SetOpacity(0.7) // 中等透明度 companyStamp.SetWidth(100) companyStamp.SetPageRange(hotn.PageRangeAll) // 4. 签名印章(特定页面) signatureStamp := hotn.NewStamp("signature.png") signatureStamp.SetPosition("bl") signatureStamp.SetOpacity(0.9) // 高透明度,清晰可见 signatureStamp.SetWidth(80) signatureSelector := hotn.PageSelector{ PageNumbers: []int{1, 10}, // 仅关键页面 } signatureStamp.SetPageSelector(signatureSelector) // 按层次顺序添加(先添加的在底层) config.AddStamp(*watermark) config.AddStamp(*companyStamp) config.AddStamp(*signatureStamp) ``` #### 印章位置避让 ```go // 避免印章重叠的位置规划 config := hotn.NewStampConfig() config.SetInputFile("document.pdf") config.SetOutputFile("stamped.pdf") // 左上角 - 标题印章 titleStamp := hotn.NewStamp("title_seal.png") titleStamp.SetPosition("tl") titleStamp.SetOffset(20, -20) // 向右下偏移 // 右上角 - 日期印章 dateStamp := hotn.NewStamp("date_seal.png") dateStamp.SetPosition("tr") dateStamp.SetOffset(-20, -20) // 向左下偏移 // 左下角 - 部门印章 deptStamp := hotn.NewStamp("dept_seal.png") deptStamp.SetPosition("bl") deptStamp.SetOffset(20, 20) // 向右上偏移 // 右下角 - 公司印章 companyStamp := hotn.NewStamp("company_seal.png") companyStamp.SetPosition("br") companyStamp.SetOffset(-20, 20) // 向左上偏移 config.AddStamp(*titleStamp) config.AddStamp(*dateStamp) config.AddStamp(*deptStamp) config.AddStamp(*companyStamp) ``` ### 性能优化 - **批量处理**: 对大量文档使用批处理 - **内存管理**: 及时清理临时文件 - **并发处理**: 可以并行处理多个文档 - **缓存策略**: 重复使用的印章可以预处理 - **骑缝章优化**: 自动智能分组算法,防重叠优化机制 - **多印章管理**: 合理规划印章层次和位置避让 ### 错误处理 ```go if err := hotn.AddStamp(config); err != nil { switch { case errors.Is(err, hotn.ErrFileNotFound): log.Println("文件不存在") case errors.Is(err, hotn.ErrInvalidConfig): log.Println("配置参数错误") case errors.Is(err, hotn.ErrPDFProcessing): log.Println("PDF处理失败") default: log.Printf("未知错误: %v", err) } } ``` ## 🔬 技术原理 ### 骑缝章实现原理 纳鲁之锤采用**图像切分技术**实现真正的骑缝章效果: 1. **图像分析**: 读取印章图片,获取尺寸信息 2. **智能切分**: 根据RidingStampPosition和PDF页数将印章切分成N个片段 - `t`/`b`(顶部/底部):水平切分 - `l`/`r`(左侧/右侧):垂直切分 3. **精确定位**: 每页使用对应的印章片段作为水印 4. **位置偏移**: 多组骑缝章根据位置类型自动偏移避免重叠 - 顶部/底部骑缝:向右偏移一个印章宽度 - 左侧/右侧骑缝:向下偏移一个印章高度 5. **无缝拼接**: 多页文档拼接后形成完整印章图像 ```go // 核心算法示例 // 印章尺寸自动从图片文件获取 stampWidth, stampHeight, _ := getStampImageDimensions(stampFile) // 根据骑缝章位置确定切分方向和偏移策略 switch ridingStampPosition { case RidingStampPositionTop, RidingStampPositionBottom: // 水平切分,多组向右偏移 segmentWidth := stampWidth / pageCount groupOffset[0] += groupIndex * stampWidth case RidingStampPositionLeft, RidingStampPositionRight: // 垂直切分,多组向下偏移 segmentHeight := stampHeight / pageCount groupOffset[1] += groupIndex * stampHeight } ``` ### 智能分组算法 纳鲁之锤采用**智能分组优化**技术,自动处理骑缝章的最佳分布: ```go // 智能分组示例:10页文档,间隔3页 // 传统分组: [1-3] [4-6] [7-9] [10] (最后一组只有1页) // 智能分组: [1-3] [4-6] [7-10] (自动合并最后一组) groups := calculateOptimizedRidingStampGroups(totalPages, interval) for _, group := range groups { // 为每组计算防重叠位置(印章尺寸自动获取) stampWidth, stampHeight, _ := getStampImageDimensions(stampFile) position := calculateGroupPosition(groupIndex, baseOffset, float64(stampWidth), float64(stampHeight), ridingStampPosition) } ``` #### 智能分组示例 ```go // 10页文档,每3页一组(包含防重叠优化) config := hotn.NewStampConfig() stamp := hotn.NewStamp("stamp.png") stamp.SetRidingInterval(3) stamp.RidingStampPosition = hotn.RidingStampPositionTop // 顶部骑缝,多组向右偏移 stamp.SetPosition("tl") stamp.SetWidth(113) stamp.SetOpacity(0.8) config.SetInputFile("document.pdf") config.SetOutputFile("sealed.pdf") config.AddStamp(*stamp) // 自动分组结果(防重叠优化): // 分组1: 页面1-3 (共3页) - 位置: 基础偏移 // 分组2: 页面4-6 (共3页) - 位置: 向右偏移1个印章宽度 // 分组3: 页面7-9 (共3页) - 位置: 向右偏移2个印章宽度 // 分组4: 页面8-10 (共3页) - 位置: 向右偏移3个印章宽度(防重叠新组) // 其他骑缝章位置示例: // RidingStampPositionLeft: 左侧骑缝,多组向下偏移 // RidingStampPositionRight: 右侧骑缝,多组向下偏移 // RidingStampPositionBottom: 底部骑缝,多组向右偏移 err := hotn.AddRidingStamp(config) ``` ### 防重叠优化机制 骑缝章功能包含智能防重叠优化,专门处理特定场景下的章印重叠问题: #### 适用场景 - **总页数**: 10页 - **间隔设置**: 每3页一组 - **问题**: 按常规分组会导致第10页与前面页面的章印重叠 #### 优化策略 ```go // 常规分组(会导致重叠): // 分组1: 页面1-3 // 分组2: 页面4-6 // 分组3: 页面7-10 (第10页与第7-9页重叠) // 防重叠优化后: // 分组1: 页面1-3 // 分组2: 页面4-6 // 分组3: 页面7-9 // 分组4: 页面8-10 (新增独立分组,避免重叠) ``` #### 技术实现 - 自动检测10页+3页间隔的特殊场景 - 创建独立的第4个分组覆盖页面8-10 - 确保每个章印都有独立的位置空间 - 其他页数配置保持原有的智能合并逻辑 ### 页面过滤机制 支持灵活的页面范围选择,满足不同业务需求: ```go // 页面过滤算法 func filterPagesByRange(totalPages int, rangeType PageRangeType) ([]int, error) { switch rangeType { case PageRangeAll: return []int{1, 2, 3, ..., totalPages}, nil case PageRangeOdd: return []int{1, 3, 5, 7, ...}, nil case PageRangeEven: return []int{2, 4, 6, 8, ...}, nil } } ``` ### 防篡改机制 - **页面完整性**: 任何页面的增删都会破坏印章连续性 - **内容保护**: 印章与页面内容形成整体,难以单独修改 - **视觉验证**: 通过肉眼即可快速识别文档是否被篡改 - **智能定位**: 自动计算防重叠位置,确保多组印章清晰可见 ## 🤝 贡献指南 我们欢迎所有形式的贡献! ### 开发环境 ```bash # 克隆项目 git clone https://gitee.com/leonscript/naaru-hammer.git cd naaru-hammer # 安装依赖 go mod tidy # 运行测试 go test ./hotn -v ``` ### 提交规范 - 🐛 `fix`: 修复bug - ✨ `feat`: 新功能 - 📚 `docs`: 文档更新 - 🎨 `style`: 代码格式 - ♻️ `refactor`: 重构 - ✅ `test`: 测试相关 ## 📄 许可证 本项目采用 MIT 许可证 - 查看 [LICENSE](LICENSE) 文件了解详情。 ## 🙏 致谢 - [pdfcpu](https://github.com/pdfcpu/pdfcpu) - 强大的PDF处理库 - [GoConvey](https://github.com/smartystreets/goconvey) - 优雅的测试框架 ---
**纳鲁之锤** - 让PDF盖章变得简单而强大 [⭐ Star](https://gitee.com/leonscript/naaru-hammer) | [🐛 Issues](https://gitee.com/leonscript/naaru-hammer/issues) | [📖 Wiki](https://gitee.com/leonscript/naaru-hammer/wikis)