问题:
我有一些包含 3 个不同 PDF 字节数组的代码,并将它们合并。此代码运行正常。有些人遇到问题是因为每一个 PDF 都被视为一个完整的页面(如果打印),即使上面只有大约 4 英寸的内容,从而在垂直方向上留下 7 英寸的空白。然后中间文档被插入,并可能在末尾没有垂直空白。然后页脚也放在自己的页面上。
以下为代码:
byte[] Bytes = rv.LocalReport.Render("PDF", null, out MimeType, out Encoding, out Extension, out StreamIDs, out Warnings); List<byte[]> MergeSets = // 在此代码之前填充 // 将任何其他页面附加到此主要信件 if (MergeSets.Count > 0) { MemoryStream ms = new MemoryStream(); Document document = new Document(); PdfCopy copy = new PdfCopy(document, ms); document.Open(); PdfImportedPage page; PdfReader reader = new PdfReader(Bytes); // 读取生成的正文信 int pages = reader.NumberOfPages; for (int i = 0; i < pages;) { page = copy.GetImportedPage(reader, ++i); copy.AddPage(page); } // 遍历所有正文信的页面 // 现在附加合并集 foreach (byte[] ba in MergeSets) { reader = new PdfReader(ba); pages = reader.NumberOfPages; for (int i = 0; i < pages;) { page = copy.GetImportedPage(reader, ++i); copy.AddPage(page); } // 遍历当前合并集中的所有页面 } // 遍历数据集中所有内容 document.Close(); ServerSaved = SaveGeneratedLetter(ms.GetBuffer(), DateTime.Now.Year, hl.LetterName, SaveName); } // 如果有待合并的任何内容
问题:
在我合并每个页面时,是否有办法剪切/删除/删除每个 PDF 末尾的垂直空白,使其显示为一个无缝文档?
更新:
以下是示例.pdf 文件,我正在试图合并它们。
标题,正文,页脚
更新 2:使用答案:
我已经将 @mkl 的代码转换为 C#,如下所示。
该工具类:
public class PdfVeryDenseMergeTool { private Rectangle PageSize; private float TopMargin; private float BottomMargin; private float Gap; private Document Document = null; private PdfWriter Writer = null; private float YPosition = 0; public PdfVeryDenseMergeTool(Rectangle size, float top, float bottom, float gap) { this.PageSize = size; this.TopMargin = top; this.BottomMargin = bottom; this.Gap = gap; } // PdfVeryDenseMergeTool public void Merge(MemoryStream outputStream, List<PdfReader> inputs) { try { this.OpenDocument(outputStream); foreach (PdfReader reader in inputs) { this.Merge(reader); } // 遍历待合并的 PDF 文件 } finally { this.CloseDocument(); } // try-catch-finally } // Merge public void OpenDocument(MemoryStream outputStream) { this.Document = new Document(PageSize, 36, 36, this.TopMargin, this.BottomMargin); this.Writer = PdfWriter.GetInstance(Document, outputStream); this.Document.Open(); this.NewPage(); } // OpenDocument public void CloseDocument() { try { this.Document.Close(); } finally { this.Document = null; this.Writer = null; this.YPosition = 0; } // try-finally } // CloseDocument public void NewPage() { this.Document.NewPage(); this.YPosition = PageSize.GetTop(this.TopMargin); } // Merge public void Merge(PdfReader reader) { PdfReaderContentParser parser = new PdfReaderContentParser(reader); for (int pageIndex = 1; pageIndex <= reader.NumberOfPages; pageIndex++) { this.Merge(reader, parser, pageIndex); } // 遍历当前 PDF 的所有页面 } // Merge public void Merge(PdfReader reader, PdfReaderContentParser parser, int pageIndex) { PdfImportedPage importedPage = Writer.GetImportedPage(reader, pageIndex); PdfContentByte directContent = Writer.DirectContent; PageVerticalAnalyzer finder = parser.ProcessContent(pageIndex, new PageVerticalAnalyzer()); if (finder.VerticalFlips.Count < 2) return; Rectangle pageSizeToImport = reader.GetPageSize(pageIndex); int startFlip = finder.VerticalFlips.Count - 1; bool first = true; while (startFlip > 0) { if (!first) this.NewPage(); float freeSpace = this.YPosition - PageSize.GetBottom(BottomMargin); int endFlip = startFlip + 1; while ((endFlip > 1) && (finder.VerticalFlips[startFlip] - finder.VerticalFlips[endFlip - 2] < freeSpace)) endFlip -= 2; if (endFlip < startFlip) { float height = finder.VerticalFlips[startFlip] - finder.VerticalFlips[endFlip]; directContent.SaveState(); directContent.Rectangle(0, this.YPosition - height, pageSizeToImport.Width, height); directContent.Clip(); directContent.NewPath(); this.Writer.DirectContent.AddTemplate(importedPage, 0, this.YPosition - (finder.VerticalFlips[startFlip] - pageSizeToImport.Bottom)); directContent.RestoreState(); this.YPosition -= height + this.Gap; startFlip = endFlip - 1; } else if (!first) { throw new ArgumentException(string.Format("Page {0} content too large", pageIndex)); } // if first = false; } // while } // Merge } // PdfVeryDenseMergeTool
渲染侦听器类:
更新 3:修复了 1 行代码,现在可以正常工作:请参见代码中的注释
public class PageVerticalAnalyzer : IRenderListener { public PageVerticalAnalyzer() { } public List<float> VerticalFlips = new List<float>(); public void AddVerticalUseSection(float from, float to) { if (to < from) { float temp = to; to = from; from = temp; } int i = 0; int j = 0; for (i = 0; i < VerticalFlips.Count; i++) { float flip = VerticalFlips[i]; if (flip < from) continue; for (j = i; j < VerticalFlips.Count; j++) { flip = VerticalFlips[j]; if (flip < to) continue; break; } break; } // 遍历所有垂直翻转 bool fromOutsideInterval = i % 2 == 0; bool toOutsideInterval = j % 2 == 0; while (j-- > i) VerticalFlips.RemoveAt(j); // 这是存在问题的代码行,只使用了 .Remove(j) if (toOutsideInterval) VerticalFlips.Insert(i, to); if (fromOutsideInterval) VerticalFlips.Insert(i, from); } // AddVerticalUseSection public void BeginTextBlock() { /* Do nothing */ } public void EndTextBlock() { /* Do nothing */ } public void RenderImage(ImageRenderInfo renderInfo) { Matrix ctm = renderInfo.GetImageCTM(); List<float> YCoords = new List<float>(4) { 0, 0, 0, 0 }; for (int x = 0; x < 2; x++) { for (int y = 0; y < 2; y++) { Vector corner = new Vector(x, y, 1).Cross(ctm); YCoords[2 * x + y] = corner[Vector.I2]; } } YCoords.Sort();
以上是合并PDF时如何消除空白?的详细内容。更多信息请关注PHP中文网其他相关文章!