pdf-lib 如何将裁剪后的页面切片堆叠回单页?
结论
setCropBox() 只设置页面的可视区域,不会删除页面内容流中的其他内容。后续代码通过 copyPages() 和 embedPdf() 导入页面时,仍然处理整页,因此 CropBox 隐藏的内容也可能被带入。
要把切片组合到一页上,可以使用 PDFDocument.embedPage(page, boundingBox),为每个切片指定边界,再将嵌入页面绘制到目标页。boundingBox 使用 PDF 页面坐标系,原点在左下角。pdf-lib 的 API 文档列出了 embedPage 的可选 boundingBox 参数。pdf-lib API 文档
按切片边界嵌入页面
下面假设每个切片都是原始页面上的一个矩形,边界格式为 { left, bottom, right, top }。请将 chunkBoxes 替换为裁剪 UI 实际生成的坐标,并确保坐标相对于原始页面,而非缩放或裁剪后的预览图。
import { PDFDocument } from 'pdf-lib';
export async function stackChunks(
inputBytes: Uint8Array,
outputBytes: Uint8Array,
sourcePageIndex: number,
chunkBoxes: Array<{
left: number;
bottom: number;
right: number;
top: number;
}>,
) {
const sourceDoc = await PDFDocument.load(inputBytes);
const sourcePage = sourceDoc.getPage(sourcePageIndex);
const { width: pageWidth, height: pageHeight } = sourcePage.getSize();
const outputDoc = await PDFDocument.create();
const outputPage = outputDoc.addPage([pageWidth, pageHeight]);
const margin = 30;
const spacing = 10;
const targetWidth = pageWidth - margin * 2;
let currentY = pageHeight - margin;
for (const box of chunkBoxes) {
const chunkWidth = box.right - box.left;
const chunkHeight = box.top - box.bottom;
if (chunkWidth <= 0 || chunkHeight <= 0) {
throw new Error('切片边界无效');
}
const embeddedChunk = await outputDoc.embedPage(sourcePage, box);
const scale = targetWidth / chunkWidth;
const drawWidth = chunkWidth * scale;
const drawHeight = chunkHeight * scale;
if (currentY - drawHeight < margin) {
throw new Error('切片总高度超出目标页面;请减小缩放比例或增加目标页');
}
outputPage.drawPage(embeddedChunk, {
x: margin,
y: currentY - drawHeight,
width: drawWidth,
height: drawHeight,
});
currentY -= drawHeight + spacing;
}
return outputDoc.save();
}
代码会把所有切片绘制到同一张目标页面,因此 chunkBoxes 的顺序决定了它们从页面顶部开始的堆叠顺序。drawPage() 的 x、y 使用左下角坐标;代码通过 currentY - drawHeight 将切片放在当前垂直位置下方。
如果现有的裁剪页保留了对应的 CropBox,可以读取并转换为嵌入边界:
const crop = croppedPage.getCropBox();
const box = {
left: crop.x,
bottom: crop.y,
right: crop.x + crop.width,
top: crop.y + crop.height,
};
然后将 box 传给 embedPage()。如果裁剪边界只保存在前端预览坐标中,需要先换算为 PDF 页面坐标,并确认切片宽高、页面旋转和坐标原点都与 PDF 页面一致。
关于“删除”被裁掉的内容
使用 boundingBox 可以在嵌入时限制显示范围,适合将切片排版到新页面,但不会从源 PDF 中物理删除矩形外的内容。如果需要彻底清除敏感内容,不能只依赖 CropBox 或嵌入裁剪;应采用能够移除或重建对应页面内容的处理方案,并检查最终文件。
备注:内容仅供参考。
