【问题标题】:Cannot stamp certain PDFs无法标记某些 PDF
【发布时间】:2014-08-12 09:58:35
【问题描述】:

PDF 标记几乎适用于我尝试过的所有文档。然而,一位客户扫描了一些页面,他的计算机生成了一个可以抵抗盖章的 PDF 文档。嵌入的图像文件是 JBIG2 格式,但我不确定这是否重要。我已经用 Apache 的 pdfbox 调试了 PDF,我可以看到嵌入的文本。它只是没有显示出来。

这里是不会盖章的 PDF:http://demo.clearvillageinc.com/plans.pdf

还有我的代码:

static void Main(string[] args) {
    string stamp = "<div style=\"color:#F00;\">Reviewed for Code Compliance</div>";
    string fileName = @"C:\temp\source.pdf";
    string outputFileName = @"C:\temp\source-output.pdf";

    // Open a destination stream.
    using (var destStream = new System.IO.MemoryStream()) {
        using (var sourceReader = new PdfReader(fileName)) {

            // Convert the HTML into a stamp.
            using (var stampData = FromHtml(stamp)) {
                using (var stampReader = new PdfReader(stampData)) {
                    using (var stamper = new PdfStamper(sourceReader, destStream)) {
                        stamper.Writer.CloseStream = false; 
                        // Add the stamp stream to the source document.
                        var stampPage = stamper.GetImportedPage(stampReader, 1);

                        // Process all of the pages in the source document.
                        for (int i = 1; i <= sourceReader.NumberOfPages; i++) {
                            var canvas = stamper.GetOverContent(i);
                            canvas.AddTemplate(stampPage, 0, -50);
                        }
                    }
                }
            }
        }

        // Finished.  Save the file.    
        using (var fs = new System.IO.FileStream(outputFileName, FileMode.Create)) {
            destStream.Position = 0;
            destStream.CopyTo(fs);
        }
    }
}

public static System.IO.Stream FromHtml(string html) {
    var ms = new System.IO.MemoryStream();

    // Convert html to pdf.
    using (var document = new iTextSharp.text.Document()) {
        var writer = iTextSharp.text.pdf.PdfWriter.GetInstance(document, ms);
        writer.CloseStream = false;

        document.Open();

        using (var sr = new System.IO.StringReader(html)) {
            XMLWorkerHelper.GetInstance().ParseXHtml(writer, document, sr);
        }
    }

    ms.Position = 0; // Reset for reading.
    return ms;
}

【问题讨论】:

标签: pdf itextsharp


【解决方案1】:

页面定义的一部分是控制页面大小的“MediaBox”。此属性采用两个位置,指定矩形的两个对角的坐标。尽管不是必需的,但大多数 PDF 首先指定左下角,然后是右上角。此外,大多数 PDF 使用0x0 作为左下角,然后使用页面的顶部角的宽度和高度。因此,一个 8.5x11 英寸的 PDF 将是 0,0612,792(8.5 * 72 = 612 和 11 * 72 = 792),这将被写为 0,0,612,792

但是,无论出于何种原因,您扫描的 PDF 都决定将 0,7072 视为左下角,将 614,7864 视为右上角。这仍然(几乎)为我们提供了 8.5x11 的页面大小,但如果您尝试在 0,0 处绘制一些东西,它将比实际页面低 7,072 像素。您可以在 Acrobat Pro 中通过缩小非常远(对我来说是 1%)、选择工具、编辑对象然后执行全选来看到这一点。你也应该看到一些被选中的东西。

要解决这个问题,您需要尊重页面的边界。

for (int i = 1; i <= sourceReader.NumberOfPages; i++) {
    //Get the page to be stamped
    var pageToBeStamped = sourceReader.GetPageSize(i);

    var canvas = stamper.GetOverContent(i);

    //Offset our new page by 50 pixels off of the destination page's bottom
    canvas.AddTemplate(stampPage, pageToBeStamped.Left, pageToBeStamped.Bottom - 50);
}

上面的代码获取导入页面的矩形并使用底部偏移 50 像素(来自您的原始代码)。此外,虽然在您的情况下不是问题,但我们使用导入页面的实际左边缘而不是零。

但是,此代码仍可能中断。第一段中的数学使用72,这是 PDF 的默认值,但可以更改。大多数人不会改变它,但大多数人也不会改变0,0。目前,您的-50 假定为72,这提供了将印章从顶部边缘移动约十分之七英寸的视觉感知。如果您遇到这种情况,您需要查看retrieving the user unit

另外,正如我在第一段中所说,大多数应用程序使用左下右上,但这不是硬性规则。有人可以指定右上角和左下角,甚至是左上角和右下角。这是一个很难考虑的问题,但您至少应该意识到这一点。

【讨论】:

    猜你喜欢
    • 2016-04-21
    • 2011-10-03
    • 2010-10-30
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2016-01-17
    • 1970-01-01
    • 2012-05-26
    相关资源
    最近更新 更多