开发者

iTextSharp - Some pages not stamped as expected

I'm using iTextSharp 5.0.6 to read an existing PDF, iterate each page stamping text on each, and then writing out the newly stamped PDF. The issue I'm faced with is that this isn't working 100% of the time. For some PDFs every page is stamped as expected, for others most pages are stamped while some are not. Seems as if there's potentially an issue where the stamper's GetOverContent() is not returning the top-most layer, but that's just an assumption. Has anyone had a similar issue?

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 f开发者_开发问答ontSize = 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();
    }
}


For those that may encounter the same problem the key is inspecting the CropBox. Since the dimensions of a PDF's CropBox may be less than that of its PageSize you need to conditionally use one or the other. So, based on the code sample above the for loop would be altered as so:

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();
}


You've made two mistakes:

  1. You're assuming that the pages aren't rotated, but they can be: 90, 180, 270. Note that I've never seen a 180 page, but its legal. When drawing to a rotated page, you have to take that rotation into account when drawing on it. Fun with transformation matrices.

  2. You're assuming that the page's (unrotated) lower left corner is 0,0. You're basing your measurements on the page's width and height (close), but aren't adjusting for any offset in that bottom left corner.

There are three ways to do a landscape page:
11"x8.5"
8.5"x11" @ 90 degrees rotation
8.5"x11" @ 270 degrees rotation

Technically, a 4th way is to build an 11x8.5 @ 180, but anyone writing such code should be Punished. A lot.

There are various SO questions floating about that give details on how to deal with page rotation. Going by your code, I'd say you'll figure out the llx,lly thing pretty quickly.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜