【问题标题】:iTextSharp copy document, resize to custom size, and centeriTextSharp 复制文档,调整为自定义大小,并居中
【发布时间】:2013-05-15 19:57:20
【问题描述】:

我已经为此苦苦挣扎了一段时间,所以我想我会把这篇文章发给任何能够找到解决方案的大师。

我有一个要复制的 PDF 文档,当我复制它时,我想将页面大小调整为自定义大小。例如,原始文档的页面大小为 8 1/2 x 16。新文档需要为 8 1/2 x 22。新文档中的 8 1/2 来自原始的宽度; 22 是固定的(常数)。使问题复杂化的是新文档需要将旧文档内容置于页面中心。因此,在新文档中,它需要具有顶部 3 英寸、底部 3 英寸的边距,以便原始 16 英寸居中。宽度无关紧要,只是高度需要居中。

寻找 iTextSharp 的代码片段。

创建了以下有效的解决方案。发回社区,希望它可以帮助某人。解决方案在 VB.NET 中。

使用带有 2 个布尔值的调用 resizeAndRotateDocument。 “旋转” - 将每一页旋转 90 度 - 真,假。和“调整大小” - 将页面大小调整为 22 英寸高度,并将边距添加到顶部/底部到中心页面 - 真/假。还有 2 个字符串:要处理的输入 pdf 文件的名称和要创建的输出 pdf 文件的名称。

    Private Sub AdjustMediaBoxSize(ByRef mediaBoxSize As PdfArray, ByVal rotationIsPresent As Boolean)

    Const Fixed_22_Inch_Page As Integer = 22 * 72

    Dim ll_x, ll_y, ur_x, ur_y As Integer
    Dim heightDiff, heightAdjustment As Integer
    Dim new_ll_x, new_ll_y, new_ur_x, new_ur_y As Integer

    ' Read current coordinates of the Mediabox
    ll_x = mediaBoxSize(0).ToString
    ll_y = mediaBoxSize(1).ToString

    ur_x = mediaBoxSize(2).ToString
    ur_y = mediaBoxSize(3).ToString

    ' Figure out the height difference and the adjustment factor.
    If rotationIsPresent = True Then
        heightDiff = Fixed_22_Inch_Page - ur_x
    Else
        heightDiff = Fixed_22_Inch_Page - ur_y
    End If

    ' adjustment needed to top and to bottom
    heightAdjustment = heightDiff / 2

    ' Apply the adjustments; only use the ones we need.
    new_ll_x = ll_x - heightAdjustment
    new_ur_x = ur_x + heightAdjustment

    new_ll_y = ll_y - heightAdjustment
    new_ur_y = ur_y + heightAdjustment

    If rotationIsPresent = True Then
        mediaBoxSize(0) = New iTextSharp.text.pdf.PdfNumber(new_ll_x)
        mediaBoxSize(2) = New iTextSharp.text.pdf.PdfNumber(new_ur_x)
    Else
        ' Make the adjustment. Value is passed back by reference.
        mediaBoxSize(1) = New iTextSharp.text.pdf.PdfNumber(new_ll_y)
        mediaBoxSize(3) = New iTextSharp.text.pdf.PdfNumber(new_ur_y)
    End If

End Sub

Private Sub resizeAndRotateDocument(ByVal rotate As Boolean, ByVal resize As Boolean, ByVal inPDF As String, ByVal outPDF As String)

    Const desiredRot As Integer = 90

    Dim reader As New PdfReader(inPDF)
    Dim pageCount As Integer = reader.NumberOfPages

    Dim pageDict As PdfDictionary
    Dim mediabox As New PdfArray
    Dim cropbox As New PdfArray

    For i As Integer = 1 To pageCount

        pageDict = reader.GetPageN(i)

        ' Rotation is hard coded to 90 degrees.
        If rotate = True Then
            pageDict.Put(PdfName.ROTATE, New PdfNumber(desiredRot))
        End If

        If resize = True Then
            ' Read the current mediabox dimensions. 
            ' Then adjust the size to scale up to 22 inches adjusting for rotation if necessary.
            ' Finally, write the updated mediabox back to the dictionary -> to the reader.

            mediabox = pageDict.GetAsArray(PdfName.MEDIABOX)
            AdjustMediaBoxSize(mediabox, rotate)
            pageDict.Put(PdfName.MEDIABOX, mediabox)

        End If

        ' Since the PDFs are created in-house, they should NEVER contain a cropbox.
        cropbox = pageDict.GetAsArray(PdfName.CROPBOX)
        If cropbox IsNot Nothing Then
            MsgBox("Error ... found a valid cropbox !!!")
        End If

    Next

    ' Use the stamper to create and write the pdf output file.
    Dim pdfStamper As New PdfStamper(reader, New FileStream(outPDF, FileMode.Create))
    pdfStamper.Close()

End Sub

再次感谢布鲁诺!

【问题讨论】:

    标签: c# vb.net pdf itextsharp


    【解决方案1】:

    看看我书中的RotatePages 示例。在ManipulatePdf() 方法中,我遍历页面,获取页面字典,并更改/Rotate 键以旋转页面。这不是你需要的,但原理是相似的。

    您需要从页面字典中获取/MediaBox/CropBox 值:

    PdfArray mediabox = pageDict.getAsArray(PdfName.MEDIABOX);
    PdfArray cropbox = pageDict.getAsArray(PdfName.CROPBOX);
    

    在许多情况下,cropbox 将是null,在这种情况下您可以放心地忽略它。

    您的页面尺寸为 8 1/2 x 16 英寸,所以我猜 mediabox 将是一个如下所示的数组:[ 0 0 612 1152 ]

    零点是左下角的坐标。右上角的坐标为 x = 612 (72 x 8.5) 和 y = 1152 (72 x 16)。

    现在您需要用类似的数组替换 /MediaBox 条目,在该数组中从第二个值中减去 216 (72 x 3) 并将 216 添加到第四个值中。换句话说:你最终会得到以下数组[ 0 -216 612 1368 ]。将/MediaBox(和/CropBox,如果存在)替换为这样一个改变的数组,就像我替换/Rotate键一样,你就有了你的示例代码。

    如果我是你,我不会使用绝对值,我会从你在页面字典中找到的数组中的任何值中减去 216。

    免责声明:我是 iText 的原作者,以及从中获取旋转示例的“iText in Action”书籍的原作者。我是一名 Java 开发人员;我花钱请其他开发人员将我书中的示例移植到 C#。请不要让我用 C# 写出你的例子,因为我从来没有写过任何 C# 代码,只有 Java 代码。我相信您将能够使用本文中提供的信息编写满足您需求的代码。

    【讨论】:

    • Bruno ...关于我的后续问题的任何建议。如果您在调整大小之前添加旋转,则调整大小不会正确。
    • 如果您更新原始问题,我不会收到有关此更新的警告。我提出的调整大小解决方案是基于没有旋转的假设。如果有,您需要更改 X 的值而不是 Y 的值。换句话说:您需要先测试旋转,然后决定是调整 Y 值还是 X 值。
    • 嗨,我正在尝试使用此选项来剪切 pdf 页面的顶部和底部(页面大小不应更改)。但无法获得输出。裁切后页面大小总是减小到平衡区域。是否可以在不更改页面大小的情况下剪切某些区域?
    • 你需要引入一个剪切路径来实现你想要的。 “剪辑”的内容仍会出现在文件中,但人眼看不到。
    • @BrunoLowagie 您能否详细说明“我会从您在页面字典中找到的数组中的任何值中减去 216。”是否真的可以一次移动页面的全部内容(无需遍历所有对象)?
    猜你喜欢
    • 2012-02-01
    • 1970-01-01
    • 2013-08-27
    • 2011-01-30
    • 1970-01-01
    • 1970-01-01
    • 2013-03-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多