itextsharp 5 Writer. DirectContent создает файл на 50% меньше, чем PDFStamper - PullRequest
0 голосов
/ 12 мая 2019

Я действительно хотел бы использовать более новый подход - использование PDFStamper вместо более старого подхода (PdfWriter.GetInstance ... writer.DirectContent), но размер файла PDF, созданного с использованием более старого метода, в два раза меньше, чем при использованииновый подход.Есть ли что-то, чего мне не хватает между двумя подходами?

//Old way using PdfWriter.GetInstance... writer.DirectContent
        public static void AddHeaderTextLayer()
        {
            string HdrLeft = string.Empty;
            string HdrRight = string.Empty;
            string PageHdrName = "XHdr";
            string NoOfPagesPadded = string.Empty;
            string PageNoPadded = string.Empty;
            int xLeft = 30;
            int xRight = 100;
            int xTop = 15;
            string filename = "4_20140909.pdf";

            PdfReader reader = new PdfReader(@"C:\!stuff\Junk\ChemWatchPDF\" + filename); // input file

            using (var fileStream = new FileStream(@"C:\!stuff\Junk\ChemWatchPDF\" + filename.Replace(".pdf", "") + "_withHdrLTp.pdf", FileMode.Create, FileAccess.Write))
            {
                var document = new Document(reader.GetPageSizeWithRotation(1));
                var writer = PdfWriter.GetInstance(document, fileStream);
                document.Open();

                for (var i = 1; i <= reader.NumberOfPages; i++)
                {
                    Rectangle pageRect = reader.GetPageSize(i);
                    document.NewPage();

                    var baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
                    var importedPage = writer.GetImportedPage(reader, i);
                    var contentByte = writer.DirectContent;

                    contentByte.AddTemplate(importedPage, 0, 0);
                    string SDSNo = "12345678";
                    HdrLeft = $"Company MSDS# {SDSNo}";

                    NoOfPagesPadded = (reader.NumberOfPages.ToString());
                    PageNoPadded = i.ToString();
                    HdrRight = $" Page {PageNoPadded} of {NoOfPagesPadded}";

                    contentByte.BeginLayer(new PdfLayer(PageHdrName + i.ToString(), writer));

                    contentByte.BeginText();
                    contentByte.SetFontAndSize(baseFont, 10);
                    contentByte.SetColorFill(LabColor.RED);
                    contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrLeft, pageRect.Left + xLeft, pageRect.Top - xTop, 0);
                    contentByte.EndText();

                    contentByte.BeginText();
                    contentByte.SetFontAndSize(baseFont, 10);
                    contentByte.SetColorFill(LabColor.RED);
                    contentByte.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrRight, pageRect.Right - xRight, pageRect.Top - xTop, 0);
                    contentByte.EndText();

                    contentByte.EndLayer();
                }
                document.Close();
                writer.Close();
            }
        }

// New way using PDFStamper
       public void Add()
        {
            BaseFont baseFont = BaseFont.CreateFont(BaseFont.HELVETICA_BOLD, Encoding.ASCII.EncodingName, false);
            string outPutFile = string.Empty;
            var SingleLine = string.Empty;
            string HdrLeft = string.Empty;
            string HdrRight = string.Empty;
            string PageHdrName = "xHdr";
            string NoOfPagesPadded = string.Empty;
            string PageNoPadded = string.Empty;
            int xLeft = 30;
            int xRight = 100;
            int xTop = 15;
            string filename = "4_20140909.pdf";
            outPutFile = @"C:\!stuff\Junk\ChemWatchPDF\" + filename.Replace(".pdf", "") + "_withHdrLTStamp.pdf";

            using (var newPDF = new FileStream(outPutFile, FileMode.Create, FileAccess.ReadWrite))
            {
                PdfReader reader = new PdfReader(@"C:\!stuff\Junk\ChemWatchPDF\" + filename); // input file
                PdfStamper pdfStamper = new PdfStamper(reader, newPDF);
                PdfLayer wmLayer = new PdfLayer(PageHdrName, pdfStamper.Writer);
                for (int page = 1; page <= reader.NumberOfPages; page++)
                {
                    PdfContentByte pdfContent = pdfStamper.GetOverContent(page);
                    Rectangle pageRect = reader.GetPageSize(page);
                    string SDSNo = "12345678";
                    HdrLeft = $"Company MSDS# {SDSNo}";
                    NoOfPagesPadded = (reader.NumberOfPages.ToString());
                    PageNoPadded = page.ToString();

                    HdrRight = $"Page {PageNoPadded} of {NoOfPagesPadded}";
                    pdfContent.BeginLayer(wmLayer);

                    pdfContent.BeginText();
                    pdfContent.SetFontAndSize(baseFont, 10);
                    pdfContent.SetColorFill(LabColor.RED);
                    pdfContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrLeft, pageRect.Left + xLeft, pageRect.Top - xTop, 0);
                    pdfContent.EndText();

                    pdfContent.BeginText();
                    pdfContent.SetFontAndSize(baseFont, 10);
                    pdfContent.SetColorFill(LabColor.RED);
                    pdfContent.ShowTextAligned(PdfContentByte.ALIGN_LEFT, HdrRight, pageRect.Right - xRight, pageRect.Top - xTop, 0);
                    pdfContent.EndText();

                    pdfContent.EndLayer();
                }
                pdfStamper.Close();
            }
        }
    }
}

1 Ответ

1 голос
/ 14 мая 2019

Ваша штампованная копия (вывод "более нового подхода") содержит структурное дерево , которое, как я предполагаю, происходит из исходного документа. Он теряется в выводе «старого подхода».

Структура дерева описывает логическую структуру документа. Это увеличивает доступность документа, и его присутствие становится юридическим требованием во все большем количестве стран и контекстов. Таким образом, выбрасывать дерево структуры вообще - плохая идея.

Само дерево структуры состоит из очень большого количества маленьких косвенных объектов, в случае с вашим PDF-файлом существует более 1000 косвенных объектов размером примерно 90 КБ. Кроме того, каждый косвенный объект требует 20-байтовой записи перекрестных ссылок, которая в вашем случае составляет почти 20 КБ. Это объясняет почти всю разницу в размере 111 КБ между двумя выходами.

Если вы используете потоки объектов и потоки перекрестных ссылок, дерево структуры обычно может быть достаточно хорошо сжато. Таким образом, я бы предложил вам активировать полное сжатие в iText, что заставляет его использовать потоки объектов и потоки перекрестных ссылок:

PdfStamper pdfStamper = new PdfStamper(reader, newPDF);
pdfStamper.SetFullCompression();
pdfStamper.Writer.CompressionLevel = 9;

Просто обработав ваш большой PDF парой PdfReader/PdfStamper с этими настройками без каких-либо других манипуляций, я уменьшил размер вашего файла с 234 КБ до 133 КБ.


Кстати, вы называете подход с PdfWriter, а страница импортирует «старый путь», а подход с PdfStamper - «новый путь». На самом деле класс PdfStamper существует в iText по крайней мере с 2003 года! Так что это не совсем старый против новый ...

...