iTextSharp - 某些页面没有按预期标记

时间:2011-04-06 14:18:37

标签: itextsharp

我正在使用iTextSharp 5.0.6来读取现有PDF,在每个页面上迭代每个页面标记文本,然后写出新标记的PDF。我面临的问题是,这不是100%的工作时间。对于某些PDF,每个页面都按预期标记,对于其他页面,大多数页面都会加盖,而有些页面则没有。看起来似乎存在压模的GetOverContent()没有返回最顶层的问题,但这只是一个假设。有没有人有类似的问题?

using iTextSharp.text;
using iTextSharp.text.pdf;
const string WATERMARK_TEXT = "John Doe";

static void Main(string[] args)
{
    string masterPdf = "master.pdf";
    string pdfToCreate = "watermark.pdf";

    byte[] bytes = StampPDF(masterPdf);
    using (FileStream stream = new FileStream(pdfToCreate, FileMode.Create))
    {
        stream.Write(bytes, 0, bytes.Length);
    }

}

static byte[] StampPDF(string PdfPath)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        PdfReader reader = new PdfReader(PdfPath);
        int pageCount = reader.NumberOfPages;
        PdfStamper stamper = new PdfStamper(reader, memoryStream);

        float fontSize = 9;
        float textAngle = 0f;
        BaseFont font = BaseFont.CreateFont(BaseFont.TIMES_ROMAN, BaseFont.WINANSI, BaseFont.EMBEDDED);
        BaseColor backgroundColor = new BaseColor(0, 0, 0);
        BaseColor fontColor = new BaseColor(255, 255, 255);
        float padding = 2f;
        float fontWidth = font.GetWidthPoint(WATERMARK_TEXT, fontSize);
        iTextSharp.text.Rectangle pageSize;
        PdfContentByte pageContents;
        for (int i = 1; i <= pageCount; i++)
        {
            pageSize = reader.GetPageSize(i);
            pageContents = stamper.GetOverContent(i);
            //draw a rectangle
            pageContents.SetColorFill(backgroundColor);
            pageContents.MoveTo(pageSize.Width - (fontWidth + padding), 0f);
            pageContents.LineTo(pageSize.Width, 0f);
            pageContents.LineTo(pageSize.Width, 14f);
            pageContents.LineTo(pageSize.Width - (fontWidth + padding), 14f);
            pageContents.Fill();
            //drop our watermark on top of the rectangle we just created
            pageContents.BeginText();
            pageContents.SetColorFill(fontColor);
            pageContents.SetFontAndSize(font, fontSize);
            pageContents.ShowTextAligned(PdfContentByte.ALIGN_LEFT, WATERMARK_TEXT, pageSize.Width - fontWidth, 4, textAngle);
            pageContents.EndText();
        }
        stamper.Close();
        reader.Close();

        return memoryStream.ToArray();
    }
}

2 个答案:

答案 0 :(得分:3)

对于那些可能遇到同样问题的人来说,关键是检查CropBox。由于PDF的CropBox的尺寸可能小于其PageSize的尺寸,因此您需要有条件地使用其中一个。因此,基于上面的代码示例,for循环将被更改为:

for (int i = 1; i <= pageCount; i++)
{
    mediaBox = reader.GetPageSize(i);
    cropBox = reader.GetCropBox(i);
    overContent = stamper.GetOverContent(i);

    if (cropBox != null && (cropBox.Width < mediaBox.Width || cropBox.Height < cropBox.Height))
        mediaBox = cropBox;

    //draw a rectangle
    overContent.SetColorFill(backgroundColor);
    overContent.MoveTo(mediaBox.Right - (fontWidth + fontPadding), mediaBox.Bottom);
    overContent.LineTo(mediaBox.Right, mediaBox.Bottom);
    overContent.LineTo(mediaBox.Right, mediaBox.Bottom + rectangleHeight);
    overContent.LineTo(mediaBox.Right - (fontWidth + fontPadding), mediaBox.Bottom + rectangleHeight);
    overContent.ClosePathFillStroke();
    //drop our watermark on top of the rectangle we just created
    overContent.BeginText();
    overContent.SetColorFill(fontColor);
    overContent.SetFontAndSize(font, fontSize);
    overContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, WATERMARK_TEXT, mediaBox.Right - fontWidth, mediaBox.Bottom + (rectangleHeight - fontSize), textAngle);
    overContent.EndText();
}

答案 1 :(得分:0)

你犯了两个错误:

  1. 您假设页面没有旋转,但它们可以是:90,180,270。请注意,我从未见过180页,但它是合法的。绘制到旋转页面时,必须在绘制时将该旋转考虑在内。有趣的转换矩阵。

  2. 您假设页面的(未旋转的)左下角是0,0。您的测量基于页面的宽度和高度(关闭),但不会调整左下角的任何偏移。

  3. 横向页面有三种方法:
    11 “×8.5”
    8.5“x11”@ 90度旋转
    8.5“x11”@ 270度旋转

    从技术上讲,第四种方法是建立一个11x8.5 @ 180,但任何人都应该惩罚这些代码。很多。

    有各种各样的SO问题浮出水面,提供有关如何处理页面轮换的详细信息。按照你的代码,我会说你会很快找出llx,lly的东西。