Samples Overview
Content Addition | Document Setup | Imposition | Information Extraction | Content Modification | Annotations and Form Fields
Content Addition
Add barcode to PDF
Generate and add a barcode at a specified position on the first page of a PDF document.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create file stream
using (Stream fontStream = new FileStream(fontPath, FileMode.Open, FileAccess.Read))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Create embedded font in output document
Font font = outDoc.CreateFont(fontStream, true);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
if (currentPageNumber == 1)
{
// Add barcode to first page
AddBarcode(outDoc, outPage, barcode, font, 50);
}
// Add page to document
outDoc.Pages.Add(outPage);
currentPageNumber++;
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddBarcode(Document outputDoc, Page outPage, string barcode,
Font font, double fontSize)
{
// Create content generator
using (ContentGenerator gen = new ContentGenerator(outPage.Content, false))
{
// Create text object
Text barcodeText = outputDoc.CreateText();
// Create text generator
using (TextGenerator textGenerator = new TextGenerator(barcodeText, font,
fontSize, null))
{
// Calculate position
Point position = new Point
{
X = outPage.Size.Width - (textGenerator.GetWidth(barcode) + Border),
Y = outPage.Size.Height - (fontSize * (font.Ascent + font.Descent) + Border)
};
// Move to position
textGenerator.MoveTo(position);
// Add given barcode string
textGenerator.ShowLine(barcode);
}
// Paint the positioned barcode text
gen.PaintText(barcodeText);
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
// Create file stream
FileStream fontStream = new FileStream(fontPath, "r");
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Create embedded font in output document
Font font = outDoc.createFont(fontStream, true);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (int i = 0; i < inDoc.getPages().size(); i++) {
Page inPage = inDoc.getPages().get(i);
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
if (i == 0) {
// Add barcode to first page
addBarcode(outDoc, outPage, barcode, font, 50);
}
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addBarcode(Document outputDoc, Page outPage, String barcode, Font font, double fontSize)
throws ErrorCodeException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text barcodeText = outputDoc.createText();
// Create a text generator
TextGenerator textgenerator = new TextGenerator(barcodeText, font, fontSize, null);
// Calculate position
Point position = new Point(outPage.getSize().width - (textgenerator.getWidth(barcode) + Border),
outPage.getSize().height - (fontSize * (font.getAscent() + font.getDescent()) + Border));
// Move to position
textgenerator.moveTo(position);
// Add given barcode string
textgenerator.showLine(barcode);
// Close text generator
textgenerator.close();
// Paint the positioned barcode text
generator.paintText(barcodeText);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create file stream
pFontStream = _tfopen(szFontPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pFontStream, _T("Failed to open font file."));
PdfCreateFILEStreamDescriptor(&fontDescriptor, pFontStream, 0);
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
pFont = PdfDocumentCreateFont(pOutDoc, &fontDescriptor, 1);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
PdfPageGetSize(pOutPage, &size);
if (iPage == 0)
{
// Add barcode to first page
if (addBarcode(pOutDoc, pOutPage, szBarcode, pFont, 50) == 1)
{
goto cleanup;
}
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addBarcode(TPdfDocument* pOutDoc, TPdfPage* pOutPage, TCHAR* szBarcode, TPdfFont* pFont, double dFontSize)
{
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
TPdfText* pBarcodeText = NULL;
TPdfTextGenerator* pTextGenerator = NULL;
pContent = PdfPageGetContent(pOutPage);
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create text object
pBarcodeText = PdfDocumentCreateText(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pBarcodeText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create text generator
pTextGenerator = PdfNewTextGenerator(pBarcodeText, pFont, dFontSize, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate position
TPdfPoint position;
double dTextWidth = PdfTextGeneratorGetWidth(pTextGenerator, szBarcode);
GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dFontAscent = PdfFontGetAscent(pFont);
GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontAscent, _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dFontDescent = PdfFontGetDescent(pFont);
GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontDescent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
position.dX = size.dWidth - (dTextWidth + dBorder);
position.dY = size.dHeight - (dFontSize * (dFontAscent + dFontDescent) + dBorder);
// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorMoveTo(pTextGenerator, &position), _T("Failed to move to position %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add given barcode string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorShowLine(pTextGenerator, szBarcode), _T("Failed to add barcode string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Close text generator
if (pTextGenerator != NULL)
PdfClose(pTextGenerator);
// Paint the positioned barcode text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintText(pGenerator, pBarcodeText), _T("Failed to paint the positioned barcode text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pBarcodeText != NULL)
PdfClose(pBarcodeText);
if (pContent != NULL)
PdfClose(pContent);
if (pGenerator != NULL)
PdfClose(pGenerator);
return iReturnValue;
}
Add Data Matrix to PDF
Add a two-dimensional barcode from an existing image on the first page of a PDF document.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
if (currentPageNumber == 1)
{
// Add data matrix as image to first page
AddDataMatrix(outDoc, outPage, datamatrixPath);
}
// Add page to document
outDoc.Pages.Add(outPage);
currentPageNumber++;
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddDataMatrix(Document document, Page page, string datamatrixPath)
{
// Create content generator
using (ContentGenerator generator = new ContentGenerator(page.Content, false))
// Import data matrix
using (Stream inMatrix = new FileStream(datamatrixPath, FileMode.Open, FileAccess.Read))
{
// Create image object for data matrix
Image datamatrix = document.CreateImage(inMatrix);
// Data matrix size
double datamatrixSize = 85;
// Calculate Rectangle for data matrix
Rectangle rect = new Rectangle
{
Left = Border,
Bottom = page.Size.Height - (datamatrixSize + Border),
Right = datamatrixSize + Border,
Top = page.Size.Height - Border
};
// Paint image of data matrix into the specified rectangle
generator.PaintImage(datamatrix, rect);
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (int i = 0; i < inDoc.getPages().size(); i++) {
Page inPage = inDoc.getPages().get(i);
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
if (i == 0) {
// Add image on the first page
addDatamatrix(outDoc, outPage, datamatrixPath);
}
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addDatamatrix(Document document, Page page, String datamatrixPath)
throws ErrorCodeException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(page.getContent(), false);
// Import data matrix
FileStream inMatrix = new FileStream(datamatrixPath, "r")) {
// Create image object for data matrix
Image datamatrix = document.createImage(inMatrix);
// Data matrix size
double datamatrixSize = 85;
// Calculate Rectangle for data matrix
Rectangle rect = new Rectangle(Border, page.getSize().height - (datamatrixSize + Border),
datamatrixSize + Border, page.getSize().height - Border);
// Paint image of data matrix into the specified rectangle
generator.paintImage(datamatrix, rect);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Create embedded font in output document
pFont = PdfDocumentCreateSystemFont(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
PdfPageGetSize(pOutPage, &size);
if (iPage == 0)
{
//Add text on first page
if (addDataMatrix(pOutDoc, pOutPage, szDatamatrixPath) == 1)
{
goto cleanup;
}
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addDataMatrix(TPdfDocument* pOutDoc, TPdfPage* pOutPage, TCHAR* szDataMatrixPath)
{
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
TPdfStreamDescriptor datamatrixDescriptor;
FILE* pDatamatrixStream = NULL;
TPdfImage* pDatamatrix = NULL;
pContent = PdfPageGetContent(pOutPage);
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Import data matrix
pDatamatrixStream = _tfopen(szDataMatrixPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pDatamatrixStream, _T("Failed to open data matrix file \"%s\".\n"), szDataMatrixPath);
PdfCreateFILEStreamDescriptor(&datamatrixDescriptor, pDatamatrixStream, 0);
// Create image object for data matrix
pDatamatrix = PdfDocumentCreateImage(pOutDoc, &datamatrixDescriptor);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pDatamatrix, _T("Failed to create image object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Data matrix size
double dDatamatrixSize = 85.0;
// Calculate Rectangle for data matrix
TPdfRectangle rect;
rect.dLeft = dBorder;
rect.dBottom = size.dHeight - (dDatamatrixSize + dBorder);
rect.dRight = dDatamatrixSize + dBorder;
rect.dTop = size.dHeight - dBorder;
// Paint image of data matrix into the specified rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintImage(pGenerator, pDatamatrix, &rect), _T("Failed to paint data matrix into the specified rectangle. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pContent != NULL)
PdfClose(pContent);
if (pGenerator != NULL)
PdfClose(pGenerator);
return iReturnValue;
}
Add image to PDF
Place an image with a specified size at a specific location of a page.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
if (currentPageNumber == pageNumber)
{
// Add image on chosen page
AddImage(outDoc, outPage, imagePath, 150, 150);
}
// Add page to output document
outDoc.Pages.Add(outPage);
currentPageNumber++;
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddImage(Document document, Page page, string imagePath, double x, double y)
{
// Create content generator
using (ContentGenerator generator = new ContentGenerator(page.Content, false))
// Load image from input path
using (Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
{
// Create image object
Image image = document.CreateImage(inImage);
double resolution = 150;
// Calculate rectangle for image
Rectangle rect = new Rectangle
{
Left = x,
Bottom = y,
Right = x + image.Width * 72 / resolution,
Top = y + image.Height * 72 / resolution
};
// Paint image into the specified rectangle
generator.PaintImage(image, rect);
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (int i = 0; i < inDoc.getPages().size(); i++) {
Page inPage = inDoc.getPages().get(i);
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
if (i == (pageNumber - 1)) {
// Add image on chosen page
addImage(outDoc, outPage, imagePath, 150, 150);
}
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addImage(Document document, Page outPage, String imagePath, double x, double y)
throws ErrorCodeException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
// Load image from input path
FileStream inImage = new FileStream(imagePath, "r")) {
// Create image object
Image image = document.createImage(inImage);
double resolution = 150;
// Calculate rectangle for image
Rectangle rect = new Rectangle(x, y, x + image.getWidth() * 72 / resolution,
y + image.getHeight() * 72 / resolution);
// Paint image into the specified rectangle
generator.paintImage(image, rect);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Create embedded font in output document
pFont = PdfDocumentCreateSystemFont(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 1; iPage <= PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage - 1);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
PdfPageGetSize(pOutPage, &size);
if (iPage == iPageNumber)
{
//Add text on first page
if (addImage(pOutDoc, pOutPage, szImagePath, 150, 150) == 1)
{
goto cleanup;
}
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addImage(TPdfDocument* pOutDoc, TPdfPage* pOutPage, TCHAR* szImagePath, double x, double y)
{
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
TPdfStreamDescriptor imageDescriptor;
FILE* pImageStream = NULL;
TPdfImage* pImage = NULL;
pContent = PdfPageGetContent(pOutPage);
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
// Load image from input path
pImageStream = _tfopen(szImagePath, _T("rb"));
PdfCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);
// Create image object
pImage = PdfDocumentCreateImage(pOutDoc, &imageDescriptor);
double dResolution = 150.0;
double dImageWidth = PdfImageGetWidth(pImage);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dImageWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dImageHeight = PdfImageGetHeight(pImage);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dImageHeight, _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate Rectangle for data matrix
TPdfRectangle rect;
rect.dLeft = x;
rect.dBottom = y;
rect.dRight = x + dImageWidth * 72 / dResolution;
rect.dTop = y + dImageHeight * 72 / dResolution;
// Paint image into the specified rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintImage(pGenerator, pImage, &rect), _T("Failed to paint image. to specified rectangle. %s(ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pContent != NULL)
PdfClose(pContent);
if (pGenerator != NULL)
PdfClose(pGenerator);
return iReturnValue;
}
Add image mask to PDF
Place a rectangular image mask at a specified location of a page. The image mask is a stencil mask to fill or mask out the image per pixel.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Get the device color space
ColorSpace colorSpace = outDoc.CreateDeviceColorSpace(DeviceColorSpaceType.RGB);
// Create paint object
paint = outDoc.CreateSolidPaint(colorSpace, 1.0, 0.0, 0.0);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
if (currentPageNumber == 1)
{
// Add image mask
AddImageMask(outDoc, outPage, imageMaskPath, 250, 150);
}
// Add page to document
outDoc.Pages.Add(outPage);
currentPageNumber++;
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddImageMask(Document document, Page outPage, string imagePath,
double x, double y)
{
// Create content generator
using (ContentGenerator generator = new ContentGenerator(outPage.Content, false))
// Load image from input path
using (Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
{
// Create image mask object
ImageMask imageMask = document.CreateImageMask(inImage);
double resolution = 150;
// Calculate rectangle for image
Rectangle rect = new Rectangle
{
Left = x,
Bottom = y,
Right = x + imageMask.Width * 72 / resolution,
Top = y + imageMask.Height * 72 / resolution
};
// Paint image mask into the specified rectangle
generator.PaintImageMask(imageMask, rect, paint);
}
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Get the device color space
ColorSpace colorSpace = outDoc.createDeviceColorSpace(DeviceColorSpaceType.RGB);
// Create paint object
paint = outDoc.createSolidPaint(colorSpace, 1.0, 0.0, 0.0);
// Loop through all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add image mask
addImageMask(outDoc, outPage, imageMaskPath, 250, 150);
// Add page to document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addImageMask(Document document, Page outPage, String imagePath, double x, double y)
throws ErrorCodeException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
// Load image from input path
FileStream inImage = new FileStream(imagePath, "r")) {
// Create image mask object
ImageMask imageMask = document.createImageMask(inImage);
double resolution = 150;
// Calculate rectangle for image
Rectangle rect = new Rectangle(x, y, x + imageMask.getWidth() * 72 / resolution,
y + imageMask.getHeight() * 72 / resolution);
// Paint image mask into the specified rectangle
generator.paintImageMask(imageMask, rect, paint);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
// Get the device color space
TPdfColorSpace* pColorSpace = PdfDocumentCreateDeviceColorSpace(pOutDoc, ePdfColorSpaceRGB);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the device color space. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Chose the RGB color value
double color[] = { 1.0, 0.0, 0.0 };
size_t nColor = sizeof(color) / sizeof(double);
// Create paint object
pPaint = PdfDocumentCreateSolidPaint(pOutDoc, pColorSpace, color, nColor);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int i = 0; i < PdfPageListGetCount(pInPageList); i++)
{
pInPage = PdfPageListGet(pInPageList, i);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add image mask
if (addImageMask(pOutDoc, pOutPage, szImageMaskPath, 250, 150) == 1)
{
goto cleanup;
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addImageMask(TPdfDocument* pOutDoc, TPdfPage* pOutPage, TCHAR* szImageMaskPath, double x, double y)
{
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
FILE* pImageStream = NULL;
TPdfStreamDescriptor imageDescriptor;
TPdfImageMask* pImageMask = NULL;
pContent = PdfPageGetContent(pOutPage);
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Load image from input path
pImageStream = _tfopen(szImageMaskPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pImageStream, _T("Failed to open image mask file \"%s\".\n"), szImageMaskPath);
PdfCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);
// Create image mask object
pImageMask = PdfDocumentCreateImageMask(pOutDoc, &imageDescriptor);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pImageMask, _T("Failed to create image mask obejct. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dResolution = 150.0;
double dImageMaskWidth = PdfImageMaskGetWidth(pImageMask);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dImageMaskWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dImageMaskHeight = PdfImageMaskGetHeight(pImageMask);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dImageMaskHeight, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate Rectangle for image
TPdfRectangle rect;
rect.dLeft = x;
rect.dBottom = y;
rect.dRight = x + dImageMaskWidth * 72 / dResolution;
rect.dTop = y + dImageMaskHeight * 72 / dResolution;
// Paint image mask into the specified rectangle
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintImageMask(pGenerator, pImageMask, &rect, pPaint), _T("Failed to paint image mask. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pContent != NULL)
PdfClose(pContent);
if (pGenerator != NULL)
PdfClose(pGenerator);
return iReturnValue;
}
Add stamp to PDF
Add a semi-transparent stamp text onto each page of a PDF document. Optionally specify the color and the opacity of the stamp.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
font = outDoc.CreateSystemFont("Arial", "Italic", true);
// Get the device color space
ColorSpace colorspace = outDoc.CreateDeviceColorSpace(DeviceColorSpaceType.RGB);
// Create paint object with the choosen RGB color
paint = outDoc.CreateAlphaPaint(colorspace, alpha, 1.0, 0.0, 0.0);
// Define copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyFormFields | CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
// Copy page from input to output
Page outPage = outDoc.CopyPage(inPage, copyOptions);
// Add text to page
AddStamp(outDoc, outPage, stampString);
// Add page to document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddStamp(Document outputDoc, Page outPage, string stampString)
{
// Create content generator and text object
using (ContentGenerator gen = new ContentGenerator(outPage.Content, false))
{
Text text = outputDoc.CreateText();
// Create text generator
using (TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null))
{
// Calculate point and angle of rotation
Point rotationCenter = new Point
{
X = outPage.Size.Width / 2.0,
Y = outPage.Size.Height / 2.0
};
double rotationAngle = Math.Atan2(outPage.Size.Height,
outPage.Size.Width) / Math.PI * 180.0;
// Rotate textinput around the calculated position
Transformation trans = new Transformation();
trans.RotateAround(rotationAngle, rotationCenter);
gen.Transform(trans);
// Calculate position
Point position = new Point
{
X = (outPage.Size.Width - textgenerator.GetWidth(stampString)) / 2.0,
Y = (outPage.Size.Height - font.Ascent * fontSize) / 2.0
};
// Move to position
textgenerator.MoveTo(position);
// Set text rendering
textgenerator.SetRendering(paint, null, false);
// Add given stamp string
textgenerator.ShowLine(stampString);
}
// Paint the positioned text
gen.PaintText(text);
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Create embedded font in output document
font = outDoc.createSystemFont("Arial", "Italic", true);
// Get the device color space
ColorSpace colorSpace = outDoc.createDeviceColorSpace(DeviceColorSpaceType.RGB);
// Choose the RGB color value
double[] color = { 1.0, 0.0, 0.0 };
// Create paint object
paint = outDoc.createAlphaPaint(colorSpace, alpha, color);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop throw all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add text to page
addStamp(outDoc, outPage, stampString);
// Add page to document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addStamp(Document outputDoc, Page outPage, String stampString)
throws ErrorCodeException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text text = outputDoc.createText();
try (// Create text generator
TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
// Calculate point and angle of rotation
Point rotationCenter = new Point(outPage.getSize().width / 2.0, outPage.getSize().height / 2.0);
// Calculate rotation angle
double rotationAngle = Math.atan2(outPage.getSize().height, outPage.getSize().width) / Math.PI * 180.0;
// Rotate text input around the calculated position
Transformation trans = new Transformation();
trans.rotateAround(rotationAngle, rotationCenter);
generator.transform(trans);
// Calculate position
Point position = new Point((outPage.getSize().width - textgenerator.getWidth(stampString)) / 2.0,
(outPage.getSize().height - font.getAscent() * fontSize) / 2.0);
// Move to position
textgenerator.moveTo(position);
// Set text rendering
textgenerator.setRendering(paint, null, false);
// Add given stamp string
textgenerator.showLine(stampString);
}
// Paint the positioned text
generator.paintText(text);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&inDescriptor, pInStream, FALSE);
pInDoc = PdfDocumentOpen(&inDescriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file %s.\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file %s cannot be closed. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Create embedded font in output document
pFont = PdfDocumentCreateSystemFont(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Embedded font cannot be created. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
// Get the device color space
TPdfColorSpace* pColorSpace = PdfDocumentCreateDeviceColorSpace(pOutDoc, ePdfColorSpaceRGB);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the device color space. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Chose the RGB color values
double color[] = { 1.0, 0.0, 0.0 };
size_t nColor = sizeof(color) / sizeof(double);
// Create paint object
pPaint = PdfDocumentCreateAlphaPaint(pOutDoc, pColorSpace, dAlpha, color, nColor);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int i = 0; i < PdfPageListGetCount(pInPageList); i++)
{
// Get a list of pages
pInPage = PdfPageListGet(pInPageList, i);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add stamp to page
if (addStamp(pOutDoc, pOutPage, szStampString, pFont, 50) == 1)
{
goto cleanup;
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addStamp(TPdfDocument* pOutDoc, TPdfPage* pOutPage, TCHAR* szStampString, TPdfFont* pFont, double dFontSize)
{
TPdfContentGenerator* pGenerator = NULL;
TPdfText* pText = NULL;
TPdfTextGenerator* pTextGenerator = NULL;
TPdfTransformation* pTrans = NULL;
TPdfContent* pContent = PdfPageGetContent(pOutPage);
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create text object
pText = PdfDocumentCreateText(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create a text generator
pTextGenerator = PdfNewTextGenerator(pText, pFont, dFontSize, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Get output page size
TPdfSize size;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageGetSize(pOutPage, &size), _T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate point and angle of rotation
TPdfPoint rotationCenter;
rotationCenter.dX = size.dWidth / 2.0;
rotationCenter.dY = size.dHeight / 2.0;
double dRotationAngle = atan2(size.dHeight, size.dWidth) / M_PI * 180.0;
// Rotate textinput around the calculated position
pTrans = PdfNewTransformationIdentity();
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTransformationRotateAround(pTrans, dRotationAngle, &rotationCenter), _T("Failed to rotate textinput around the calculated position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorTransform(pGenerator, pTrans), _T("Failed to modify the current transformation. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate position
TPdfPoint position;
double dTextWidth = PdfTextGeneratorGetWidth(pTextGenerator, szStampString);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dFontAscent = PdfFontGetAscent(pFont);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
position.dX = (size.dWidth - dTextWidth) / 2.0;
position.dY = (size.dHeight - dFontAscent * dFontSize) / 2.0;
// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorMoveTo(pTextGenerator, &position), _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set text rendering
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorSetRendering(pTextGenerator, pPaint, NULL, FALSE), _T("Failed to set rendering. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add given stamp string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorShowLine(pTextGenerator, szStampString), _T("Failed to add stamp. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Close text generator
if (pTextGenerator != NULL)
{
PdfClose(pTextGenerator);
pTextGenerator = NULL;
}
// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintText(pGenerator, pText), _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pTrans != NULL)
PdfClose(pTrans);
if (pTextGenerator != NULL)
PdfClose(pTextGenerator);
if (pText != NULL)
PdfClose(pText);
if (pContent != NULL)
PdfClose(pContent);
if (pGenerator != NULL)
PdfClose(pGenerator);
return iReturnValue;
}
Add text to PDF
Add text at a specified position on the first page of a PDF document.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Create a font
font = outDoc.CreateSystemFont("Arial", "Italic", true);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
if (currentPageNumber == 1)
{
// Add text on first page
AddText(outDoc, outPage, textString);
}
// Add page to document
outDoc.Pages.Add(outPage);
currentPageNumber++;
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddText(Document outputDoc, Page outPage, string textString)
{
// Create content generator and text object
using (ContentGenerator gen = new ContentGenerator(outPage.Content, false))
{
Text text = outputDoc.CreateText();
// Create text generator
using (TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null))
{
// Calculate position
Point position = new Point
{
X = border,
Y = outPage.Size.Height - border - fontSize * font.Ascent
};
// Move to position
textGenerator.MoveTo(position);
// Add given text string
textGenerator.ShowLine(textString);
}
// Paint the positioned text
gen.PaintText(text);
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Create embedded font in output document
font = outDoc.createSystemFont("Arial", "Italic", true);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (int i = 0; i < inDoc.getPages().size(); i++) {
Page inPage = inDoc.getPages().get(i);
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
if (i == 0) {
// Add text on first page
addText(outDoc, outPage, textString);
}
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data (excluding metadata)
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addText(Document outputDoc, Page outPage, String textString)
throws ErrorCodeException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text text = outputDoc.createText();
try (// Create a text generator
TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
// Calculate position
Point position = new Point(border, outPage.getSize().height - border - fontSize * font.getAscent());
// Move to position
textgenerator.moveTo(position);
// Add given text string
textgenerator.showLine(textString);
}
// Paint the positioned text
generator.paintText(text);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Create embedded font in output document
pFont = PdfDocumentCreateSystemFont(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (iPage == 0)
{
//Add text on first page
if (addText(pOutDoc, pOutPage, szTextString, pFont, 15) == 1)
{
goto cleanup;
}
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addText(TPdfDocument* pOutDoc, TPdfPage* pOutPage, TCHAR* szTextString, TPdfFont* pFont, double dFontSize)
{
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
TPdfText* pText = NULL;
TPdfTextGenerator* pTextGenerator = NULL;
pContent = PdfPageGetContent(pOutPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content of output file. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create text object
pText = PdfDocumentCreateText(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create a text generator
pTextGenerator = PdfNewTextGenerator(pText, pFont, dFontSize, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Get output page size
TPdfSize size;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageGetSize(pOutPage, &size), _T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dFontAscent = PdfFontGetAscent(pFont);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate position
TPdfPoint position;
position.dX = dBorder;
position.dY = size.dHeight - dBorder - dFontSize * dFontAscent;
// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorMoveTo(pTextGenerator, &position), _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add given text string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorShowLine(pTextGenerator, szTextString), _T("Failed to add text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Close text generator
if (pTextGenerator != NULL)
PdfClose(pTextGenerator);
// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintText(pGenerator, pText), _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pText != NULL)
PdfClose(pText);
if (pContent != NULL)
PdfClose(pContent);
if (pGenerator != NULL)
PdfClose(pGenerator);
return iReturnValue;
}
Add vector graphic to PDF
Draw a line on an existing PDF page.
// Open input document
using (System.IO.Stream inStream = new System.IO.FileStream(inPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (System.IO.Stream outStream = new System.IO.FileStream(outPath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
// Add a line
AddLine(outDoc, outPage);
// Add page to output document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddLine(Document document, Page page)
{
// Create content generator
using (ContentGenerator generator = new ContentGenerator(page.Content, false))
{
// Create a path
Path path = new Path(InsideRule.EvenOdd);
using (PathGenerator pathGenerator = new PathGenerator(path))
{
// Draw a line diagonally across the page
Size pageSize = page.Size;
pathGenerator.MoveTo(new Point() { X = 10.0, Y = 10.0 });
pathGenerator.LineTo(new Point() { X = pageSize.Width - 10.0, Y = pageSize.Height - 10.0 });
}
// Create a RGB color space
ColorSpace deviceRgbColorSpace = document.CreateDeviceColorSpace(DeviceColorSpaceType.RGB);
// Create a red color
double[] color = new double[] { 1.0, 0.0, 0.0 };
// Create a paint
Paint paint = document.CreateSolidPaint(deviceRgbColorSpace, color);
// Create stroking parameters with given paint and line width
StrokeParams stroke = new StrokeParams() { Paint = paint, LineWidth = 10.0 };
// Draw the path onto the page
generator.PaintPath(path, null, stroke, false);
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add a line
addLine(outDoc, outPage);
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addLine(Document document, Page outPage)
throws ErrorCodeException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create a path
Path path = new Path(InsideRule.EVEN_ODD);
try (// Create a path generator
PathGenerator pathGenerator = new PathGenerator(path)) {
// Draw a line diagonally across the page
Size pageSize = outPage.getSize();
pathGenerator.moveTo(new Point(10.0, 10.0));
pathGenerator.lineTo(new Point(pageSize.width - 10.0, pageSize.height - 10.0));
}
// Create a RGB color space
ColorSpace deviceRgbColorSpace = document.createDeviceColorSpace(DeviceColorSpaceType.RGB);
// Create a red color
double[] color = new double[] { 1.0, 0.0, 0.0 };
// Create a paint
Paint paint = document.createSolidPaint(deviceRgbColorSpace, color);
// Create stroking parameters with given paint and line width
StrokeParams stroke = new StrokeParams();
stroke.paint = paint;
stroke.lineWidth = 10.0;
// Draw the path onto the page
generator.paintPath(path, null, stroke, false);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 1; iPage <= PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage - 1);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
PdfPageGetSize(pOutPage, &size);
//Add text on first page
if (addLine(pOutDoc, pOutPage) == 1)
{
goto cleanup;
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addLine(TPdfDocument * pOutDoc, TPdfPage * pOutPage)
{
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
TPdfPath* pPath = NULL;
TPdfPathGenerator* pPathGenerator = NULL;
TPdfColorSpace* pDeviceRgbColorSpace = NULL;
double aColor[3];
TPdfPaint* pPaint = NULL;
TPdfStrokeParams stroke;
TPdfSize pageSize;
TPdfPoint point;
PdfStrokeParamsInitialize(&stroke);
pContent = PdfPageGetContent(pOutPage);
PdfPageGetSize(pOutPage, &pageSize);
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL(pGenerator, szErrorBuff, PdfGetLastError());
// Create a path
pPath = PdfNewPath(ePdfRuleNonzeroWindingNumber);
GOTO_CLEANUP_IF_NULL(pPath, szErrorBuff, PdfGetLastError());
// Create a path generator
pPathGenerator = PdfNewPathGenerator(pPath);
GOTO_CLEANUP_IF_NULL(pPathGenerator, szErrorBuff, PdfGetLastError());
// Draw a line diagonally across the page
point.dX = 10.0;
point.dY = 10.0;
GOTO_CLEANUP_IF_FALSE(PdfPathGeneratorMoveTo(pPathGenerator, &point), szErrorBuff, PdfGetLastError());
point.dX = pageSize.dWidth - 10.0;
point.dY = pageSize.dHeight - 10.0;
GOTO_CLEANUP_IF_FALSE(PdfPathGeneratorLineTo(pPathGenerator, &point), szErrorBuff, PdfGetLastError());
// Close the path generator in order to finish the path
PdfClose(pPathGenerator);
pPathGenerator = NULL;
// Create a RGB color space
pDeviceRgbColorSpace = PdfDocumentCreateDeviceColorSpace(pOutDoc, ePdfColorSpaceRGB);
GOTO_CLEANUP_IF_NULL(pDeviceRgbColorSpace, szErrorBuff, PdfGetLastError());
// Initialize a red color
aColor[0] = 1.0;
aColor[1] = 0.0;
aColor[2] = 0.0;
// Create a paint
pPaint = PdfDocumentCreateSolidPaint(pOutDoc, pDeviceRgbColorSpace, aColor, sizeof(aColor) / sizeof(aColor[0]));
GOTO_CLEANUP_IF_NULL(pPaint, szErrorBuff, PdfGetLastError());
// Setup strokeing parameters with given paint and line width
stroke.pPaint = pPaint;
stroke.dLineWidth = 10.0;
// Draw the path onto the page
GOTO_CLEANUP_IF_FALSE(PdfContentGeneratorPaintPath(pGenerator, pPath, NULL, &stroke, FALSE), szErrorBuff, PdfGetLastError());
cleanup:
if (pPathGenerator != NULL)
PdfClose(pPathGenerator);
if (pGenerator != NULL)
PdfClose(pGenerator);
if (pContent != NULL)
PdfClose(pContent);
return iReturnValue;
}
Layout text on PDF page
Create a new PDF document with one page. On this page, within a given rectangular area, add a text block with a full justification layout.
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.CreateNew, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, Conformance.Unknown, null))
{
Font font = outDoc.CreateSystemFont("Arial", "Italic", true);
// Create page
Page outPage = outDoc.CreatePage(PageSize);
// Add text as justified text
LayoutText(outDoc, outPage, textPath, font, 20);
// Add page to document
outDoc.Pages.Add(outPage);
}
private static void LayoutText(Document outputDoc, Page outPage, string textPath, Font font,
double fontSize)
{
// Create content generator
using (ContentGenerator gen = new ContentGenerator(outPage.Content, false))
{
// Create text object
Text text = outputDoc.CreateText();
// Create text generator
using (TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null))
{
string[] lines = File.ReadAllLines(textPath, Encoding.Default);
// Calculate position
Point position = new Point
{
X = Border,
Y = outPage.Size.Height - Border
};
// Move to position
textGenerator.MoveTo(position);
// Loop throw all lines of the textinput
foreach (string line in lines)
{
// Split string in substrings
string[] substrings = line.Split(new char[] { ' ' }, StringSplitOptions.None);
string currentLine = null;
double maxWidth = (outPage.Size.Width - (Border * 2));
int wordcount = 0;
// Loop throw all words of input strings
foreach (string word in substrings)
{
string tempLine;
// Concatenate substrings to line
if (currentLine != null)
{
tempLine = currentLine + " " + word;
}
else
{
tempLine = word;
}
// Calculate the current width of line
double width = textGenerator.GetWidth(currentLine);
if ((textGenerator.GetWidth(tempLine) > maxWidth))
{
// Calculate the word spacing
textGenerator.WordSpacing = ((maxWidth - width) / (wordcount - 1));
// Paint on new line
textGenerator.ShowLine(currentLine);
textGenerator.WordSpacing = (0);
currentLine = word;
wordcount = 1;
}
else
{
currentLine = tempLine;
wordcount++;
}
}
textGenerator.WordSpacing = (0);
// Add given stamp string
textGenerator.ShowLine(currentLine);
}
// Paint the positioned text
gen.PaintText(text);
}
}
}
try (
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, Conformance.UNKNOWN, null)) {
// Create embedded font in output document
Font font = outDoc.createSystemFont("Arial", "Italic", true);
// Create page
Page outPage = outDoc.createPage(PageSize);
// Add text to document
layoutText(outDoc, outPage, textPath, font, 20);
// Add page to output document
outDoc.getPages().add(outPage);
}
}
private static void layoutText(Document outputDoc, Page outPage, String textPath, Font font, double fontSize)
throws ErrorCodeException, IOException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Create text object
Text text = outputDoc.createText();
try (// Create a text generator
TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null)) {
List<String> lines = Files.readAllLines(Paths.get(textPath), Charset.defaultCharset());
// Calculate position
Point position = new Point(Border, outPage.getSize().height - Border);
// Move to position
textGenerator.moveTo(position);
// Loop throw all lines of the textinput
for (String line : lines) {
// Split string in substrings
String[] substrings = line.split(" ");
String currentLine = null;
double maxWidth = (outPage.getSize().width - (Border * 2));
int wordCount = 0;
// Loop throw all words of input strings
for (String word : substrings) {
String tempLine;
// Concatenate substrings to line
if (currentLine != null) {
tempLine = currentLine + " " + word;
} else {
tempLine = word;
}
// Calculate the current width of line
double width = textGenerator.getWidth(currentLine);
if ((textGenerator.getWidth(tempLine) > maxWidth)) {
// Calculate the word spacing
textGenerator.setWordSpacing((maxWidth - width) / (double) (wordCount - 1));
// Paint on new line
textGenerator.showLine(currentLine);
textGenerator.setWordSpacing(0);
currentLine = word;
wordCount = 1;
} else {
currentLine = tempLine;
wordCount++;
}
}
textGenerator.setWordSpacing(0);
// Add given stamp string
textGenerator.showLine(currentLine);
}
}
// Paint the positioned text
generator.paintText(text);
}
}
Stamp page number to PDF
Stamp the page number to the footer of each page of a PDF document.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Create embedded font in output document
Font font = outDoc.CreateSystemFont("Arial", string.Empty, true);
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
// Copy page from input to output
Page outPage = outDoc.CopyPage(inPage, copyOptions);
// Stamp page number on current page of output document
AddPageNumber(outDoc, outPage, font, currentPageNumber++);
// Add page to output document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddPageNumber(Document outDoc, Page outPage, Font font, int pageNumber)
{
// Create content generator
using (ContentGenerator generator = new ContentGenerator(outPage.Content, false))
{
// Create text object
Text text = outDoc.CreateText();
// Create a text generator with the given font, size and position
using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
{
// Generate string to be stamped as page number
string stampText = string.Format("Page {0}", pageNumber);
// Calculate position for centering text at bottom of page
Point position = new Point
{
X = (outPage.Size.Width / 2) - (textgenerator.GetWidth(stampText) / 2),
Y = 10
};
// Position the text
textgenerator.MoveTo(position);
// Add page number
textgenerator.Show(stampText);
}
// Paint the positioned text
generator.PaintText(text);
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Copy pages from input to output
int pageNo = 1;
// Create embedded font in output document
Font font = outDoc.createSystemFont("Arial", "", true);
// Loop through all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Stamp page number on current page of output document
applyStamps(outDoc, outPage, font, pageNo++);
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void applyStamps(Document doc, Page page, Font font, int pageNo) throws ErrorCodeException {
try (// Create content generator
ContentGenerator generator = new ContentGenerator(page.getContent(), false)) {
// Create text object
Text text = doc.createText();
try (// Create a text generator with the given font, size and position
TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
// Generate string to be stamped as page number
String stampText = String.format("Page %d", pageNo);
// Calculate position for centering text at bottom of page
Point position = new Point((page.getSize().width / 2) - (textgenerator.getWidth(stampText) / 2), 10);
// Position the text
textgenerator.moveTo(position);
// Add page number
textgenerator.show(stampText);
}
// Paint the positioned text
generator.paintText(text);
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Create embedded font in output document
pFont = PdfDocumentCreateSystemFont(pOutDoc, _T("Arial"), _T(""), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
int iPageNo = 1;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageGetSize(pOutPage, &size), _T("Failed to get size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Stamp page number on current page of output document
if (addPageNumber(pOutDoc, pOutPage, pFont, iPageNo++) == 1)
{
goto cleanup;
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int addPageNumber(TPdfDocument* pOutDoc, TPdfPage* pOutPage, TPdfFont* pFont, int nPageNumber)
{
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
TPdfText* pText = NULL;
TPdfTextGenerator* pTextGenerator = NULL;
pContent = PdfPageGetContent(pOutPage);
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create text object
pText = PdfDocumentCreateText(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create a text generator with the given font, size and position
pTextGenerator = PdfNewTextGenerator(pText, pFont, 8, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Generate string to be stamped as page number
char szStampBuffer[50];
sprintf(szStampBuffer, _T("Page %d"), nPageNumber);
TCHAR* szStampText = szStampBuffer;
double dTextWidth = PdfTextGeneratorGetWidth(pTextGenerator, szStampText);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("Failed to get text width. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate position
TPdfPoint position;
position.dX = (size.dWidth / 2) - (dTextWidth / 2);
position.dY = 10;
// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorMoveTo(pTextGenerator, &position), _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add given text string
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorShowLine(pTextGenerator, szStampText), _T("Failed to add given text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Close text generator
if (pTextGenerator != NULL)
PdfClose(pTextGenerator);
// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintText(pGenerator, pText), _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pText != NULL)
PdfClose(pText);
if (pContent != NULL)
PdfClose(pContent);
if (pGenerator != NULL)
PdfClose(pGenerator);
return iReturnValue;
}
Document Setup
Add metadata to PDF
Set metadata such as author, title, and creator of a PDF document. Optionally use the metadata of another PDF document or the content of an XMP file.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Set Metadata
if (args.Length == 3)
{
Metadata mdata;
// Add metadata from a input file
using (FileStream metaStream = File.OpenRead(mdatafile))
{
if (mdatafile.EndsWith(".pdf"))
{
// Use the metadata of another PDF file
Document metaDoc = Document.Open(metaStream, "");
mdata = outDoc.CopyMetadata(metaDoc.Metadata);
}
else
{
// Use the content of an XMP metadata file
mdata = outDoc.CreateMetadata(metaStream);
}
outDoc.Metadata = mdata;
}
}
else
{
// Set some metadata properties
Metadata metadata = outDoc.Metadata;
metadata.Author = "Your Author";
metadata.Title = "Your Title";
metadata.Subject = "Your Subject";
metadata.Creator = "Your Creator";
metadata.Producer = "Your Producer";
}
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data (except metadata)
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add pages to output document
outDoc.getPages().add(outPage);
}
if (args.length == 3) {
Metadata mdata;
// Add metadata from a input file
FileStream metaStream = new FileStream(mdatafile, "r");
if (mdatafile.toLowerCase().endsWith(".pdf")) {
// Use the metadata of another PDF file
Document metaDoc = Document.open(metaStream, null);
mdata = outDoc.copyMetadata(metaDoc.getMetadata());
} else {
// Use the content of an XMP metadata file
mdata = outDoc.createMetadata(metaStream);
}
outDoc.setMetadata(mdata);
} else {
// Set some metadata properties
Metadata metadata = outDoc.getMetadata();
metadata.setAuthor("Your Author");
metadata.setTitle("Your Title");
metadata.setSubject("Your Subject");
metadata.setCreator("Your Creator");
metadata.setProducer("Your Producer");
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data (excluding metadata)
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
if (argc == 4)
{
// Add metadata from a input file
pMdataStream = _tfopen(szMdatafile, _T("rb"));
GOTO_CLEANUP_IF_NULL(pMdataStream, _T("Failed to open metadata file \"%s\".\n"), szMdatafile);
PdfCreateFILEStreamDescriptor(&mdataDescriptor, pMdataStream, 0);
// Get file extension
TCHAR* szExt = _tcsrchr(szMdatafile, '.');
_tcscpy(szExtension, szExt);
if (_tcscmp(szExtension, _T(".pdf")) == 0)
{
// Use the metadata of another PDF file
TPdfDocument* pMetaDoc = PdfDocumentOpen(&mdataDescriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetaDoc, _T("Failed to open metadata file. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
TPdfMetadata* pMetadata = PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pMetaDoc));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)."), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfDocumentSetMetadata(pOutDoc, pMetadata), _T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
}
else
{
// Use the content of an XMP metadata file
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfDocumentSetMetadata(pOutDoc, PdfDocumentCreateMetadata(pOutDoc, &mdataDescriptor)), _T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
}
}
else
{
// Set some metadata properties
TPdfMetadata* pMetadata = PdfDocumentGetMetadata(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to get metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfMetadataSetAuthor(pMetadata, _T("Your Author")), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfMetadataSetTitle(pMetadata, _T("Your Title")), _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfMetadataSetSubject(pMetadata, _T("Your Subject")), _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfMetadataSetCreator(pMetadata, _T("Your Creator")), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfMetadataSetProducer(pMetadata, _T("Your Producer")), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
// Copy document-wide data (excluding metadata)
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
Encrypt PDF
Encrypt a PDF document with a user password and an owner password. When opening the document, either of the passwords must be provided. If providing the user password, the document can be viewed and printed only. Providing the owner password grants full access to the document.
// Create encryption parameters
EncryptionParams encryptionParams = new EncryptionParams(UserPwd, OwnerPwd, Permission.Print |
Permission.DigitalPrint);
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document and set a user and owner password
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, encryptionParams))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
// Create encryption parameters
EncryptionParams encryptionParams = new EncryptionParams(userPwd, ownerPwd,
EnumSet.of(Permission.PRINT, Permission.DIGITAL_PRINT));
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document and set a user and owner password
Document outDoc = Document.create(outStream, inDoc.getConformance(), encryptionParams)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add pages to first document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
TPdfEncryptionParams encryptParams;
encryptParams.szUserPassword = szUserPwd;
encryptParams.szOwnerPassword = szOwnerPwd;
encryptParams.iPermissions = ePermPrint | ePermDigitalPrint;
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), &encryptParams);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to outpuf document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
Flatten form fields in PDF
Flatten the visual appearance of form fields and discard all interactive elements.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define copy options including form field flattening (CopyOption.FlattenFormFields)
CopyOption copyOptions = CopyOption.CopyOutlines | CopyOption.CopyLinks |
CopyOption.CopyAnnotations | CopyOption.CopyAssociatedFiles |
CopyOption.FlattenFormFields | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Set copy options and flatten annotations, form fields and signatures
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_OUTLINES, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_LINKS, CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_LOGIGAL_STRUCTURE,
CopyOption.FLATTEN_FORM_FIELDS);
// Loop through all pages of input
for (int i = 0; i < inDoc.getPages().size(); i++) {
Page inPage = inDoc.getPages().get(i);
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add pages to document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options and flatten form fields
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyOutlines | ePdfFlattenFormFields | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
Merge multiple PDFs
Merge several PDF documents to one.
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, Conformance.Unknown, null))
{
// Merge input documents
for (int i = 0; i < args.Length - 1; i++)
{
// Open input document
using (Stream inFs = new FileStream(inPath[i], FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inFs, null))
{
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure |
CopyOption.OptimizeResources;
// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
outDoc.Pages.Add(outPage);
}
}
}
}
try (
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, Conformance.UNKNOWN, null)) {
// Merge input document
for (int i = 0; i < args.length - 1; i++) {
try (// Open input document
FileStream inStream = new FileStream(inPath[i], "r");
Document inDoc = Document.open(inStream, null)) {
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE, CopyOption.OPTIMIZE_RESOURCES);
// Copy pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add pages to output document
outDoc.getPages().add(outPage);
}
}
}
}
}
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, ePdfUnk, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Merge input documents
for (int i = 1; i < argc - 1; i++)
{
// Open input document
pInStream = _tfopen(szInPath[i], _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath[i]);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath[i], szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy pages of input
for (int iPages = 0; iPages < PdfPageListGetCount(pInPageList); iPages++)
{
pInPage = PdfPageListGet(pInPageList, iPages);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
}
fclose(pInStream);
pInStream = NULL;
Merge multiple PDFs with outlines
Merge several PDF documents to one, while creating an outline item for each input document.
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, Conformance.Unknown, null))
{
// Merge input documents
foreach (string inPath in inPaths)
{
// Open input document
using (Stream inFs = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inFs, null))
{
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure |
CopyOption.OptimizeResources;
// Copy all pages of input document
Page firstOutPage = null;
foreach (Page inPage in inDoc.Pages)
{
// Copy page from input to output
Page outPage = outDoc.CopyPage(inPage, copyOptions);
if (firstOutPage == null)
firstOutPage = outPage;
// Add pages to document
outDoc.Pages.Add(outPage);
}
// Create outline item
string title = inDoc.Metadata.Title ?? System.IO.Path.GetFileName(inPath);
Destination destination = new LocationZoomDestination(firstOutPage, 0, firstOutPage.Size.Height, null);
OutlineItem outlineItem = outDoc.CreateOutlineItem(title, destination);
outDoc.OutlineItems.Add(outlineItem);
// Add outline items from input document as children
OutlineItemList children = outlineItem.Children;
foreach (OutlineItem inputOutline in inDoc.OutlineItems)
children.Add(outDoc.CopyOutlineItem(inputOutline, copyOptions));
}
}
}
try (
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, Conformance.UNKNOWN, null)) {
// Merge input document
for (String inPath : inPaths) {
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null)) {
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE, CopyOption.OPTIMIZE_RESOURCES);
// Copy pages of input
Page firstOutPage = null;
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
if (firstOutPage == null)
firstOutPage = outPage;
// Add pages to output document
outDoc.getPages().add(outPage);
}
// Create outline item
String title = inDoc.getMetadata().getTitle();
if (title == null)
title = Paths.get(inPath).getFileName().toString();
Destination destination = new LocationZoomDestination(firstOutPage, 0.0,
firstOutPage.getSize().getHeight(), null);
OutlineItem outlineItem = outDoc.createOutlineItem(title, destination);
outDoc.getOutlineItems().add(outlineItem);
// Add outline items from input document as children
OutlineItemList children = outlineItem.getChildren();
for (OutlineItem inputOutline : inDoc.getOutlineItems())
children.add(outDoc.copyOutlineItem(inputOutline, copyOptions));
}
}
}
}
Overlay color of PDF
Overlay all pages of a PDF document with a configurable color.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Set blendmode
BlendMode blendMode = BlendMode.Multiply;
// Create colorspace
ColorSpace colorSpace = outDoc.CreateDeviceColorSpace(colorType);
Paint paint = null;
switch (colorType)
{
// Create blending paint
case DeviceColorSpaceType.Gray:
paint = outDoc.CreateBlendingPaint(colorSpace, blendMode, colorAlpha, color[0]);
break;
case DeviceColorSpaceType.RGB:
paint = outDoc.CreateBlendingPaint(colorSpace, blendMode, colorAlpha, color[0],
color[1], color[2]);
break;
case DeviceColorSpaceType.CMYK:
paint = outDoc.CreateBlendingPaint(colorSpace, blendMode, colorAlpha, color[0],
color[1], color[2], color[3]);
break;
}
// Get output pages
PageList outPages = outDoc.Pages;
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Loop through all pages
foreach (Page inPage in inDoc.Pages)
{
// Create a new page
Size size = inPage.Size;
Page outPage = outDoc.CopyPage(inPage, copyOptions);
// Create a content generator
using (ContentGenerator generator = new ContentGenerator(outPage.Content, false))
{
// Compute Rectangle
Rectangle rect = new Rectangle
{
Left = 0,
Bottom = 0,
Right = size.Width,
Top = size.Height
};
// Make a rectangular path the same size as the page
PdfTools.Pdf.Path path = new PdfTools.Pdf.Path(InsideRule.EvenOdd);
using (PathGenerator pathGenerator = new PathGenerator(path))
{
Rectangle pathRect = new Rectangle
{
Left = 0,
Bottom = 0,
Right = size.Width,
Top = size.Height
};
pathGenerator.AddRectangle(pathRect);
}
// Paint the path with the transparent paint
generator.PaintPath(path, paint, null, false);
}
// Add pages to output document
outPages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Set blendmode
BlendMode blendMode = BlendMode.MULTIPLY;
// Create colorspace
ColorSpace colorSpace = outDoc.createDeviceColorSpace(colorType);
// Create a transparent paint for the given color
Paint paint = null;
switch (colorType) {
case GRAY:
paint = outDoc.createBlendingPaint(colorSpace, blendMode, colorAlpha, color[0]);
break;
case RGB:
paint = outDoc.createBlendingPaint(colorSpace, blendMode, colorAlpha, color[0], color[1],
color[2]);
break;
case CMYK:
paint = outDoc.createBlendingPaint(colorSpace, blendMode, colorAlpha, color[0], color[1],
color[2], color[3]);
break;
}
// Get output pages
PageList outPages = outDoc.getPages();
// Set copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES, CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages
for (Page inPage : inDoc.getPages()) {
// Create a new page
Size size = inPage.getSize();
Page outPage = outDoc.copyPage(inPage, copyOptions);
try (// Create a content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Calculate rectangle
Rectangle rect = new Rectangle(0, 0, size.width, size.height);
// Make a rectangular path the same size as the page
Path path = new Path(InsideRule.EVEN_ODD);
try (
PathGenerator pathGenerator = new PathGenerator(path)) {
pathGenerator.addRectangle(rect);
}
// Paint the path with the transparent paint
generator.paintPath(path, paint, null, false);
}
// Add pages to output document
outPages.add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
Add info entries to PDF
Set metadata such as author, title, and creator of a PDF document or add a custom entry.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy pages from input document
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
outDoc.Pages.Add(outPage);
}
// Set info entry
Metadata metadata = outDoc.CopyMetadata(inDoc.Metadata);
if (key == "Title")
metadata.Title = value;
else if (key == "Author")
metadata.Author = value;
else if (key == "Subject")
metadata.Subject = value;
else if (key == "Keywords")
metadata.Keywords = value;
else if (key == "CreationDate")
metadata.CreationDate2 = DateTimeOffset.Parse(value);
else if (key == "ModDate")
throw new Exception("ModDate cannot be set.");
else if (key == "Creator")
metadata.Creator = value;
else if (key == "Producer")
metadata.Producer = value;
else
metadata.CustomEntries[key] = value;
outDoc.Metadata = metadata;
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data (except metadata)
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (Page inPage : inDoc.getPages()) {
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add pages to output document
outDoc.getPages().add(outPage);
}
// Set info entry
Metadata metadata = outDoc.copyMetadata(inDoc.getMetadata());
if (key.equals("Title"))
metadata.setTitle(value);
else if (key.equals("Author"))
metadata.setAuthor(value);
else if (key.equals("Subject"))
metadata.setSubject(value);
else if (key.equals("Keywords"))
metadata.setKeywords(value);
else if (key.equals("CreationDate")) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ssZ");
Calendar val = Calendar.getInstance();
val.setTime(format.parse(value));
metadata.setCreationDate(val);
} else if (key.equals("ModDate"))
throw new Exception("ModDate cannot be set.");
else if (key.equals("Creator"))
metadata.setCreator(value);
else if (key.equals("Producer"))
metadata.setProducer(value);
else
metadata.getCustomEntries().put(key, value);
outDoc.setMetadata(metadata);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data (excluding metadata)
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
Set the open-destination of a PDF
Set the page that is displayed when opening the document.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
if (destinationPageNumber > inDoc.Pages.Count)
throw new ArgumentOutOfRangeException("Page number is not in range");
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
outDoc.Pages.Add(outPage);
// Add open destination
if (currentPageNumber == destinationPageNumber)
outDoc.OpenDestination = new LocationZoomDestination(outPage, 0, outPage.Size.Height, null);
currentPageNumber++;
}
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
Remove pages from PDF
Selectively remove pages from a PDF document.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
firstPage = Math.Max(Math.Min(inDoc.Pages.Count - 1, firstPage), 0);
lastPage = Math.Max(Math.Min(inDoc.Pages.Count - 1, lastPage), 0);
if (firstPage > lastPage)
{
Console.WriteLine("lastPage must be greater or equal to firstPage");
return;
}
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy specified page range from input document
for (int currentPage = 1; currentPage <= inDoc.Pages.Count; currentPage++)
{
if (currentPage >= firstPage && currentPage <= lastPage)
{
// Copy from input to output
Page inPage = inDoc.Pages[currentPage - 1];
Page outPage = outDoc.CopyPage(inPage, copyOptions);
// Add page to document
outDoc.Pages.Add(outPage);
}
}
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null)) {
firstPage = Math.max(Math.min(inDoc.getPages().size() - 1, firstPage), 0);
lastPage = Math.max(Math.min(inDoc.getPages().size() - 1, lastPage), 0);
if (firstPage > lastPage) {
System.out.println("lastPage must be greater or equal to firstPage");
return;
}
try (
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (int i = 0; i <= inDoc.getPages().size(); i++) {
if (i >= firstPage && i <= lastPage) {
Page inPage = inDoc.getPages().get(i);
// Copy from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add pages to first document
outDoc.getPages().add(outPage);
}
}
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
int nInPages = PdfPageListGetCount(pInPageList);
iFirstPage = MAX(MIN(nInPages - 1, iFirstPage), 0);
iLastPage = MAX(MIN(nInPages - 1, iLastPage), 0);
GOTO_CLEANUP_IF_FALSE(iFirstPage <= iLastPage, _T("Invalid page range given: %d - %d.\n"), iFirstPage, iLastPage);
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < nInPages; iPage++)
{
if (iPage >= iFirstPage && iPage <= iLastPage)
{
pInPage = PdfPageListGet(pInPageList, iPage);
// Copy from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add pages to first document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
Imposition
Create a booklet from PDF
Place up to two A4 pages in the right order on an A3 page, so that duplex printing and folding the A3 pages results in a booklet.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Create a font
Font font = outDoc.CreateSystemFont("Arial", "Italic", true);
// Copy pages
PageList inPages = inDoc.Pages;
PageList outPages = outDoc.Pages;
int numberOfSheets = (inPages.Count + 3) / 4;
for (int sheetNumber = 0; sheetNumber < numberOfSheets; ++sheetNumber)
{
// Add on front side
CreateBooklet(inPages, outDoc, outPages, 4 * numberOfSheets - 2 * sheetNumber - 1,
2 * sheetNumber, font);
// Add on back side
CreateBooklet(inPages, outDoc, outPages, 2 * sheetNumber + 1,
4 * numberOfSheets - 2 * sheetNumber - 2, font);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void CreateBooklet(PageList inPages, Document outDoc, PageList outPages, int leftPageIndex,
int rightPageIndex, Font font)
{
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Create page object
Page outpage = outDoc.CreatePage(PageSize);
// Create content generator
using (ContentGenerator generator = new ContentGenerator(outpage.Content, false))
{
BlendMode blendMode = 0;
double alpha = 1.0;
TransparencyParams transparencyParams = new TransparencyParams(blendMode, alpha);
// Left page
if (leftPageIndex < inPages.Count)
{
// Copy page from input to output
Page leftPage = inPages[leftPageIndex];
Group leftGroup = outDoc.CopyPageAsGroup(leftPage, copyOptions);
// Paint group on the calculated rectangle
generator.PaintGroup(leftGroup, ComputTargetRect(leftGroup.Size, true),
transparencyParams);
// Add page number to page
StampPageNumber(outDoc, font, generator, leftPageIndex + 1, true);
}
// Right page
if (rightPageIndex < inPages.Count)
{
// Copy page from input to output
Page rigthPage = inPages[rightPageIndex];
Group rightGroup = outDoc.CopyPageAsGroup(rigthPage, copyOptions);
// Paint group on the calculated rectangle
generator.PaintGroup(rightGroup, ComputTargetRect(rightGroup.Size, false),
transparencyParams);
// Add page number to page
StampPageNumber(outDoc, font, generator, rightPageIndex + 1, false);
}
}
// Add page to output document
outPages.Add(outpage);
}
private static Rectangle ComputTargetRect(Size bbox, Boolean isLeftPage)
{
// Calculate factor for fitting page into rectangle
double scale = Math.Min(CellWidth / bbox.Width, CellHeight / bbox.Height);
double groupWidth = bbox.Width * scale;
double groupHeight = bbox.Height * scale;
// Calculate x-value
double groupXPos;
if (isLeftPage)
groupXPos = CellLeft + (CellWidth - groupWidth) / 2;
else
groupXPos = CellRight + (CellWidth - groupWidth) / 2;
// Calculate y-value
double groupYPos = CellYPos + (CellHeight - groupHeight) / 2;
// Calculate rectangle
return new Rectangle
{
Left = groupXPos,
Bottom = groupYPos,
Right = groupXPos + groupWidth,
Top = groupYPos + groupHeight
};
}
private static void StampPageNumber(Document document, Font font, ContentGenerator generator,
int PageNo, Boolean isLeftPage)
{
// Create text object
Text text = document.CreateText();
// Create text generator
using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
{
String stampText = String.Format("Page {0}", PageNo);
// Get width of stamp text
double width = textgenerator.GetWidth(stampText);
double x;
// Calculate position
if (isLeftPage)
x = Border + 0.5 * CellWidth - width / 2;
else
x = 2 * Border + 1.5 * CellWidth - width / 2;
double y = Border;
Point point = new Point
{
X = x,
Y = y
};
// Move to position
textgenerator.MoveTo(point);
// Add page number
textgenerator.Show(stampText);
}
// Paint the positioned text
generator.PaintText(text);
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
Font font = outDoc.createSystemFont("Arial", "Italic", true);
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Copy pages
PageList inPages = inDoc.getPages();
PageList outPages = outDoc.getPages();
int numberOfSheets = (inPages.size() + 3) / 4;
for (int sheetNumber = 0; sheetNumber < numberOfSheets; ++sheetNumber) {
// Add on front side
CreateBooklet(inPages, outDoc, outPages, 4 * numberOfSheets - 2 * sheetNumber - 1,
2 * sheetNumber, font);
// Add on back side
CreateBooklet(inPages, outDoc, outPages, 2 * sheetNumber + 1,
4 * numberOfSheets - 2 * sheetNumber - 2, font);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void CreateBooklet(PageList inPages, Document outDoc, PageList outPages, int leftPageIndex,
int rightPageIndex, Font font) throws ErrorCodeException {
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Create page object
Page outPage = outDoc.createPage(PageSize);
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
BlendMode blendMode = BlendMode.NORMAL;
double alpha = 1.0;
TransparencyParams transparencyParams = new TransparencyParams(blendMode, alpha);
// Left page
if (leftPageIndex < inPages.size()) {
Page leftPage = inPages.get(leftPageIndex);
// Copy page from input to output
Group leftGroup = outDoc.copyPageAsGroup(leftPage, copyOptions);
// Paint group on the calculated rectangle
generator.paintGroup(leftGroup, ComputTargetRect(leftGroup.getSize(), true), transparencyParams);
// Add page number to page
StampPageNumber(outDoc, font, generator, leftPageIndex + 1, true);
}
// Right page
if (rightPageIndex < inPages.size()) {
Page rightPage = inPages.get(rightPageIndex);
// Copy page from input to output
Group rightGroup = outDoc.copyPageAsGroup(rightPage, copyOptions);
// Paint group on the calculated rectangle
generator.paintGroup(rightGroup, ComputTargetRect(rightGroup.getSize(), false), transparencyParams);
// Add page number to page
StampPageNumber(outDoc, font, generator, rightPageIndex + 1, false);
}
}
// Add page to output document
outPages.add(outPage);
}
private static Rectangle ComputTargetRect(Size bbox, Boolean isLeftPage) {
// Calculate factor for fitting page into rectangle
double scale = Math.min(CellWidth / bbox.width, CellHeight / bbox.height);
double groupWidth = bbox.width * scale;
double groupHeight = bbox.height * scale;
// Calculate x-value
double groupXPos;
if (isLeftPage)
groupXPos = CellLeft + (CellWidth - groupWidth) / 2;
else
groupXPos = CellRight + (CellWidth - groupWidth) / 2;
// Calculate y-value
double groupYPos = CellYPos + (CellHeight - groupHeight) / 2;
// Calculate rectangle
return new Rectangle(groupXPos, groupYPos, groupXPos + groupWidth, groupYPos + groupHeight);
}
private static void StampPageNumber(Document document, Font font, ContentGenerator generator, int pageNo,
boolean isLeftPage) throws ErrorCodeException {
// Create text object
Text text = document.createText();
try (// Create text generator
TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
String stampText = String.format("Page %d", pageNo);
// Get width of stamp text
double width = textgenerator.getWidth(stampText);
double x;
// Calculate position
if (isLeftPage)
x = Border + 0.5 * CellWidth - width / 2;
else
x = 2 * Border + 1.5 * CellWidth - width / 2;
double y = Border;
Point point = new Point(x, y);
// Move to position
textgenerator.moveTo(point);
// Add page number
textgenerator.show(stampText);
}
// Paint the positioned text
generator.paintText(text);
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
pFont = PdfDocumentCreateSystemFont(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy pages
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
int nNumberOfSheets = (PdfPageListGetCount(pInPageList) + 3) / 4;
for (int nSheetNumber = 0; nSheetNumber < nNumberOfSheets; nSheetNumber++)
{
// Add on front side
CreateBooklet(pInPageList, pOutDoc, pOutPageList, 4 * nNumberOfSheets - 2 * nSheetNumber - 1, 2 * nSheetNumber, pFont);
// Add on back side
CreateBooklet(pInPageList, pOutDoc, pOutPageList, 2 * nSheetNumber + 1, 4 * nNumberOfSheets - 2 * nSheetNumber - 2, pFont);
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
int StampPageNumber(TPdfDocument* pDocument, TPdfFont* pFont, TPdfContentGenerator* pGenerator, int nPageNo, BOOL bIsLeftPage)
{
TPdfText* pText = NULL;
TPdfTextGenerator* pTextGenerator = NULL;
// Create text object
pText = PdfDocumentCreateText(pDocument);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create text generator
pTextGenerator = PdfNewTextGenerator(pText, pFont, 8, NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create text generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
char szStampBuffer[50];
sprintf(szStampBuffer, _T("Page %d"), nPageNo);
TCHAR* szStampText = szStampBuffer;
// Get width of stamp text
double dStampWidth = PdfTextGeneratorGetWidth(pTextGenerator, szStampText);
GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dStampWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dStampX;
// Calculate position
if (bIsLeftPage)
{
dStampX = dBorder + 0.5 * dCellWidth - dStampWidth / 2;
}
else
{
dStampX = 2 * dBorder + 1.5 * dCellWidth - dStampWidth / 2;
}
double dStampY = dBorder;
TPdfPoint point;
point.dX = dStampX;
point.dY = dStampY;
// Move to position
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorMoveTo(pTextGenerator, &point), _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add page number
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTextGeneratorShow(pTextGenerator, szStampText), _T("Failed to add page number. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pTextGenerator != NULL)
PdfClose(pTextGenerator);
// Paint the positioned text
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintText(pGenerator, pText), _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
if (pText != NULL)
PdfClose(pText);
return iReturnValue;
}
void ComputeTargetRect(TPdfRectangle* pRectangle, const TPdfSize* pBBox, BOOL bIsLeftPage)
{
// Calculate factor for fitting page into rectangle
double dScale = MIN(dCellWidth / pBBox->dWidth, dCellHeight / pBBox->dHeight);
double dGroupWidth = pBBox->dWidth * dScale;
double dGroupHeight = pBBox->dHeight * dScale;
// Calculate x-value
double dGroupXPos;
if (bIsLeftPage)
dGroupXPos = dCellLeft + (dCellWidth - dGroupWidth) / 2;
else
dGroupXPos = dCellRight + (dCellWidth - dGroupWidth) / 2;
// Calculate y-value
double dGroupYPos = dCellYPos + (dCellHeight - dGroupHeight) / 2;
// Calculate rectangle
pRectangle->dLeft = dGroupXPos;
pRectangle->dBottom = dGroupYPos;
pRectangle->dRight = dGroupXPos + dGroupWidth;
pRectangle->dTop = dGroupYPos + dGroupHeight;
}
int CreateBooklet(TPdfPageList* pInDocList, TPdfDocument* pOutDoc, TPdfPageList* pOutDocList, int nLeftPageIndex, int nRightPageIndex, TPdfFont* pFont)
{
TPdfPage* pOutPage = NULL;
TPdfContent* pContent = NULL;
TPdfContentGenerator* pGenerator = NULL;
TPdfRectangle targetRect;
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
// Create page object
pOutPage = PdfDocumentCreatePage(pOutDoc, &PageSize);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create page object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Create content generator
pContent = PdfPageGetContent(pOutPage);
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
int nPageCount = PdfPageListGetCount(pInDocList);
TPdfTransparencyParams trans;
trans.iBlendMode = ePdfBlendModeNormal;
trans.dConstAlpha = 1.0;
// Left page
if (nLeftPageIndex < nPageCount)
{
TPdfPage* pLeftPage = PdfPageListGet(pInDocList, nLeftPageIndex);
// Copy page from input to output
TPdfGroup* pLeftGroup = PdfDocumentCopyPageAsGroup(pOutDoc, pLeftPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pLeftGroup, _T("Failed to copy group from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
TPdfSize leftGroupSize;
PdfGroupGetSize(pLeftGroup, &leftGroupSize);
// Paint group on the calculated rectangle
ComputeTargetRect(&targetRect, &leftGroupSize, TRUE);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintGroup(pGenerator, pLeftGroup, &targetRect, &trans), _T("Failed to paint group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add page number to page
if (StampPageNumber(pOutDoc, pFont, pGenerator, nLeftPageIndex + 1, TRUE) == 1)
{
goto cleanup;
}
}
// Right page
if (nRightPageIndex < nPageCount)
{
TPdfPage* pRightPage = PdfPageListGet(pInDocList, nRightPageIndex);
// Copy page from input to output
TPdfGroup* pRightGroup = PdfDocumentCopyPageAsGroup(pOutDoc, pRightPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pRightGroup, _T("Failed to copy group from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
TPdfSize rightGroupSize;
PdfGroupGetSize(pRightGroup, &rightGroupSize);
// Paint group on the calculated rectangle
ComputeTargetRect(&targetRect, &rightGroupSize, FALSE);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintGroup(pGenerator, pRightGroup, &targetRect, &trans), _T("Failed to paint group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Add page number to page
if (StampPageNumber(pOutDoc, pFont, pGenerator, nRightPageIndex + 1, FALSE) == 1)
{
goto cleanup;
}
}
if (pGenerator != NULL)
PdfClose(pGenerator);
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutDocList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
cleanup:
return iReturnValue;
}
Fit pages to specific page format
Fit each page of a PDF document to a specific page format.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy pages
foreach (Page inPage in inDoc.Pages)
{
Page outPage = null;
Size pageSize = inPage.Size;
bool rotate = AllowRotate &&
(pageSize.Height >= pageSize.Width) != (TargetSize.Height >= TargetSize.Width);
Size rotatedSize = pageSize;
if (rotate)
rotatedSize = new Size { Width = pageSize.Height, Height = pageSize.Width };
if (rotatedSize.Width == TargetSize.Width && rotatedSize.Height == TargetSize.Width)
{
// If size is correct, copy page only
outPage = outDoc.CopyPage(inPage, copyOptions);
if (rotate)
outPage.Rotate(Rotation.Clockwise);
}
else
{
// Create new page of correct size and fit existing page onto it
outPage = outDoc.CreatePage(TargetSize);
// Copy page as group
Group group = outDoc.CopyPageAsGroup(inPage, copyOptions);
// Calculate scaling and position of group
double scale = Math.Min(TargetSize.Width / rotatedSize.Width,
TargetSize.Height / rotatedSize.Height);
// Calculate position
Point position = new Point
{
X = (TargetSize.Width - pageSize.Width * scale) / 2,
Y = (TargetSize.Height - pageSize.Height * scale) / 2
};
// Create content generator
using (ContentGenerator generator = new ContentGenerator(outPage.Content, false))
{
// Calculate and apply transformation
Transformation transformation = new Transformation();
transformation.Translate(position.X, position.Y);
transformation.Scale(scale, scale);
Point point = new Point()
{
X = pageSize.Width / 2.0,
Y = pageSize.Height / 2.0
};
// Rotate input file
if (rotate)
transformation.RotateAround(90, point);
generator.Transform(transformation);
// Paint group
generator.PaintGroup(group, null, null);
}
}
// Add page to output document
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Copy pages
for (Page inPage : inDoc.getPages()) {
Page outPage = null;
Size pageSize = inPage.getSize();
boolean rotate = AllowRotate
&& (pageSize.height >= pageSize.width) != (TargetSize.height >= TargetSize.width);
Size rotatedSize = pageSize;
if (rotate)
rotatedSize = new Size(pageSize.height, pageSize.width);
if (rotatedSize.width == TargetSize.width && rotatedSize.height == TargetSize.height) {
// If size is correct, copy page only
outPage = outDoc.copyPage(inPage, copyOptions);
if (rotate)
outPage.rotate(Rotation.CLOCKWISE);
} else {
// Create new page of correct size and fit existing page onto it
outPage = outDoc.createPage(TargetSize);
// Copy page as group
Group group = outDoc.copyPageAsGroup(inPage, copyOptions);
// Calculate scaling and position of group
double scale = Math.min(TargetSize.width / rotatedSize.width,
TargetSize.height / rotatedSize.height);
// Calculate position
Point position = new Point((TargetSize.width - pageSize.width * scale) / 2,
(TargetSize.height - pageSize.height * scale) / 2);
try (// Create content generator
ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
// Calculate and apply transformation
Transformation transformation = new Transformation();
transformation.translate(position.x, position.y);
transformation.scale(scale, scale);
Point point = new Point(pageSize.width / 2.0, pageSize.height / 2.0);
// Rotate input file
if (rotate)
transformation.rotateAround(90, point);
generator.transform(transformation);
// Paint group
generator.paintGroup(group, null, null);
}
}
// Add page
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy pages
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPage = NULL;
TPdfSize pageSize;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageGetSize(pInPage, &pageSize), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
BOOL rotate = bAllowRotate && (pageSize.dHeight >= pageSize.dWidth) != (targetSize.dHeight >= targetSize.dWidth);
TPdfSize rotatedSize = pageSize;
if (rotate)
{
rotatedSize.dWidth = pageSize.dHeight;
rotatedSize.dHeight = pageSize.dHeight;
}
if (rotatedSize.dWidth == targetSize.dWidth && rotatedSize.dHeight == targetSize.dWidth)
{
// If size is correct, copy page only
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (rotate)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageRotate(pOutPage, ePdfRotateClockwise), _T("Failed to rotate page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
}
}
else
{
// Create a new page of correct size and fit existing page onto it
pOutPage = PdfDocumentCreatePage(pOutDoc, &targetSize);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create a new page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy page as group
TPdfGroup* pGroup = NULL;
pGroup = PdfDocumentCopyPageAsGroup(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate scaling and position of group
double scale = MIN(targetSize.dWidth / rotatedSize.dWidth, targetSize.dHeight / rotatedSize.dHeight);
// Calculate position
TPdfPoint position;
position.dX = (targetSize.dWidth - pageSize.dWidth * scale) / 2;
position.dY = (targetSize.dHeight - pageSize.dHeight * scale) / 2;
TPdfContent* pContent = PdfPageGetContent(pOutPage);
TPdfContentGenerator* pGenerator = NULL;
// Create content generator
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate and apply transformation
TPdfTransformation* pTransformation = PdfNewTransformationIdentity();
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTransformation, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTransformationTranslate(pTransformation, position.dX, position.dY), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTransformationScale(pTransformation, scale, scale), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
TPdfPoint point;
point.dX = pageSize.dWidth / 2.0;
point.dY = pageSize.dHeight / 2.0;
// Rotate input file
if (rotate)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfTransformationRotateAround(pTransformation, 90, &point), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
}
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorTransform(pGenerator, pTransformation), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Paint form
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintGroup(pGenerator, pGroup, NULL, NULL), _T("Failed to paint the group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pTransformation != NULL)
PdfClose(pTransformation);
if (pGenerator != NULL)
PdfClose(pGenerator);
if (pGroup != NULL)
PdfClose(pGroup);
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
Place multiple pages on one page
Place four pages of a PDF document on a single page.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
PageList outPages = outDoc.Pages;
int pageCount = 0;
ContentGenerator generator = null;
Page outPage = null;
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Copy all pages from input document
foreach (Page inPage in inDoc.Pages)
{
if (pageCount == Nx * Ny)
{
// Add to output document
generator.Dispose();
outPages.Add(outPage);
outPage.Dispose();
outPage = null;
pageCount = 0;
}
if (outPage == null)
{
// Create a new output page
outPage = outDoc.CreatePage(PageSize);
generator = new ContentGenerator(outPage.Content, false);
}
// Get area where group has to be
int x = pageCount % Nx;
int y = Ny - (pageCount / Nx) - 1;
// Compute cell size
Size cellSize = new Size
{
Width = (PageSize.Width - ((Nx + 1) * Border)) / Nx,
Height = (PageSize.Height - ((Ny + 1) * Border)) / Ny
};
// Compute cell position
Point cellPosition = new Point
{
X = Border + x * (cellSize.Width + Border),
Y = Border + y * (cellSize.Height + Border)
};
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy page as group from input to output
Group group = outDoc.CopyPageAsGroup(inPage, copyOptions);
// Compute group position
Size groupSize = group.Size;
double scale = Math.Min(cellSize.Width / groupSize.Width,
cellSize.Height / groupSize.Height);
// Compute target size
Size targetSize = new Size
{
Width = groupSize.Width * scale,
Height = groupSize.Height * scale
};
// Compute position
Point targetPos = new Point
{
X = cellPosition.X + ((cellSize.Width - targetSize.Width) / 2),
Y = cellPosition.Y + ((cellSize.Height - targetSize.Height) / 2)
};
// Compute rectangle
Rectangle targetRect = new Rectangle
{
Left = targetPos.X,
Bottom = targetPos.Y,
Right = targetPos.X + targetSize.Width,
Top = targetPos.Y + targetSize.Height
};
// Add group to page
generator.PaintGroup(group, targetRect, null);
pageCount++;
}
// Add page
if (outPage != null)
{
generator.Dispose();
outPages.Add(outPage);
outPage.Dispose();
}
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null)) {
try (
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
PageList outPages = outDoc.getPages();
int pageCount = 0;
ContentGenerator generator = null;
Page outPage = null;
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Copy pages
for (Page inPage : inDoc.getPages()) {
if (pageCount == Nx * Ny) {
// Add to output document
generator.close();
outPages.add(outPage);
outPage = null;
pageCount = 0;
}
if (outPage == null) {
// Create a new output page
outPage = outDoc.createPage(PageSize);
generator = new ContentGenerator(outPage.getContent(), false);
}
// Get area where group has to be
int x = pageCount % Nx;
int y = Ny - (pageCount / Nx) - 1;
// Calculate cell size
Size cellSize = new Size((PageSize.width - ((Nx + 1) * Border)) / Nx,
(PageSize.height - ((Ny + 1) * Border)) / Ny);
// Calculate cell position
Point cellPosition = new Point(Border + x * (cellSize.width + Border),
Border + y * (cellSize.height + Border));
// Set copy option
EnumSet<CopyOption> copyoptions = EnumSet.of(CopyOption.COPY_LINKS,
CopyOption.COPY_ANNOTATIONS, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Copy page group from input to output
Group group = outDoc.copyPageAsGroup(inPage, copyoptions);
// Calculate group position
Size groupSize = group.getSize();
double scale = Math.min(cellSize.width / groupSize.width,
cellSize.height / groupSize.height);
// Calculate target size
Size targetSize = new Size(groupSize.width * scale, groupSize.height * scale);
// Calculate position
Point targetPos = new Point(cellPosition.x + ((cellSize.width - targetSize.width) / 2),
cellPosition.y + ((cellSize.height - targetSize.height) / 2));
// Calculate rectangle
Rectangle targetRect = new Rectangle(targetPos.x, targetPos.y,
targetPos.x + targetSize.width, targetPos.y + targetSize.height);
// Add group to page
generator.paintGroup(group, targetRect, null);
pageCount++;
}
// Add page
if (outPage != null) {
generator.close();
outPages.add(outPage);
}
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
int nPageCount = 0;
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Copy pages
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 0; iPage < PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage);
if (nPageCount == nNx * nNy)
{
// Add to output document
PdfClose(pGenerator);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
PdfClose(pOutPage);
pOutPage = NULL;
nPageCount = 0;
}
if (pOutPage == NULL)
{
// Create a new output page
pOutPage = PdfDocumentCreatePage(pOutDoc, &PageSize);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create a new output page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
TPdfContent* pContent = PdfPageGetContent(pOutPage);
pGenerator = PdfNewContentGenerator(pContent, FALSE);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create content generator. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
}
// Get area where group has to be
int x = nPageCount % nNx;
int y = nNy - (nPageCount / nNx) - 1;
// Calculate cell size
TPdfSize cellSize;
cellSize.dWidth = (PageSize.dWidth - ((nNx + 1) * dBorder)) / nNx;
cellSize.dHeight = (PageSize.dHeight - ((nNy + 1) * dBorder)) / nNy;
// Calculate cell position
TPdfPoint cellPosition;
cellPosition.dX = dBorder + x * (cellSize.dWidth + dBorder);
cellPosition.dY = dBorder + y * (cellSize.dHeight + dBorder);
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
// Copy page group from input to output
pGroup = PdfDocumentCopyPageAsGroup(pOutDoc, pInPage, iCopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page group from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Calculate group position
TPdfSize groupSize;
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfGroupGetSize(pGroup, &groupSize), _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
double dScale = MIN(cellSize.dWidth / groupSize.dWidth, cellSize.dHeight / groupSize.dHeight);
// Calculate target size
TPdfSize targetSize;
targetSize.dWidth = groupSize.dWidth * dScale;
targetSize.dHeight = groupSize.dHeight * dScale;
// Calculate position
TPdfPoint targetPos;
targetPos.dX = cellPosition.dX + ((cellSize.dWidth - targetSize.dWidth) / 2);
targetPos.dY = cellPosition.dY + ((cellSize.dHeight - targetSize.dHeight) / 2);
// Calculate rectangle
TPdfRectangle targetRect;
targetRect.dLeft = targetPos.dX;
targetRect.dBottom = targetPos.dY;
targetRect.dRight = targetPos.dX + targetSize.dWidth;
targetRect.dTop = targetPos.dY + targetSize.dHeight;
TPdfTransparencyParams trans;
trans.iBlendMode = ePdfBlendModeNormal;
trans.dConstAlpha = 1.0;
// Add group to page
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfContentGeneratorPaintGroup(pGenerator, pGroup, &targetRect, &trans), _T("Failed to paint the group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pGroup != NULL)
{
PdfClose(pGroup);
pGroup = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
nPageCount++;
}
// Add partially filled page
if (pOutPage != NULL)
{
PdfClose(pGenerator);
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
PdfClose(pOutPage);
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
Set page orientation
Rotate a specified page of a PDF document by 90 degrees.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outFs = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outFs, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyFormFields |
CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy all pages from input document
int currentPageNumber = 1;
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
if (pageNumbers.Contains(currentPageNumber))
{
// Rotate selected pages by 90°
outPage.Rotate(Rotation.Clockwise);
}
// Add pages to document
outDoc.Pages.Add(outPage);
currentPageNumber++;
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Set copy options and flatten annotations, form fields and signatures
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_OUTLINES, CopyOption.COPY_LINKS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.FLATTEN_ANNOTATIONS, CopyOption.FLATTEN_FORM_FIELDS,
CopyOption.FLATTEN_SIGNATURE_APPEARANCES, CopyOption.COPY_LOGIGAL_STRUCTURE);
// Loop through all pages of input
for (int i = 1; i <= inDoc.getPages().size(); i++) {
Page inPage = inDoc.getPages().get(i - 1);
// Copy page from input to output
Page outPage = outDoc.copyPage(inPage, copyOptions);
for (int pages : pageNumbers) {
if (pages == i) {
// Rotate selected pages by 90°
outPage.rotate(Rotation.CLOCKWISE);
}
}
// Add pages to document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Create output document
pOutStream = _tfopen(szOutPath, _T("wb+"));
GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
PdfCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
pOutDoc = PdfDocumentCreate(&outDescriptor, PdfDocumentGetConformance(pInDoc), NULL);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szOutPath, szErrorBuff, PdfGetLastError());
// Copy document-wide data
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc), _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Set copy options
TPdfCopyOption iCopyOptions = ePdfCopyLinks | ePdfCopyAnnotations | ePdfCopyAssociatedFiles | ePdfCopyFormFields | ePdfCopyOutlines | ePdfCopyLogicalStructure;
pInPageList = PdfDocumentGetPages(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList, _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
pOutPageList = PdfDocumentGetPages(pOutDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList, _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
// Loop through all pages of input
for (int iPage = 1; iPage <= PdfPageListGetCount(pInPageList); iPage++)
{
pInPage = PdfPageListGet(pInPageList, iPage - 1);
// Copy page from input to output
pOutPage = PdfDocumentCopyPage(pOutDoc, pInPage, iopyOptions);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
for (int i = 0; i < nPages; i++)
{
if (aPageNumbers[i] == iPage)
{
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageRotate(pOutPage, ePdfRotateClockwise), _T("Failed to rotate page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
break;
}
}
// Add page to output document
GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PdfPageListAppend(pOutPageList, pOutPage), _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (pOutPage != NULL)
{
PdfClose(pOutPage);
pOutPage = NULL;
}
if (pInPage != NULL)
{
PdfClose(pInPage);
pInPage = NULL;
}
}
int copyDocumentData(TPdfDocument * pInDoc, TPdfDocument * pOutDoc)
{
TPdfFileReferenceList* pInFileRefList;
TPdfFileReferenceList* pOutFileRefList;
TPdfConformance iConformance;
// Output intent
if (PdfDocumentGetOutputIntent(pInDoc) != NULL)
if (PdfDocumentSetOutputIntent(pOutDoc, PdfDocumentCopyColorSpace(pOutDoc, PdfDocumentGetOutputIntent(pInDoc))) == FALSE)
return FALSE;
// Metadata
if (PdfDocumentSetMetadata(pOutDoc, PdfDocumentCopyMetadata(pOutDoc, PdfDocumentGetMetadata(pInDoc))) == FALSE)
return FALSE;
// Viewer settings
if (PdfDocumentSetViewerSettings(pOutDoc, PdfDocumentCopyViewerSettings(pOutDoc, PdfDocumentGetViewerSettings(pInDoc))) == FALSE)
return FALSE;
// Associated files (for PDF/A-3 and PDF 2.0 only)
pInFileRefList = PdfDocumentGetAssociatedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetAssociatedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
iConformance = PdfDocumentGetConformance(pOutDoc);
if (iConformance != ePdfA3a && iConformance != ePDFA3b && iConformance != ePdfA3u)
{
pInFileRefList = PdfDocumentGetEmbeddedFiles(pInDoc);
pOutFileRefList = PdfDocumentGetEmbeddedFiles(pOutDoc);
if (pInFileRefList == NULL || pOutFileRefList == NULL)
return FALSE;
for (int iFileRef = 0; iFileRef < PdfFileReferenceListGetCount(pInFileRefList); iFileRef++)
if (PdfFileReferenceListAppend(pOutFileRefList, PdfDocumentCopyFileReference(pOutDoc, PdfFileReferenceListGet(pInFileRefList, iFileRef))) == FALSE)
return FALSE;
}
return TRUE;
}
Information Extraction
List bounds of page content
For each page, list the page size and the rectangular bounding box of all content on the page in PDF points (1/72 inch).
// Open input document
using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
using (Document doc = Document.Open(stream, null))
{
// Iterate over all pages
int pageNumber = 1;
foreach (Page page in doc.Pages)
{
// Print page size
Console.WriteLine("Page {0}", pageNumber++);
Size size = page.Size;
Console.WriteLine(" Size:");
Console.WriteLine(" Width: {0}", size.Width);
Console.WriteLine(" Height: {0}", size.Height);
// Compute rectangular bounding box of all content on page
Rectangle contentBox = new Rectangle()
{
Left = double.MaxValue,
Bottom = double.MaxValue,
Right = double.MinValue,
Top = double.MinValue,
};
ContentExtractor extractor = new ContentExtractor(page.Content);
foreach (ContentElement element in extractor)
{
// Enlarge the content box for each content element
Transformation tr = element.Transform;
Rectangle box = element.BoundingBox;
// The location on the page is given by the transformed points
Enlarge(ref contentBox, tr.TransformPoint(new Point() { X = box.Left, Y = box.Bottom, }));
Enlarge(ref contentBox, tr.TransformPoint(new Point() { X = box.Right, Y = box.Bottom, }));
Enlarge(ref contentBox, tr.TransformPoint(new Point() { X = box.Right, Y = box.Top, }));
Enlarge(ref contentBox, tr.TransformPoint(new Point() { X = box.Left, Y = box.Top, }));
}
Console.WriteLine(" Content bounding box:");
Console.WriteLine(" Left: {0}", contentBox.Left);
Console.WriteLine(" Bottom: {0}", contentBox.Bottom);
Console.WriteLine(" Right: {0}", contentBox.Right);
Console.WriteLine(" Top: {0}", contentBox.Top);
}
}
static void Enlarge(ref Rectangle box, Point point)
{
// Enlarge box if point lies outside of box
if (point.X < box.Left)
box.Left = point.X;
else if (point.X > box.Right)
box.Right = point.X;
if (point.Y < box.Bottom)
box.Bottom = point.Y;
else if (point.Y > box.Top)
box.Top = point.Y;
}
try (// Open input document
FileStream stream = new FileStream(path, "r");
Document doc = Document.open(stream, null)) {
// Iterate over all pages
int pageNumber = 1;
for (Page page : doc.getPages()) {
// Print page size
System.out.format("Page %d\n", pageNumber++);
Size size = page.getSize();
System.out.println(" Size:");
System.out.format(" Width: %f\n", size.getWidth());
System.out.format(" Height: %f\n", size.getHeight());
// Compute rectangular bounding box of all content on page
Rectangle contentBox = new Rectangle(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Double.MIN_VALUE);
ContentExtractor extractor = new ContentExtractor(page.getContent());
for (ContentElement element : extractor) {
// Enlarge the content box for each content element
Transformation tr = element.getTransform();
Rectangle box = element.getBoundingBox();
// The location on the page is given by the transformed points
contentBox = Enlarge(contentBox, tr.transformPoint(new Point(box.getLeft(), box.getBottom())));
contentBox = Enlarge(contentBox, tr.transformPoint(new Point(box.getRight(), box.getBottom())));
contentBox = Enlarge(contentBox, tr.transformPoint(new Point(box.getRight(), box.getTop())));
contentBox = Enlarge(contentBox, tr.transformPoint(new Point(box.getLeft(), box.getTop())));
}
System.out.println(" Content bounding box:");
System.out.format(" Left: %f\n", contentBox.getLeft());
System.out.format(" Bottom: %f\n", contentBox.getBottom());
System.out.format(" Right: %f\n", contentBox.getRight());
System.out.format(" Top: %f\n", contentBox.getTop());
}
}
static Rectangle Enlarge(Rectangle box, Point point) {
// Enlarge box if point lies outside of box
if (point.getX() < box.getLeft())
box.setLeft(point.getX());
else if (point.getX() > box.getRight())
box.setRight(point.getX());
if (point.getY() < box.getBottom())
box.setBottom(point.getY());
else if (point.getY() > box.getTop())
box.setTop(point.getY());
return box;
}
List document information of PDF
List attributes of a PDF document (i.e. conformance and encryption information) and metadata (i.e. author, title, creation date etc.).
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
// Conformance
Console.WriteLine("Conformance: {0}", inDoc.Conformance.ToString());
// Encryption information
Permission? permissions = inDoc.Permissions;
if (!permissions.HasValue)
{
Console.WriteLine("Not encrypted");
}
else
{
Console.WriteLine("Encryption:");
Console.Write(" - Permissions: ");
foreach (Enum flag in Enum.GetValues(typeof(Permission)))
if (permissions.Value.HasFlag(flag))
Console.Write("{0}, ", flag.ToString());
Console.WriteLine();
}
// Get metadata
Metadata metadata = inDoc.Metadata;
Console.WriteLine("Document information:");
// Get title
string title = metadata.Title;
if (title != null)
Console.WriteLine(" - Title: {0}", title);
// Get author
string author = metadata.Author;
if (author != null)
Console.WriteLine(" - Author: {0}", author);
// Get subject
string subject = metadata.Subject;
if (subject != null)
Console.WriteLine(" - Subject: {0}", subject);
// Get keywords
string keywords = metadata.Keywords;
if (keywords != null)
Console.WriteLine(" - Keywords: {0}", keywords);
// Get creation date
DateTimeOffset? creationDate = metadata.CreationDate2;
if (creationDate != null)
Console.WriteLine(" - Creation Date: {0}", creationDate);
// Get modification date
DateTimeOffset? modificationDate = metadata.ModificationDate2;
if (modificationDate != null)
Console.WriteLine(" - Modification Date: {0}", modificationDate);
// Get creator
string creator = metadata.Creator;
if (creator != null)
Console.WriteLine(" - Creator: {0}", creator);
// Get producer
string producer = metadata.Producer;
if (producer != null)
Console.WriteLine(" - Producer: {0}", producer);
// Custom entries
Console.WriteLine("Custom entries:");
foreach (var entry in metadata.CustomEntries)
Console.WriteLine(" - {0}: {1}", entry.Key, entry.Value);
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null)) {
// Conformance
System.out.format("Conformance: %s\n", inDoc.getConformance().toString());
// Encryption information
EnumSet<Permission> permissions = inDoc.getPermissions();
if (permissions == null) {
System.out.println("Not encrypted");
} else {
System.out.println("Encryption:");
System.out.print(" - Permissions: ");
for (Permission permission : permissions) {
System.out.format("%s, ", permission.toString());
}
System.out.println();
}
// Get metadata of input PDF
Metadata metadata = inDoc.getMetadata();
System.out.format("Document information:\n");
// Get title
String title = metadata.getTitle();
if (title != null)
System.out.format(" - Title: %s\n", title);
// Get author
String author = metadata.getAuthor();
if (author != null)
System.out.format(" - Author: %s\n", author);
// Get subject
String subject = metadata.getSubject();
if (subject != null)
System.out.format(" - Subject: %s\n", subject);
// Get keywords
String keywords = metadata.getKeywords();
if (keywords != null)
System.out.format(" - Keywords: %s\n", keywords);
// Get creation date
Calendar creationDate = metadata.getCreationDate();
if (creationDate != null) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ssZ");
format.setTimeZone(creationDate.getTimeZone());
System.out.format(" - Creation Date: %s\n", format.format(creationDate.getTime()));
}
// Get modification date
Calendar modificationDate = metadata.getModificationDate();
if (modificationDate != null) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ssZ");
format.setTimeZone(modificationDate.getTimeZone());
System.out.format(" - Modification Date: %s\n", format.format(modificationDate.getTime()));
}
// Get creator
String creator = metadata.getCreator();
if (creator != null)
System.out.format(" - Creator: %s\n", creator);
// Get producer
String producer = metadata.getProducer();
if (producer != null)
System.out.format(" - Producer: %s\n", producer);
// Custom entries
System.out.format("Custom entries:\n");
for (Map.Entry<String, String> entry : metadata.getCustomEntries().entrySet())
System.out.format(" - %s: %s\n", entry.getKey(), entry.getValue());
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Conformance
TPdfConformance conformance = PdfDocumentGetConformance(pInDoc);
if (conformance == ePdfUnk && PdfGetLastError() != ePdfSuccess)
{
GOTO_CLEANUP(szErrorBuff, PdfGetLastError());
}
_tprintf(_T("Conformance: "));
switch (conformance)
{
case ePdf10: _tprintf(_T("PDF 1.0\n")); break;
case ePdf11: _tprintf(_T("PDF 1.1\n")); break;
case ePdf12: _tprintf(_T("PDF 1.2\n")); break;
case ePdf13: _tprintf(_T("PDF 1.3\n")); break;
case ePdf14: _tprintf(_T("PDF 1.4\n")); break;
case ePdf15: _tprintf(_T("PDF 1.5\n")); break;
case ePdf16: _tprintf(_T("PDF 1.6\n")); break;
case ePdf17: _tprintf(_T("PDF 1.7\n")); break;
case ePdf20: _tprintf(_T("PDF 2.0\n")); break;
case ePdfA1b: _tprintf(_T("PDF/A1-b\n")); break;
case ePdfA1a: _tprintf(_T("PDF/A1-a\n")); break;
case ePdfA2b: _tprintf(_T("PDF/A2-b\n")); break;
case ePdfA2u: _tprintf(_T("PDF/A2-u\n")); break;
case ePdfA2a: _tprintf(_T("PDF/A2-a\n")); break;
case ePdfA3b: _tprintf(_T("PDF/A3-b\n")); break;
case ePdfA3u: _tprintf(_T("PDF/A3-u\n")); break;
case ePdfA3a: _tprintf(_T("PDF/A3-a\n")); break;
}
// Encryption information
TPdfPermission permissions;
BOOL iRet = PdfDocumentGetPermissions(pInDoc, &permissions);
if (iRet == FALSE)
{
if (PdfGetLastError() != ePdfSuccess)
GOTO_CLEANUP(szErrorBuff, PdfGetLastError());
_tprintf(_T("Not encrypted\n"));
}
else
{
_tprintf(_T("Encryption:\n"));
_tprintf(_T(" - Permissions: "));
if (permissions & ePermPrint) _tprintf(_T("Print, "));
if (permissions & ePermModify) _tprintf(_T("Modify, "));
if (permissions & ePermCopy) _tprintf(_T("Copy, "));
if (permissions & ePermAnnotate) _tprintf(_T("Annotate, "));
if (permissions & ePermFillForms) _tprintf(_T("FillForms, "));
if (permissions & ePermSupportDisabilities) _tprintf(_T("SupportDisabilities, "));
if (permissions & ePermAssemble) _tprintf(_T("Assemble, "));
if (permissions & ePermDigitalPrint) _tprintf(_T("DigitalPrint, "));
_tprintf(_T("\n"));
}
// Get metadata of input PDF
pMetadata = PdfDocumentGetMetadata(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to get metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
_tprintf(_T("Document information:\n"));
// Get title
size_t nTitle = PdfMetadataGetTitle(pMetadata, NULL, 0);
if (nTitle != 0)
{
TCHAR* szTitle = (TCHAR*)malloc(nTitle * sizeof(TCHAR));
if (szTitle != NULL)
{
PdfMetadataGetTitle(pMetadata, szTitle, nTitle);
_tprintf(_T(" - Title: %s\n"), szTitle);
free(szTitle);
}
}
// Get author
size_t nAuthor = PdfMetadataGetAuthor(pMetadata, NULL, 0);
if (nAuthor != 0)
{
TCHAR* szAuthor = (TCHAR*)malloc(nAuthor * sizeof(TCHAR));
if (szAuthor != NULL)
{
PdfMetadataGetAuthor(pMetadata, szAuthor, nAuthor);
_tprintf(_T(" - Author: %s\n"), szAuthor);
free(szAuthor);
}
}
// Get creator
size_t nCreator = PdfMetadataGetCreator(pMetadata, NULL, 0);
if (nCreator != 0)
{
TCHAR* szCreator = (TCHAR*)malloc(nCreator * sizeof(TCHAR));
if (szCreator != NULL)
{
PdfMetadataGetCreator(pMetadata, szCreator, nCreator);
_tprintf(_T(" - Creator: %s\n"), szCreator);
free(szCreator);
}
}
// Get producer
size_t nProducer = PdfMetadataGetProducer(pMetadata, NULL, 0);
if (nProducer != 0)
{
TCHAR* szProducer = (TCHAR*)malloc(nProducer * sizeof(TCHAR));
if (szProducer != NULL)
{
PdfMetadataGetProducer(pMetadata, szProducer, nProducer);
_tprintf(_T(" - Producer: %s\n"), szProducer);
free(szProducer);
}
}
// Get subject
size_t nSubject = PdfMetadataGetSubject(pMetadata, NULL, 0);
if (nSubject != 0)
{
TCHAR* szSubject = (TCHAR*)malloc(nSubject * sizeof(TCHAR));
if (szSubject != NULL)
{
PdfMetadataGetSubject(pMetadata, szSubject, nSubject);
_tprintf(_T(" - Subject: %s\n"), szSubject);
free(szSubject);
}
}
// Get keywords
size_t nKeywords = PdfMetadataGetKeywords(pMetadata, NULL, 0);
if (nKeywords != 0)
{
TCHAR* szKeywords = (TCHAR*)malloc(nKeywords * sizeof(TCHAR));
if (szKeywords != NULL)
{
PdfMetadataGetKeywords(pMetadata, szKeywords, nKeywords);
_tprintf(_T(" - Keywords: %s\n"), szKeywords);
free(szKeywords);
}
}
// Get creation date
if (PdfMetadataGetCreationDate(pMetadata, &date) == TRUE)
{
_tprintf(_T(" - Creation Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear + 1900, date.iMonth, date.iDay,
date.iHour, date.iMinute, date.iSecond,
date.iTZSign >= 0 ? '+' : '-', date.iTZHour, date.iTZMinute);
}
// Get modification date
if (PdfMetadataGetModificationDate(pMetadata, &date) == TRUE)
{
_tprintf(_T(" - Modification Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear + 1900, date.iMonth, date.iDay,
date.iHour, date.iMinute, date.iSecond,
date.iTZSign >= 0 ? '+' : '-', date.iTZHour, date.iTZMinute);
}
// Get custom entries
_tprintf(_T("Custom entries:\n"));
TPdfStringMap* pCustomEntries = PdfMetadataGetCustomEntries(pMetadata);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCustomEntries, _T("Failed to get custom entries. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
for (int i = PdfStringMapGetBegin(pCustomEntries), iEnd = PdfStringMapGetEnd(pCustomEntries); i != iEnd; i = PdfStringMapGetNext(pCustomEntries, i))
{
size_t nKeySize = PdfStringMapGetKey(pCustomEntries, i, NULL, 0);
TCHAR* szKey = (TCHAR*)malloc(nKeySize * sizeof(TCHAR));
nKeySize = PdfStringMapGetKey(pCustomEntries, i, szKey, nKeySize);
size_t nValueSize = PdfStringMapGetValue(pCustomEntries, i, NULL, 0);
TCHAR* szValue = (TCHAR*)malloc(nValueSize * sizeof(TCHAR));
nValueSize = PdfStringMapGetValue(pCustomEntries, i, szValue, nValueSize);
if (szKey && nKeySize && szValue && nValueSize)
_tprintf(_T(" - %s: %s\n"), szKey, szValue);
free (szKey);
free (szValue);
}
List Signatures in PDF
List all signature fields in a PDF document and their properties.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
SignatureFieldList signatureFields = inDoc.SignatureFields;
Console.WriteLine("Number of signature fields: {0}", signatureFields.Count);
foreach (SignatureField sig in signatureFields)
{
if (sig.IsSigned)
{
// List name
string name = sig.Name;
Console.WriteLine("- {0} fields, signed by: {1}",
sig.IsVisible ? "Visible" : "Invisible", name != null ? name : "(Unknown name)");
// List location
string location = sig.Location;
if (location != null)
Console.WriteLine(" - Location: {0}", location);
// List reason
string reason = sig.Reason;
if (reason != null)
Console.WriteLine(" - Reason: {0}", reason);
// List contact info
string contactInfo = sig.ContactInfo;
if (contactInfo != null)
Console.WriteLine(" - Contact info: {0}", contactInfo);
// List date
DateTimeOffset? date = sig.Date;
if (date != null)
Console.WriteLine(" - Date: {0}", date.Value);
}
else
Console.WriteLine("- {0} field, not signed", sig.IsVisible ? "Visible" : "Invisible");
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null)) {
SignatureFieldList signatureFields = inDoc.getSignatureFields();
System.out.format("Number of signature fields: %d\n", signatureFields.size());
for (SignatureField sig : signatureFields) {
if (sig.getIsSigned()) {
// List name
String name = sig.getName();
System.out.format("- %s field, signed by: %s\n", sig.getIsVisible() ? "Visible" : "Invisible",
name != null ? name : "(Unknown name)");
// List location
String location = sig.getLocation();
if (location != null)
System.out.format(" - Location: %s\n", location);
// List reason
String reason = sig.getReason();
if (reason != null)
System.out.format(" - Reason: %s\n", reason);
// List contact info
String contactInfo = sig.getContactInfo();
if (contactInfo != null)
System.out.format(" - Contact info: %s\n", contactInfo);
// List date
Calendar date = sig.getDate();
if (date != null) {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd' 'HH:mm:ss");
format.setTimeZone(date.getTimeZone());
System.out.format(" - Date: %s\n", format.format(date.getTime()));
}
} else {
System.out.format("- %s field, not signed\n", sig.getIsVisible() ? "Visible" : "Invisible");
}
}
}
// Open input document
pInStream = _tfopen(szInPath, _T("rb"));
GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
PdfCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
pInDoc = PdfDocumentOpen(&descriptor, _T(""));
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szInPath, szErrorBuff, PdfGetLastError());
// Get signatures of input PDF
pSignatureFields = PdfDocumentGetSignatureFields(pInDoc);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pSignatureFields, _T("Failed to get signatures of input PDF. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
_tprintf(_T("Number of signature fields: %d\n"), PdfSignatureFieldListGetCount(pSignatureFields));
for (int i = 0; i < PdfSignatureFieldListGetCount(pSignatureFields); i++)
{
pSig = PdfSignatureFieldListGet(pSignatureFields, i);
GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pSig, _T("Failed to get signature. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, PdfGetLastError());
if (PdfSignatureFieldIsSigned(pSig))
{
// List name
size_t nName = PdfSignatureFieldGetName(pSig, NULL, 0);
_tprintf(_T("- %s fields"), PdfSignatureFieldIsVisible(pSig) ? _T("Visible") : _T("Invisible"));
if (nName != 0)
{
TCHAR* szName = (TCHAR*)malloc(nName * sizeof(TCHAR));
if (szName != NULL)
{
PdfSignatureFieldGetName(pSig, szName, nName);
_tprintf(_T(", signed by: %s"), szName);
free(szName);
}
}
_tprintf(_T("\n"));
// List location
size_t nLocation = PdfSignatureFieldGetLocation(pSig, NULL, 0);
if (nLocation != 0)
{
TCHAR* szLocation = (TCHAR*)malloc(nLocation * sizeof(TCHAR));
if (szLocation != NULL)
{
PdfSignatureFieldGetLocation(pSig, szLocation, nLocation);
_tprintf(_T(" - Location: %s\n"), szLocation);
free(szLocation);
}
}
// List reason
size_t nReason = PdfSignatureFieldGetReason(pSig, NULL, 0);
if (nReason != 0)
{
TCHAR* szReason = (TCHAR*)malloc(nReason * sizeof(TCHAR));
if (szReason != NULL)
{
PdfSignatureFieldGetReason(pSig, szReason, nReason);
_tprintf(_T(" - Reason: %s\n"), szReason);
free(szReason);
}
}
// List contact info
size_t nContactInfo = PdfSignatureFieldGetContactInfo(pSig, NULL, 0);
if (nContactInfo != 0)
{
TCHAR* szContactInfo = (TCHAR*)malloc(nContactInfo * sizeof(TCHAR));
if (szContactInfo != NULL)
{
PdfSignatureFieldGetContactInfo(pSig, szContactInfo, nContactInfo);
_tprintf(_T(" - Contact info: %s\n"), szContactInfo);
free(szContactInfo);
}
}
// List date
if (PdfSignatureFieldGetDate(pSig, &date) == TRUE)
{
_tprintf(_T(" - Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear + 1900, date.iMonth, date.iDay,
date.iHour, date.iMinute, date.iSecond,
date.iTZSign >= 0 ? '+' : '-', date.iTZHour, date.iTZMinute);
}
}
else
{
_tprintf(_T("- %s field, not signed\n"), PdfSignatureFieldIsVisible(pSig) ? _T("Visible") : _T("Invisible"));
}
}
Print a table of content
Print a formatted table of content from the document outline.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
{
PrintOutlineItems(inDoc.OutlineItems, "", inDoc);
}
static void PrintOutlineItem(OutlineItem item, string indentation, Document document)
{
string title = item.Title;
Console.Out.Write("{0}{1}", indentation, title);
Destination dest = item.Destination;
if (dest != null)
{
int pageNumber = document.Pages.IndexOf(dest.Target.Page) + 1;
string dots = new string('.', 78 - indentation.Length - title.Length - pageNumber.ToString().Length);
Console.Out.Write(" {0} {1}", dots, pageNumber);
}
Console.Out.WriteLine();
PrintOutlineItems(item.Children, indentation + " ", document);
}
static void PrintOutlineItems(OutlineItemList outlineItems, string indentation, Document document)
{
foreach (var item in outlineItems)
PrintOutlineItem(item, indentation, document);
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null)) {
printOutlineItems(inDoc.getOutlineItems(), "", inDoc);
}
static void printOutlineItem(OutlineItem item, String indentation, Document document) throws ErrorCodeException {
String title = item.getTitle();
System.out.format("%s%s", indentation, title);
Destination dest = item.getDestination();
if (dest != null) {
int pageNumber = document.getPages().indexOf(dest.getTarget().getPage()) + 1;
char[] dots = new char[78 - indentation.length() - title.length() - Integer.toString(pageNumber).length()];
Arrays.fill(dots, '.');
System.out.format(" %s %d", new String(dots), pageNumber);
}
System.out.println();
printOutlineItems(item.getChildren(), indentation + " ", document);
}
static void printOutlineItems(OutlineItemList outlineItems, String indentation, Document document)
throws ErrorCodeException {
for (OutlineItem item : outlineItems)
printOutlineItem(item, indentation, document);
}
Content Modification
Remove White Text from PDF
Remove white text from all pages of a PDF. Links, annotations, form fields, outlines, logical structure, and embedded files are discarded.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Process each page
foreach (var inPage in inDoc.Pages)
{
// Create empty output page
Page outPage = outDoc.CreatePage(inPage.Size);
// Copy page content from input to output
CopyContent(inPage.Content, outPage.Content, outDoc);
// Add the new page to the output document's page list
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void CopyContent(Content inContent, Content outContent, Document outDoc)
{
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
using (ContentGenerator generator = new ContentGenerator(outContent, false))
{
// Iterate over all content elements
foreach (ContentElement inElement in extractor)
{
ContentElement outElement = null;
// Special treatment for group elements
if (inElement is GroupElement inGroupElement)
{
// Create empty output group element
GroupElement outGroupElement = outDoc.CopyGroupElementWithoutContent(inGroupElement);
outElement = outGroupElement;
// Call CopyContent() recursively for the group element's content
CopyContent(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc);
}
else
{
// Copy the content element to the output document
outElement = outDoc.CopyContentElement(inElement);
if (outElement is TextElement outTextElement)
{
// Special treatment for text element
Text text = outTextElement.Text;
// Remove all those text fragments whose fill and stroke paint is white
for (int iFragment = text.Count - 1; iFragment >= 0; iFragment--)
{
TextFragment fragment = text[iFragment];
if ((fragment.Fill == null || IsWhite(fragment.Fill.Paint)) &&
(fragment.Stroke == null || IsWhite(fragment.Stroke.Paint)))
text.RemoveAt(iFragment);
}
// Prevent appending an empty text element
if (text.Count == 0)
outElement = null;
}
}
// Append the finished output element to the content generator
if (outElement != null)
generator.AppendContentElement(outElement);
}
}
}
private static bool IsWhite(Paint paint)
{
switch (paint.ColorSpace.Type)
{
case ColorSpaceType.DeviceGray:
case ColorSpaceType.CalGray:
case ColorSpaceType.DeviceRGB:
case ColorSpaceType.CalRGB:
return paint.Color.Min() == 1.0;
case ColorSpaceType.DeviceCMYK:
return paint.Color.Max() == 0.0;
case ColorSpaceType.Lab:
case ColorSpaceType.ICCBased:
case ColorSpaceType.Indexed:
case ColorSpaceType.Separation:
case ColorSpaceType.DeviceN:
case ColorSpaceType.NChannel:
return false;
}
return false;
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Process each page
for (Page inPage : inDoc.getPages()) {
// Create empty output page
Page outPage = outDoc.createPage(inPage.getSize());
// Copy page content from input to output
CopyContent(inPage.getContent(), outPage.getContent(), outDoc);
// Add page to output document
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void CopyContent(Content inContent, Content outContent, Document outDoc) throws ErrorCodeException {
// Use a content extractor and a content generator to copy content
ContentExtractor extractor = new ContentExtractor(inContent);
try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
// Iterate over all content elements
for (ContentElement inElement : extractor) {
ContentElement outElement = null;
// Special treatment for group elements
if (inElement instanceof GroupElement) {
GroupElement inGroupElement = (GroupElement)inElement;
// Create empty output group element
GroupElement outGroupElement = outDoc.copyGroupElementWithoutContent(inGroupElement);
outElement = outGroupElement;
// Call CopyContent() recursively for the group element's content
CopyContent(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc);
} else {
// Copy the content element to the output document
outElement = outDoc.copyContentElement(inElement);
if (outElement instanceof TextElement) {
// Special treatment for text element
TextElement outTextElement = (TextElement)outElement;
Text text = outTextElement.getText();
// Remove all those text fragments whose fill and stroke paint is white
for (int iFragment = text.size() - 1; iFragment >= 0; iFragment--) {
TextFragment fragment = text.get(iFragment);
if ((fragment.getFill() == null || IsWhite(fragment.getFill().getPaint())) &&
(fragment.getStroke() == null || IsWhite(fragment.getStroke().getPaint())))
text.remove(iFragment);
}
// Prevent appending an empty text element
if (text.size() == 0)
outElement = null;
}
}
// Append the finished output element to the content generator
if (outElement != null)
generator.appendContentElement(outElement);
}
}
}
private static boolean IsWhite(Paint paint) {
double[] color = paint.getColor();
switch (paint.getColorSpace().getType()) {
case DEVICE_GRAY:
case CAL_GRAY:
case DEVICE_RGB:
case CAL_RGB:
for (int i = 0; i < color.length; i++) {
if (color[i] != 1.0)
return false;
}
return true;
case DEVICE_CMYK:
for (int i = 0; i < color.length; i++) {
if (color[i] != 0.0)
return false;
}
return true;
case LAB:
case ICC_BASED:
case INDEXED:
case SEPARATION:
case DEVICE_N:
case N_CHANNEL:
return false;
}
return false;
}
Annotations and Form Fields
Add Form Field
Add form fields to a PDF.
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
// Copy all form fields
FormFieldNodeMap inFormFields = inDoc.FormFields;
FormFieldNodeMap outFormFields = outDoc.FormFields;
foreach (KeyValuePair<string, FormFieldNode> inPair in inFormFields)
{
FormFieldNode outFormFieldNode = outDoc.CopyFormFieldNode(inPair.Value);
outFormFields.Add(new KeyValuePair<string, FormFieldNode>(inPair.Key, outFormFieldNode));
}
// Define page copy options
CopyOption copyOptions = CopyOption.CopyLinks | CopyOption.CopyAnnotations |
CopyOption.CopyAssociatedFiles | CopyOption.CopyOutlines | CopyOption.CopyLogicalStructure;
// Copy first page
Page inPage = inDoc.Pages[0];
Page outPage = outDoc.CopyPage(inPage, copyOptions);
// Add different types of form fields to the output page
AddCheckBoxField(outDoc, "Check Box ID", true, outPage, new Rectangle { Left = 50, Bottom = 300, Right = 70, Top = 320 });
AddComboBoxField(outDoc, "Combo Box ID", new string[] { "item 1", "item 2" }, "item 1", outPage, new Rectangle { Left = 50, Bottom = 260, Right = 210, Top = 280 });
AddListBoxField(outDoc, "List Box ID", new string[] { "item 1", "item 2", "item 3" }, new string[] { "item 1", "item 3" }, outPage, new Rectangle { Left = 50, Bottom = 160, Right = 210, Top = 240 });
AddRadioButtonField(outDoc, "Radio Button ID", new string[] { "A", "B", "C" }, 0, outPage, new Rectangle { Left = 50, Bottom = 120, Right = 210, Top = 140 });
AddGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle { Left = 50, Bottom = 80, Right = 210, Top = 100 });
// Add page to output document
outDoc.Pages.Add(outPage);
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
private static void AddCheckBoxField(Document doc, string id, bool isChecked, Page page, Rectangle rectangle)
{
// Create a check box field
CheckBoxField field = doc.CreateCheckBoxField();
// Add the field to the document
doc.FormFields.Add(new KeyValuePair<string, FormFieldNode>(id, field));
// Set the check box's state
field.Checked = isChecked;
// Create a widget and add it to the page's annotations
Widget widget = field.AddNewWidget(rectangle);
AnnotationList annotations = page.Annotations;
annotations.Add(widget);
}
private static void AddComboBoxField(Document doc, string id, string[] itemNames, string value, Page page, Rectangle rectangle)
{
// Create a combo box field
ComboBoxField field = doc.CreateComboBoxField();
// Add the field to the document
doc.FormFields.Add(new KeyValuePair<string, FormFieldNode>(id, field));
// Loop over all given item names
foreach (string itemName in itemNames)
{
// Create a new choice item
ChoiceItem item = field.AddNewItem(itemName);
// Check whether this is the chosen item name
if (value.Equals(itemName))
field.ChosenItem = item;
}
if (field.ChosenItem == null && !string.IsNullOrEmpty(value))
{
// If no item has been chosen then assume we want to set the editable item
field.CanEdit = true;
field.EditableItemName = value;
}
// Create a widget and add it to the page's annotations
Widget widget = field.AddNewWidget(rectangle);
AnnotationList annotations = page.Annotations;
annotations.Add(widget);
}
private static void AddListBoxField(Document doc, string id, string[] itemNames, string[] chosenNames, Page page, Rectangle rectangle)
{
// Create a list box field
ListBoxField field = doc.CreateListBoxField();
// Add the field to the document
doc.FormFields.Add(new KeyValuePair<string, FormFieldNode>(id, field));
// Allow multiple selections
field.AllowMultiSelect = true;
ChoiceItemList chosenItems = field.ChosenItems;
// Loop over all given item names
foreach (string itemName in itemNames)
{
// Create a new choice item
ChoiceItem item = field.AddNewItem(itemName);
// Check whether to add to the chosen items
if (chosenNames.Contains(itemName))
chosenItems.Add(item);
}
// Create a widget and add it to the page's annotations
Widget widget = field.AddNewWidget(rectangle);
AnnotationList annotations = page.Annotations;
annotations.Add(widget);
}
private static void AddRadioButtonField(Document doc, string id, string[] buttonNames, int chosen, Page page, Rectangle rectangle)
{
// Create a radio button field
RadioButtonField field = doc.CreateRadioButtonField();
// Get the page's annotations
AnnotationList annotations = page.Annotations;
// Add the field to the document
doc.FormFields.Add(new KeyValuePair<string, FormFieldNode>(id, field));
// We partition the given rectangle horizontally into sub-rectangles, one for each button
// Compute the width of the sub-rectangles
double buttonWidth = (rectangle.Right - rectangle.Left) / buttonNames.Length;
// Loop over all button names
for (int i = 0; i < buttonNames.Length; i++)
{
// Compute the sub-rectangle for this button
Rectangle buttonRectangle = new Rectangle()
{
Left = rectangle.Left + i * buttonWidth,
Bottom = rectangle.Bottom,
Right = rectangle.Left + (i + 1) * buttonWidth,
Top = rectangle.Top
};
// Create the button and an associated widget
RadioButton button = field.AddNewButton(buttonNames[i]);
Widget widget = button.AddNewWidget(buttonRectangle);
// Check if this is the chosen button
if (i == chosen)
field.ChosenButton = button;
// Add the widget to the page's annotations
annotations.Add(widget);
}
}
private static void AddGeneralTextField(Document doc, string id, string value, Page page, Rectangle rectangle)
{
// Create a general text field
GeneralTextField field = doc.CreateGeneralTextField();
// Add the field to the document
doc.FormFields.Add(new KeyValuePair<string, FormFieldNode>(id, field));
// Set the text value
field.Text = value;
// Create a widget and add it to the page's annotations
Widget widget = field.AddNewWidget(rectangle);
AnnotationList annotations = page.Annotations;
annotations.Add(widget);
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Copy all form fields
FormFieldNodeMap inFormFields = inDoc.getFormFields();
FormFieldNodeMap outFormFields = outDoc.getFormFields();
for (Entry<String, FormFieldNode> entry : inFormFields.entrySet())
outFormFields.put(entry.getKey(), outDoc.copyFormFieldNode(entry.getValue()));
// Define page copy options
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_LINKS, CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_FORM_FIELDS, CopyOption.COPY_OUTLINES,
CopyOption.COPY_LOGIGAL_STRUCTURE);
// Copy first page
Page inPage = inDoc.getPages().get(0);
Page outPage = outDoc.copyPage(inPage, copyOptions);
// Add different types of form fields to the output page
addCheckBoxField(outDoc, "Check Box ID", true, outPage, new Rectangle(50, 300, 70, 320));
addComboBoxField(outDoc, "Combo Box ID", new String[] { "item 1", "item 2" }, "item 1", outPage,
new Rectangle(50, 260, 210, 280));
addListBoxField(outDoc, "List Box ID", new String[] { "item 1", "item 2", "item 3" },
new String[] { "item 1", "item 3" }, outPage, new Rectangle(50, 160, 210, 240));
addRadioButtonField(outDoc, "Radio Button ID", new String[] { "A", "B", "C" }, 0, outPage,
new Rectangle(50, 120, 210, 140));
addGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle(50, 80, 210, 100));
// Add page to output document
outDoc.getPages().add(outPage);
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void addCheckBoxField(Document doc, String id, boolean isChecked, Page page, Rectangle rectangle)
throws ErrorCodeException {
// Create a check box field
CheckBoxField field = doc.createCheckBoxField();
// Add the field to the document
doc.getFormFields().put(id, field);
// Set the check box's state
field.setChecked(isChecked);
// Create a widget and add it to the page's annotations
Widget widget = field.addNewWidget(rectangle);
AnnotationList annotations = page.getAnnotations();
annotations.add(widget);
}
private static void addListBoxField(Document doc, String id, String[] itemNames, String[] chosenNames, Page page,
Rectangle rectangle) throws ErrorCodeException {
List<String> chosenNamesList = Arrays.asList(chosenNames);
// Create a list box field
ListBoxField field = doc.createListBoxField();
// Add the field to the document
doc.getFormFields().put(id, field);
// Allow multiple selections
field.setAllowMultiSelect(true);
// Get the list of chosen items
ChoiceItemList chosenItems = field.getChosenItems();
// Loop over all given item names
for (String itemName : itemNames) {
ChoiceItem item = field.addNewItem(itemName);
// Check whether to add to the chosen items
if (chosenNamesList.contains(itemName))
chosenItems.add(item);
}
// Create a widget and add it to the page's annotations
Widget widget = field.addNewWidget(rectangle);
AnnotationList annotations = page.getAnnotations();
annotations.add(widget);
}
private static void addComboBoxField(Document doc, String id, String[] itemNames, String value, Page page,
Rectangle rectangle) throws ErrorCodeException {
// Create a combo box field
ComboBoxField field = doc.createComboBoxField();
// Add the field to the document
doc.getFormFields().put(id, field);
// Loop over all given item names
for (String itemName : itemNames) {
ChoiceItem item = field.addNewItem(itemName);
// Check whether to add to the chosen items
if (value.equals(itemName))
field.setChosenItem(item);
}
if (field.getChosenItem() == null && !(value == null || value.isEmpty())) {
// If no item has been chosen then assume we want to set the editable item
field.setCanEdit(true);
field.setEditableItemName(value);
}
// Create a widget and add it to the page's annotations
Widget widget = field.addNewWidget(rectangle);
AnnotationList annotations = page.getAnnotations();
annotations.add(widget);
}
private static void addRadioButtonField(Document doc, String id, String[] buttonNames, int chosen, Page page,
Rectangle rectangle) throws ErrorCodeException {
// Create a radio button field
RadioButtonField field = doc.createRadioButtonField();
// Add the field to the document
doc.getFormFields().put(id, field);
// We partition the given rectangle horizontally into sub-rectangles, one for
// each button
// Compute the width of the sub-rectangles
double buttonWidth = (rectangle.right - rectangle.left) / buttonNames.length;
// Get the page's annotations
AnnotationList annotations = page.getAnnotations();
// Loop over all button names
for (int i = 0; i < buttonNames.length; i++) {
// Compute the sub-rectangle for this button
Rectangle buttonRectangle = new Rectangle(rectangle.left + i * buttonWidth, rectangle.bottom,
rectangle.left + (i + 1) * buttonWidth, rectangle.top);
// Create the button and an associated widget
RadioButton button = field.addNewButton(buttonNames[i]);
Widget widget = button.addNewWidget(buttonRectangle);
// Check if this is the chosen button
if (i == chosen)
field.setChosenButton(button);
// Add the widget to the page's annotations
annotations.add(widget);
}
}
private static void addGeneralTextField(Document doc, String id, String value, Page page, Rectangle rectangle)
throws ErrorCodeException {
// Create a general text field
GeneralTextField field = doc.createGeneralTextField();
// Add the field to the document
doc.getFormFields().put(id, field);
// Set the check box's state
field.setText(value);
// Create a widget and add it to the page's annotations
Widget widget = field.addNewWidget(rectangle);
AnnotationList annotations = page.getAnnotations();
annotations.add(widget);
}
Fill Form Fields
Change values of AcroForm form fields.
// Open input document
using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
using (Document inDoc = Document.Open(inStream, null))
// Create output document
using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
{
// Copy document-wide data
CopyDocumentData(inDoc, outDoc);
FormFieldNodeMap outFields = outDoc.FormFields;
// Copy all form fields
FormFieldNodeMap inFields = inDoc.FormFields;
foreach (var inPair in inFields)
{
FormFieldNode inFieldNode = inPair.Value;
FormFieldNode outFormFieldNode = outDoc.CopyFormFieldNode(inFieldNode);
outFields.Add(inPair.Key, outFormFieldNode);
}
// Find the given field, exception thrown if not found
var selectedNode = outFields.Lookup(fieldIdentifier);
if (selectedNode is FormField selectedField)
FillFormField(selectedField, fieldValue);
// Define copy options excluding form fields copying (CopyOption.CopyFormFields)
CopyOption copyOptions = CopyOption.CopyAnnotations | CopyOption.CopyAssociatedFiles |
CopyOption.CopyLinks | CopyOption.CopyLogicalStructure |
CopyOption.CopyNamedDestinations | CopyOption.CopyOutlines;
// Copy all pages
foreach (Page inPage in inDoc.Pages)
{
Page outPage = outDoc.CopyPage(inPage, copyOptions);
outDoc.Pages.Add(outPage);
}
}
private static void CopyDocumentData(Document inDoc, Document outDoc)
{
// Copy document-wide data
// Output intent
if (inDoc.OutputIntent != null)
outDoc.OutputIntent = outDoc.CopyColorSpace(inDoc.OutputIntent);
// Metadata
outDoc.Metadata = outDoc.CopyMetadata(inDoc.Metadata);
// Viewer settings
outDoc.ViewerSettings = outDoc.CopyViewerSettings(inDoc.ViewerSettings);
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
foreach (FileReference inFileRef in inDoc.AssociatedFiles)
outAssociatedFiles.Add(outDoc.CopyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.Conformance;
if (conformance != Conformance.PdfA3A &&
conformance != Conformance.PdfA3B &&
conformance != Conformance.PdfA3U)
{
FileReferenceList outEmbeddedFiles = outDoc.EmbeddedFiles;
foreach (FileReference inFileRef in inDoc.EmbeddedFiles)
outEmbeddedFiles.Add(outDoc.CopyFileReference(inFileRef));
}
}
static void FillFormField(FormField formField, string value)
{
// Apply the value, depending on the field type
if (formField is TextField textField)
{
// Set the text
textField.Text = value;
}
else if (formField is CheckBoxField checkBoxField)
{
// Check or un-check
checkBoxField.Checked = "on".Equals(value, StringComparison.CurrentCultureIgnoreCase);
}
else if (formField is RadioButtonField radioButtonField)
{
// Search the buttons for given name
foreach (var button in radioButtonField.Buttons)
{
if (value.Equals(button.ExportName))
{
// Found: Select this button
radioButtonField.ChosenButton = button;
break;
}
}
}
else if (formField is ComboBoxField comboBoxField)
{
// Search for the given item
foreach (var item in comboBoxField.Items)
{
if (value.Equals(item.DisplayName))
{
// Found: Select this item.
comboBoxField.ChosenItem = item;
break;
}
}
}
else if (formField is ListBoxField listBoxField)
{
// Search for the given item
foreach (var item in listBoxField.Items)
{
if (value.Equals(item.DisplayName))
{
// Found: Set this item as the only selected item
var itemList = listBoxField.ChosenItems;
itemList.Clear();
itemList.Add(item);
break;
}
}
}
}
try (// Open input document
FileStream inStream = new FileStream(inPath, "r");
Document inDoc = Document.open(inStream, null);
FileStream outStream = new FileStream(outPath, "rw")) {
outStream.setLength(0);
try (// Create output document
Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
// Copy document-wide data
copyDocumentData(inDoc, outDoc);
// Copy all form fields
FormFieldNodeMap inFormFields = inDoc.getFormFields();
FormFieldNodeMap outFormFields = outDoc.getFormFields();
for (Entry<String, FormFieldNode> entry : inFormFields.entrySet())
outFormFields.put(entry.getKey(), outDoc.copyFormFieldNode(entry.getValue()));
// Find the given field, exception thrown if not found
FormField selectedField = (FormField) outFormFields.lookup(fieldIdentifier);
fillFormField(selectedField, fieldValue);
// Copy pages, without CopyOption.COPY_FORM_FIELDS
EnumSet<CopyOption> copyOptions = EnumSet.of(CopyOption.COPY_ANNOTATIONS,
CopyOption.COPY_ASSOCIATED_FILES, CopyOption.COPY_LINKS, CopyOption.COPY_LOGIGAL_STRUCTURE,
CopyOption.COPY_NAMED_DESTINATIONS, CopyOption.COPY_OUTLINES);
for (Page inPage : inDoc.getPages()) {
Page outPage = outDoc.copyPage(inPage, copyOptions);
outDoc.getPages().add(outPage);
}
}
}
private static void copyDocumentData(Document inDoc, Document outDoc) throws ErrorCodeException {
// Copy document-wide data
// Output intent
if (inDoc.getOutputIntent() != null)
outDoc.setOutputIntent(outDoc.copyColorSpace(inDoc.getOutputIntent()));
// Metadata
outDoc.setMetadata(outDoc.copyMetadata(inDoc.getMetadata()));
// Viewer settings
outDoc.setViewerSettings(outDoc.copyViewerSettings(inDoc.getViewerSettings()));
// Associated files (for PDF/A-3 and PDF 2.0 only)
FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
for (FileReference inFileRef : inDoc.getAssociatedFiles())
outAssociatedFiles.add(outDoc.copyFileReference(inFileRef));
// Embedded files (in PDF/A-3, all embedded files must also be associated files)
Conformance conformance = outDoc.getConformance();
if (conformance != Conformance.PDFA_3A && conformance != Conformance.PDFA_3B && conformance != Conformance.PDFA_3U) {
FileReferenceList outEmbeddedFiles = outDoc.getEmbeddedFiles();
for (FileReference inFileRef : inDoc.getEmbeddedFiles())
outEmbeddedFiles.add(outDoc.copyFileReference(inFileRef));
}
}
private static void fillFormField(FormField formField, String value) throws ErrorCodeException {
// Apply the value, depending on the field type
if (formField instanceof TextField) {
// Set the text
TextField textField = (TextField) formField;
textField.setText(value);
} else if (formField instanceof CheckBoxField) {
// Check or un-check
CheckBoxField checkBoxField = (CheckBoxField) formField;
checkBoxField.setChecked(value.equalsIgnoreCase("on"));
} else if (formField instanceof RadioButtonField) {
// Search the buttons for given name
RadioButtonField radioButtonField = (RadioButtonField) formField;
for (RadioButton button : radioButtonField.getButtons()) {
if (value.equals(button.getExportName())) {
// Found: Select this button
radioButtonField.setChosenButton(button);
break;
}
}
} else if (formField instanceof ComboBoxField) {
// Search for the given item
ComboBoxField comboBoxField = (ComboBoxField) formField;
for (ChoiceItem item : comboBoxField.getItems()) {
if (value.equals(item.getDisplayName())) {
// Found: Select this item
comboBoxField.setChosenItem(item);
break;
}
}
} else if (formField instanceof ListBoxField) {
// Search for the given item
ListBoxField listBoxField = (ListBoxField) formField;
for (ChoiceItem item : listBoxField.getItems()) {
if (value.equals(item.getDisplayName())) {
// Found: Set this item as the only selected item
ChoiceItemList itemList = listBoxField.getChosenItems();
itemList.clear();
itemList.add(item);
break;
}
}
}
}