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

如何使用iTextSharp/iText裁剪PDF页面后完成2-up拼版?

解决方案:裁剪原PDF页面后实现2-up拼版

嘿,我完全get到你的需求了——你不想缩放原PDF页面,只是要精准裁掉每边2英寸的内容,再把裁剪后的页面并排放到17×11英寸的新PDF里,而且已经试过MediaBox/CropBox但发现AddTemplate不吃这套,对吧?别担心,这里有个直接的解决方案,用iText的绘图状态控制和变换矩阵就能搞定,完全符合你的要求。

核心思路

我们不用修改原PDF的页面属性(MediaBox/CropBox),而是在绘制原页面到新PDF时,通过裁剪矩形限制显示区域,同时用AddTemplate的偏移参数把原页面的有效内容对齐到裁剪区域内。这样既不会缩放页面,又能精准保留我们需要的部分。

先明确尺寸换算(iText用点作为单位,1英寸=72点):

  • 原PDF:8.5"×11" → 612×792点
  • 裁剪边距:2英寸 → 144点
  • 裁剪后有效区域:宽度=612-2×144=324点(4.5"),高度=792-2×144=504点(7")
  • 新PDF:17"×11" → 1224×792点

代码实现(C# iTextSharp示例)

using System.IO;
using iTextSharp.text;
using iTextSharp.text.pdf;

class PdfCropperAnd2Up
{
    static void Main(string[] args)
    {
        // 尺寸常量(英寸转点)
        const float InchToPoint = 72f;
        const float CropMargin = 2f * InchToPoint;
        
        // 原PDF尺寸
        const float OrigWidth = 8.5f * InchToPoint;
        const float OrigHeight = 11f * InchToPoint;
        
        // 裁剪后页面尺寸
        const float CroppedWidth = OrigWidth - 2 * CropMargin;
        const float CroppedHeight = OrigHeight - 2 * CropMargin;
        
        // 新PDF尺寸
        const float NewWidth = 17f * InchToPoint;
        const float NewHeight = 11f * InchToPoint;

        using (PdfReader reader = new PdfReader("input.pdf"))
        using (FileStream fs = new FileStream("output.pdf", FileMode.Create))
        using (Document document = new Document(new Rectangle(NewWidth, NewHeight)))
        {
            PdfWriter writer = PdfWriter.GetInstance(document, fs);
            document.Open();
            PdfContentByte contentByte = writer.DirectContent;

            int totalPages = reader.NumberOfPages;
            // 每2页生成一个新的拼版页面
            for (int pageNum = 1; pageNum <= totalPages; pageNum += 2)
            {
                document.NewPage();

                // 处理左半边页面
                if (pageNum <= totalPages)
                {
                    PdfImportedPage sourcePage = writer.GetImportedPage(reader, pageNum);
                    // 左页面的起始位置:水平从0开始,垂直居中
                    float leftX = 0;
                    float leftY = (NewHeight - CroppedHeight) / 2;

                    // 保存当前绘图状态,避免裁剪影响后续内容
                    contentByte.SaveState();
                    // 设置裁剪矩形:只显示我们需要的区域
                    contentByte.Rectangle(leftX, leftY, CroppedWidth, CroppedHeight);
                    contentByte.Clip();
                    contentByte.NewPath();

                    // 偏移原页面:把裁剪后的有效区域对齐到裁剪矩形
                    // 向左、向下偏移裁剪边距(PDF坐标系原点在左下角)
                    contentByte.AddTemplate(sourcePage, 1, 0, 0, 1, leftX - CropMargin, leftY - CropMargin);
                    // 恢复绘图状态
                    contentByte.RestoreState();
                }

                // 处理右半边页面
                if (pageNum + 1 <= totalPages)
                {
                    PdfImportedPage sourcePage = writer.GetImportedPage(reader, pageNum + 1);
                    // 右页面的起始位置:水平从新页面中点开始,垂直居中
                    float rightX = NewWidth / 2;
                    float rightY = (NewHeight - CroppedHeight) / 2;

                    contentByte.SaveState();
                    contentByte.Rectangle(rightX, rightY, CroppedWidth, CroppedHeight);
                    contentByte.Clip();
                    contentByte.NewPath();

                    contentByte.AddTemplate(sourcePage, 1, 0, 0, 1, rightX - CropMargin, rightY - CropMargin);
                    contentByte.RestoreState();
                }
            }
        }
    }
}

关键细节解释

  1. SaveState()/RestoreState():必须成对使用,用来保存和恢复绘图状态,防止当前裁剪矩形影响后续页面的绘制。
  2. Rectangle()+Clip():创建一个裁剪区域,只有落在这个区域内的内容才会被渲染到新PDF上。
  3. AddTemplate()的偏移参数:最后两个参数是X/Y方向的偏移量。我们把原页面向左、向下各偏移2英寸(144点),让原页面的有效内容刚好对齐到裁剪矩形的位置,这样就相当于“裁掉”了边缘内容。
  4. 垂直居中排版:通过(NewHeight - CroppedHeight)/2计算垂直方向的起始位置,让裁剪后的页面在新PDF中垂直居中,排版更美观。

内容的提问来源于stack exchange,提问作者Scott Mitchell

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:03:14