Combinar varios documentos en un solo Documento PDF en .NET
Categoría del blog: PDF ; .NET
25.11.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);
}