iTextSharp - некоторые страницы не отмечены должным образом - PullRequest
4 голосов
/ 06 апреля 2011

Я использую 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 ]

3 голосов
/ 11 апреля 2011

Для тех, кто может столкнуться с той же проблемой, ключ проверяет CropBox. Так как размеры CropBox PDF могут быть меньше, чем размеры его 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();
}
0 голосов
/ 06 апреля 2011

Вы сделали две ошибки:

  1. Вы предполагаете, что страницы не повернуты, но они могут быть: 90, 180, 270. Обратите внимание, что я никогда не видел страницу 180, но это законно. При рисовании на повернутой странице вы должны учитывать это вращение при рисовании на ней. Приколы с матрицами преобразования.

  2. Вы предполагаете, что нижний левый угол страницы (без поворота) равен 0,0. Вы основываете свои измерения на ширине и высоте страницы (близко), но не корректируете ни для какого смещения в этом левом нижнем углу.

Существует три способа создания альбомной страницы:
11 "x8.5"
8,5 "x11" при повороте на 90 градусов
8,5 "x11" при вращении на 270 градусов

Технически, 4-й способ - построить 11x8.5 @ 180, но любой, кто пишет такой код, должен быть наказан. Много.

Существует множество вопросов SO, в которых подробно описывается, как обращаться с ротацией страниц. Судя по вашему коду, я бы сказал, что вы довольно быстро поймете, что такое.

...