<think>我们使用PyMuPDF库,它允许我们精确控制印章的位置和大小。在之前的代码中,我们通过定义一个矩形区域(fitz.Rect)来指定印章的位置和大小。这个矩形由四个坐标确定:左上角(x0, y0)和右下角(x1, y1)。我们可以通过调整这四个坐标来改变印章的位置和大小。
调整位置:通过改变矩形左上角的坐标(x0, y0)来移动印章。
调整大小:通过改变矩形右下角的坐标(x1, y1)来缩放印章。注意,保持印章的宽高比通常很重要,否则图像会变形。
### 具体步骤:
1. **位置调整**:我们可以通过改变矩形左上角的坐标来移动印章。例如,将印章放在右下角,我们使用:
```python
x0 = page.rect.width - stamp.width - 50 # 从右边往左50像素,再减去印章宽度
y0 = page.rect.height - stamp.height - 50 # 从底边往上50像素,再减去印章高度
```
如果我们想放在其他位置,比如左上角:
```python
x0 = 50 # 左边50像素
y0 = 50 # 顶部50像素
```
2. **大小调整**:如果我们想改变印章的大小,可以指定一个目标宽度和高度,然后创建相应大小的矩形。但要注意,直接缩放图像可能会影响质量。我们可以通过设置目标宽度和高度,然后计算矩形:
```python
# 假设我们想要将印章缩放到宽度为100,高度按比例缩放
target_width = 100
# 计算等比例的高度
target_height = stamp.height * (target_width / stamp.width)
# 然后定义矩形
stamp_rect = fitz.Rect(x0, y0, x0 + target_width, y0 + target_height)
```
### 改进的盖章函数(允许自定义位置和大小):
下面是一个改进的函数,允许用户指定印章在页面上的位置(通过左上角坐标)和印章的目标宽度(高度自动按比例计算):
```python
import fitz
def add_stamp_to_pdf(input_pdf, output_pdf, stamp_png, x, y, width=None):
"""
在PDF文件上叠加印章图像,并可以调整位置和大小
参数:
input_pdf: 源PDF文件路径
output_pdf: 输出PDF文件路径
stamp_png: 印章PNG图像路径
x: 印章左上角在页面上的x坐标(单位:点)
y: 印章左上角在页面上的y坐标(单位:点)
width: 印章的目标宽度(单位:点),如果为None,则使用原始宽度
"""
doc = fitz.open(input_pdf)
stamp = fitz.Pixmap(stamp_png)
# 如果指定了目标宽度,则计算等比例的高度
if width is not None:
# 计算缩放比例
scale = width / stamp.width
height = stamp.height * scale
else:
width = stamp.width
height = stamp.height
for page in doc:
# 创建矩形区域(左上角(x, y),右下角(x+width, y+height))
stamp_rect = fitz.Rect(x, y, x + width, y + height)
page.insert_image(stamp_rect, pixmap=stamp)
doc.save(output_pdf)
doc.close()
print(f"成功生成带印章的PDF: {output_pdf}")
# 示例:在每页的(50, 50)位置放置一个宽度为100点的印章
if __name__ == "__main__":
add_stamp_to_pdf(
input_pdf="原始文件.pdf",
output_pdf="带印章文件.pdf",
stamp_png="印章.png",
x=50,
y=50,
width=100
)
```
### 注意事项:
1. **坐标系统**:PDF的坐标系统原点在左下角,但PyMuPDF的Rect对象使用左上角为原点(即y轴向下)。因此,我们提供的y坐标是从页面顶部开始计算的。如果你想要从底部计算,可以使用`page.rect.height - y - height`(其中y为距离底部的距离)。
2. **单位**:PDF中使用的单位是点(point),1点=1/72英寸。所以,如果你需要厘米或毫米,可以自行转换。
3. **透明度**:PyMuPDF支持带有透明通道的PNG图像,因此印章的透明背景会被保留。
4. **性能**:对于大型PDF文件,处理速度可能较慢。可以考虑使用多线程或仅处理特定页面(例如只处理最后一页)来优化。
### 调整印章位置为页面底部居中示例:
如果我们想将印章放在页面底部居中位置,可以这样计算坐标:
```python
# 假设我们已经有了目标宽度和高度(width, height)
x = (page.rect.width - width) / 2 # 水平居中
y = page.rect.height - height - 50 # 距离底部50点
```
### 自定义每页位置:
上述函数在每一页的相同位置盖章。如果需要不同页面不同位置,可以在循环内单独计算每页的位置。
### 相关问题:
1. 如何为PDF文件的特定页面(如最后一页)添加印章?
2. 如何批量处理多个PDF文件并添加不同的印章?
3. 如何调整印章的旋转角度?
4. 如何处理带有水印或背景的PDF文件?
希望这些信息能帮助你灵活调整印章的位置和大小。</think># 使用Python调整PDF印章位置和大小的方法
在PDF文件上添加印章时,精确控制位置和大小至关重要。下面我将详细介绍如何使用Python和PyMuPDF库调整印章的位置和大小。
## 完整解决方案
```python
import fitz # PyMuPDF
def add_stamp_to_pdf(input_pdf, output_pdf, stamp_png,
position='bottom-right', offset=(50, 50),
scale=1.0, rotation=0, pages='all'):
"""
在PDF文件上添加可调整位置和大小的印章
参数:
input_pdf: 源PDF文件路径
output_pdf: 输出PDF文件路径
stamp_png: 印章PNG图像路径
position: 印章位置 ('top-left', 'top-right', 'bottom-left', 'bottom-right', 'center')
offset: 偏移量 (x, y) 单位:点
scale: 缩放比例 (1.0为原始大小)
rotation: 旋转角度 (0-360度)
pages: 添加印章的页面 ('all', 'last', 页码列表如[0,2])
"""
# 打开PDF文档
doc = fitz.open(input_pdf)
# 加载印章图像
stamp = fitz.Pixmap(stamp_png)
# 计算缩放后尺寸
scaled_width = int(stamp.width * scale)
scaled_height = int(stamp.height * scale)
# 确定要处理的页面
if pages == 'all':
target_pages = range(len(doc))
elif pages == 'last':
target_pages = [len(doc) - 1]
else:
target_pages = pages
for page_num in target_pages:
page = doc[page_num]
# 计算印章位置
if position == 'top-left':
x0, y0 = offset
elif position == 'top-right':
x0 = page.rect.width - scaled_width - offset[0]
y0 = offset[1]
elif position == 'bottom-left':
x0 = offset[0]
y0 = page.rect.height - scaled_height - offset[1]
elif position == 'bottom-right':
x0 = page.rect.width - scaled_width - offset[0]
y0 = page.rect.height - scaled_height - offset[1]
elif position == 'center':
x0 = (page.rect.width - scaled_width) / 2 + offset[0]
y0 = (page.rect.height - scaled_height) / 2 + offset[1]
else:
x0, y0 = offset
# 创建印章矩形区域
stamp_rect = fitz.Rect(x0, y0, x0 + scaled_width, y0 + scaled_height)
# 添加印章(支持旋转)
if rotation != 0:
# 创建旋转矩阵
mat = fitz.Matrix().rotate(rotation)
# 添加旋转后的印章
page.insert_image(stamp_rect, pixmap=stamp, rotate=rotation)
else:
page.insert_image(stamp_rect, pixmap=stamp)
# 保存带印章的PDF
doc.save(output_pdf)
doc.close()
print(f"成功生成带印章的PDF: {output_pdf}")
# 使用示例
if __name__ == "__main__":
# 在右下角添加印章(默认位置)
add_stamp_to_pdf("原始文件.pdf", "带印章文件1.pdf", "印章.png")
# 在左上角添加印章,缩放50%,无偏移
add_stamp_to_pdf("原始文件.pdf", "带印章文件2.pdf", "印章.png",
position='top-left', offset=(0, 0), scale=0.5)
# 在页面中心添加印章,旋转45度
add_stamp_to_pdf("原始文件.pdf", "带印章文件3.pdf", "印章.png",
position='center', rotation=45)
# 只在最后一页添加印章
add_stamp_to_pdf("原始文件.pdf", "带印章文件4.pdf", "印章.png",
pages='last')
```
## 参数详解
### 1. 位置调整 (`position`)
- **预定义位置**:使用字符串指定预设位置
- `'top-left'`:左上角
- `'top-right'`:右上角
- `'bottom-left'`:左下角
- `'bottom-right'`:右下角(默认)
- `'center'`:页面中心
- **自定义位置**:通过`offset`参数微调位置
- `offset=(x, y)`:x为水平偏移量,y为垂直偏移量(单位:点,1点=1/72英寸)
- 示例:`offset=(100, 50)` 表示向右100点,向下50点
### 2. 大小调整 (`scale`)
- 缩放比例:1.0表示原始大小,0.5表示缩小一半,2.0表示放大一倍
- 保持宽高比:自动按比例缩放,不会变形
- 公式:$新宽度 = 原始宽度 \times scale$,$新高度 = 原始高度 \times scale$
### 3. 旋转角度 (`rotation`)
- 支持0-360度旋转
- 示例:`rotation=45` 表示顺时针旋转45度
### 4. 页面选择 (`pages`)
- `'all'`:所有页面添加印章(默认)
- `'last'`:只在最后一页添加印章
- 页码列表:如`[0, 2]`表示在第1页和第3页添加印章(页码从0开始)
## 高级技巧
### 1. 精确位置计算
使用页面尺寸和印章尺寸进行精确计算:
```python
# 计算页面中心位置
center_x = (page.rect.width - scaled_width) / 2
center_y = (page.rect.height - scaled_height) / 2
# 计算特定百分比位置
percent_x = 0.3 # 水平位置30%
percent_y = 0.7 # 垂直位置70%
x = page.rect.width * percent_x
y = page.rect.height * percent_y
```
### 2. 保持原始质量
当缩放印章时,PNG图像的透明度通道会被保留:
```python
# 检查图像是否有alpha通道
if stamp.n > 3:
print("印章包含透明通道,缩放后仍保持透明效果")
```
### 3. 批量处理
结合文件系统操作批量处理多个PDF:
```python
import os
input_folder = "待处理PDF文件夹/"
output_folder = "已盖章PDF文件夹/"
stamp_file = "印章.png"
for pdf_file in os.listdir(input_folder):
if pdf_file.lower().endswith(".pdf"):
input_path = os.path.join(input_folder, pdf_file)
output_path = os.path.join(output_folder, f"盖章_{pdf_file}")
add_stamp_to_pdf(input_path, output_path, stamp_file)
```
## 常见问题解答
**Q: 如何确保印章在不同尺寸的PDF页面上位置一致?**
A: 使用相对位置计算(百分比)而非绝对像素值:
```python
# 右下角,距离边缘5%
x = page.rect.width * 0.95 - scaled_width
y = page.rect.height * 0.95 - scaled_height
```
**Q: 如何处理大型PDF文件的性能问题?**
A: 1) 仅处理必要页面 2) 避免不必要的图像处理 3) 使用PyMuPDF的增量保存功能[^1]
**Q: 印章添加后模糊怎么办?**
A: 1) 使用高分辨率印章图像 2) 避免过度放大 3) 确保PDF保存时保留图像质量
**Q: 如何添加多个印章到同一页面?**
A: 多次调用`insert_image`方法:
```python
# 添加主印章
page.insert_image(rect1, pixmap=stamp1)
# 添加副印章
page.insert_image(rect2, pixmap=stamp2)
```
通过调整位置、大小、旋转等参数,您可以精确控制PDF印章的外观和位置。此方法支持透明PNG印章,并保持原始PDF的矢量质量[^2]。