Объединение нескольких документов в один PDF документ в .NET
25 ноября 2020
/// <summary> /// Merges several documents (PDF, TIFF, PNG, DOCX, ...) to single PDF document. /// </summary> /// <param name="outputFilename">The output PDF filename.</param> /// <param name="inputFilenames">The filenames of input documents.</param> public static void MergeDocuments(string outputFilename, params string[] inputFilenames) { if (inputFilenames == null || inputFilenames.Length < 1) throw new System.ArgumentOutOfRangeException("inputFilenames"); // define style of index page string indexPageFontName = "Arial"; float indexPageFontSize = 14; System.Drawing.PointF indexPagePadding = new System.Drawing.PointF(indexPageFontSize * 2, indexPageFontSize * 4); float indexPageLineSpacing = indexPageFontSize * 0.8f; System.Drawing.Color linkFontColor = System.Drawing.Color.Blue; System.Drawing.Color titleFontColor = System.Drawing.Color.Black; // create output PDF document using (Vintasoft.Imaging.Pdf.PdfDocument document = new Vintasoft.Imaging.Pdf.PdfDocument(outputFilename, Vintasoft.Imaging.Pdf.PdfFormat.Pdf_17)) { // create bookmark collection document.Bookmarks = new Vintasoft.Imaging.Pdf.Tree.PdfBookmarkCollection(document); // create index page Vintasoft.Imaging.Pdf.Tree.PdfPage indexPage = new Vintasoft.Imaging.Pdf.Tree.PdfPage(document, Vintasoft.Imaging.PaperSizeKind.A4); // add index page to PDF document document.Pages.Add(indexPage); // create annotation collection for index page indexPage.Annotations = new Vintasoft.Imaging.Pdf.Tree.Annotations.PdfAnnotationList(document); // create font and text brush Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont font; using (System.IO.Stream fontProgramStream = document.FontProgramsController.GetTrueTypeFontProgram(indexPageFontName)) font = document.FontManager.CreateCIDFontFromTrueTypeFont(fontProgramStream); Vintasoft.Imaging.Pdf.Drawing.PdfBrush fontBrush = new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(linkFontColor); // open PdfGraphics on index page using (Vintasoft.Imaging.Pdf.Drawing.PdfGraphics indexGraphics = indexPage.GetGraphics()) { // start location in index page System.Drawing.PointF indexPageTextLocation = indexPage.MediaBox.Location; indexPageTextLocation.X += indexPagePadding.X; indexPageTextLocation.Y += indexPage.MediaBox.Height - indexPagePadding.Y - indexPageFontSize * 2; // draw index title System.Drawing.RectangleF titleRect = new System.Drawing.RectangleF( indexPageTextLocation.X, indexPageTextLocation.Y, indexPage.MediaBox.Width - indexPageTextLocation.X * 2, indexPageFontSize * 2 * 2); indexGraphics.DrawString( "Example: Create PDF document from several documents.", font, indexPageFontSize * 2, new Vintasoft.Imaging.Pdf.Drawing.PdfBrush(titleFontColor), titleRect, Vintasoft.Imaging.Pdf.Drawing.PdfContentAlignment.Center, true); indexPageTextLocation.Y -= indexPageLineSpacing * 4; // location of page number float indexPageNumberLocationX = indexPage.MediaBox.X + indexPage.MediaBox.Width - indexPagePadding.X; // for each input file foreach (string inputFilename in inputFilenames) { int firstPageIndex = document.Pages.Count; // create bookmark Vintasoft.Imaging.Pdf.Tree.PdfBookmark fileBookmark = new Vintasoft.Imaging.Pdf.Tree.PdfBookmark(document, System.IO.Path.GetFileName(inputFilename)); fileBookmark.Destination = new Vintasoft.Imaging.Pdf.Tree.PdfDestinationFit(document, firstPageIndex); document.Bookmarks.Add(fileBookmark); // if input image file is PDF document if (System.IO.Path.GetExtension(inputFilename).ToUpper() == ".PDF") { // open input PDF document using (Vintasoft.Imaging.Pdf.PdfDocument inputDoc = new Vintasoft.Imaging.Pdf.PdfDocument(inputFilename)) { // add pages from input PDF document to the output document, also add bookmark tree from input PDF document to the 'fileBookmark' document.AddDocument(inputDoc, fileBookmark.ChildBookmarks); } } else { // add images from input image file to the output document Vintasoft.Imaging.ImageCollection images = new Vintasoft.Imaging.ImageCollection(); images.Add(inputFilename); // if input file is vector document (DOCX, ...) if (images[0].IsVectorImage) { // create temp stream using (System.IO.MemoryStream tempStream = new System.IO.MemoryStream()) { // create PDF encoder using (Vintasoft.Imaging.Codecs.Encoders.PdfEncoder encoder = new Vintasoft.Imaging.Codecs.Encoders.PdfEncoder()) { // convert input file to temporary PDF document images.SaveSync(tempStream, encoder); // add pages from temp PDF document to the output document using (Vintasoft.Imaging.Pdf.PdfDocument tempDoc = new Vintasoft.Imaging.Pdf.PdfDocument(tempStream)) document.AddDocument(tempDoc, fileBookmark.ChildBookmarks); } } } else { // encode input file as image-only PDF pages foreach (Vintasoft.Imaging.VintasoftImage image in images) AddImageToPdfDocument(document, image); } images.ClearAndDisposeItems(); } // if 'fileBookmark' does not have children bookmarks AND added document is multipage document, i.e. // input document is PDF document without bookmarks OR input document is NOT PDF document if (fileBookmark.ChildBookmarks.Count == 0 && (document.Pages.Count - firstPageIndex) > 1) { // for each page in input document for (int i = firstPageIndex; i < document.Pages.Count; i++) { // create bookmark for page Vintasoft.Imaging.Pdf.Tree.PdfBookmark pageBookmark = new Vintasoft.Imaging.Pdf.Tree.PdfBookmark(document, string.Format("Page {0}", i - firstPageIndex + 1)); // set destination for page bookmark pageBookmark.Destination = new Vintasoft.Imaging.Pdf.Tree.PdfDestinationFit(document, i); // add page bookmark to the file bookmark fileBookmark.ChildBookmarks.Add(pageBookmark); } } // draw link text on index page System.Drawing.RectangleF indexRect = DrawIndexString( indexGraphics, System.IO.Path.GetFileName(inputFilename), font, indexPageFontSize, fontBrush, indexPageTextLocation, firstPageIndex + 1, indexPageNumberLocationX); // add link annotation on link text Vintasoft.Imaging.Pdf.Tree.Annotations.PdfLinkAnnotation linkAnnotation = new Vintasoft.Imaging.Pdf.Tree.Annotations.PdfLinkAnnotation(document.Pages[firstPageIndex], fileBookmark.Destination); linkAnnotation.Rectangle = indexRect; linkAnnotation.HighlightingMode = Vintasoft.Imaging.Pdf.Tree.Annotations.PdfAnnotationHighlightingMode.Invert; indexPage.Annotations.Add(linkAnnotation); // move to next link indexPageTextLocation.Y -= indexRect.Height + indexPageLineSpacing; } } // subset font that is used for text drawing document.FontManager.PackFont(font); // save chages in the output document document.SaveChanges(); } } /// <summary> /// Draws the index string. /// </summary> /// <param name="graphics">The graphics.</param> /// <param name="text">The text.</param> /// <param name="font">The font.</param> /// <param name="fontSize">Size of the font.</param> /// <param name="brush">The brush.</param> /// <param name="textLocation">The text location.</param> /// <param name="pageNumber">The page number.</param> /// <param name="pageNumberLocationX">The page number location at X-axis.</param> /// <returns>Rectangle, where text was drawn.</returns> private static System.Drawing.RectangleF DrawIndexString( Vintasoft.Imaging.Pdf.Drawing.PdfGraphics graphics, string text, Vintasoft.Imaging.Pdf.Tree.Fonts.PdfFont font, float fontSize, Vintasoft.Imaging.Pdf.Drawing.PdfBrush brush, System.Drawing.PointF textLocation, int pageNumber, float pageNumberLocationX) { // draw text float width, height; graphics.DrawString(text, font, fontSize, brush, textLocation); graphics.MeasureString(text, font, fontSize, out width, out height); // draw dots float lineWidth = 1; System.Drawing.PointF pageNumberLocation = new System.Drawing.PointF(pageNumberLocationX, textLocation.Y); using (Vintasoft.Imaging.Pdf.Drawing.PdfPen pen = new Vintasoft.Imaging.Pdf.Drawing.PdfPen(brush.Color, lineWidth)) { pen.DashPattern = new float[] { lineWidth, lineWidth * 2 }; graphics.DrawLine(pen, new System.Drawing.PointF(textLocation.X + width, textLocation.Y), pageNumberLocation); } // draw page number graphics.DrawString(pageNumber.ToString(), font, fontSize, brush, pageNumberLocation); graphics.MeasureString(pageNumber.ToString(), font, fontSize, out width, out height); return new System.Drawing.RectangleF(textLocation.X, textLocation.Y, pageNumberLocation.X - textLocation.X + width, height); } /// <summary> /// Adds the image to PDF document. /// </summary> /// <param name="document">The document.</param> /// <param name="image">The image.</param> private static void AddImageToPdfDocument( Vintasoft.Imaging.Pdf.PdfDocument document, Vintasoft.Imaging.VintasoftImage image) { // select compression Vintasoft.Imaging.Pdf.PdfCompression compression; Vintasoft.Imaging.Pdf.PdfCompressionSettings compressionSettings; if (image.BitsPerPixel == 1) compression = Vintasoft.Imaging.Pdf.PdfCompression.CcittFax; else if (image.PixelFormat == Vintasoft.Imaging.PixelFormat.Indexed8) compression = Vintasoft.Imaging.Pdf.PdfCompression.Zip; else compression = Vintasoft.Imaging.Pdf.PdfCompression.Jpeg; // create compression settings compressionSettings = new Vintasoft.Imaging.Pdf.PdfCompressionSettings(); compressionSettings.JpegQuality = 75; // add page document.Pages.Add(image, compression, compressionSettings); }