Toolbox add-on code samples
Start using the Toolbox add-on library with code samples. Integrate low-level access to the content of PDF files into your application in Java, .NET, and C.
info
Select a code sample in a specific language and download it. The code samples illustrate how to integrate the SDK into your projects for specific use cases. Each code sample includes a README file that gives instructions on how to run the code sample to process one or multiple files.
tip
Do you miss a specific sample and want us to include it here? Let us know through the Contact page, and we'll add it to our sample backlog.
Annotations
Add annotations to PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 // Create output document
6 using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
7 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
8
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy first page and add annotations
16 Page outPage = CopyAndAddAnnotations(outDoc, inDoc.Pages[0], copyOptions);
17
18 // Add the page to the output document's page list
19 outDoc.Pages.Add(outPage);
20
21 // Copy the remaining pages and add to the output document's page list
22 PageList inPages = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
23 PageList outPages = PageList.Copy(outDoc, inPages, copyOptions);
24 outDoc.Pages.AddRange(outPages);
25}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static Page CopyAndAddAnnotations(Document outDoc, Page inPage, PageCopyOptions copyOptions)
2{
3 // Copy page to output document
4 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
5
6 // Make a RGB color space
7 ColorSpace rgb = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);
8
9 // Get the page size for positioning annotations
10 Size pageSize = outPage.Size;
11
12 // Get the output page's list of annotations for adding annotations
13 AnnotationList annotations = outPage.Annotations;
14
15 // Create a sticky note and add to output page's annotations
16 Paint green = Paint.Create(outDoc, rgb, new double[] { 0, 1, 0 }, null);
17 Point stickyNoteTopLeft = new Point() { X = 10, Y = pageSize.Height - 10 };
18 StickyNote stickyNote = StickyNote.Create(outDoc, stickyNoteTopLeft, "Hello world!", green);
19 annotations.Add(stickyNote);
20
21 // Create an ellipse and add to output page's annotations
22 Paint blue = Paint.Create(outDoc, rgb, new double[] { 0, 0, 1 }, null);
23 Paint yellow = Paint.Create(outDoc, rgb, new double[] { 1, 1, 0 }, null);
24 Rectangle ellipseBox = new Rectangle() { Left = 10, Bottom = pageSize.Height - 60, Right = 70, Top = pageSize.Height - 20 };
25 EllipseAnnotation ellipse = EllipseAnnotation.Create(outDoc, ellipseBox, new Stroke(blue, 1.5), yellow);
26 annotations.Add(ellipse);
27
28 // Create a free text and add to output page's annotations
29 Paint yellowTransp = Paint.Create(outDoc, rgb, new double[] { 1, 1, 0 }, new Transparency(0.5));
30 Rectangle freeTextBox = new Rectangle() { Left = 10, Bottom = pageSize.Height - 170, Right = 120, Top = pageSize.Height - 70 };
31 FreeText freeText = FreeText.Create(outDoc, freeTextBox, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", yellowTransp);
32 annotations.Add(freeText);
33
34 // A highlight and a web-link to be fitted on existing page content elements
35 Highlight highlight = null;
36 WebLink webLink = null;
37 // Extract content elements from the input page
38 ContentExtractor extractor = new ContentExtractor(inPage.Content);
39 foreach (ContentElement element in extractor)
40 {
41 // Take the first text element
42 if (highlight == null && element is TextElement textElement)
43 {
44 // Get the quadrilaterals of this text element
45 QuadrilateralList quadrilaterals = new QuadrilateralList();
46 foreach (TextFragment fragment in textElement.Text)
47 quadrilaterals.Add(fragment.Transform.TransformRectangle(fragment.BoundingBox));
48
49 // Create a highlight and add to output page's annotations
50 highlight = Highlight.CreateFromQuadrilaterals(outDoc, quadrilaterals, yellow);
51 annotations.Add(highlight);
52 }
53
54 // Take the first image element
55 if (webLink == null && element is ImageElement)
56 {
57 // Get the quadrilateral of this image
58 QuadrilateralList quadrilaterals = new QuadrilateralList();
59 quadrilaterals.Add(element.Transform.TransformRectangle(element.BoundingBox));
60
61 // Create a web-link and add to the output page's links
62 webLink = WebLink.CreateFromQuadrilaterals(outDoc, quadrilaterals, "https://www.pdf-tools.com");
63 Paint red = Paint.Create(outDoc, rgb, new double[] { 1, 0, 0 }, null);
64 webLink.BorderStyle = new Stroke(red, 1.5);
65 outPage.Links.Add(webLink);
66 }
67
68 // Exit loop if highlight and webLink have been created
69 if (highlight != null && webLink != null)
70 break;
71 }
72
73 // return the finished page
74 return outPage;
75}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 // Create file stream
5 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
6 try (// Create output document
7 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
8
9 // Copy document-wide data
10 copyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy first page and add annotations
16 Page outPage = copyAndAddAnnotations(outDoc, inDoc.getPages().get(0), copyOptions);
17
18 // Add the page to the output document's page list
19 outDoc.getPages().add(outPage);
20
21 // Copy the remaining pages and add to the output document's page list
22 PageList inPages = inDoc.getPages().subList(1, inDoc.getPages().size());
23 PageList outPages = PageList.copy(outDoc, inPages, copyOptions);
24 outDoc.getPages().addAll(outPages);
25 }
26}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static Page copyAndAddAnnotations(Document outDoc, Page inPage, PageCopyOptions copyOptions) throws ConformanceException, CorruptException, IOException, UnsupportedFeatureException {
2 // Copy page to output document
3 Page outPage = Page.copy(outDoc, inPage, copyOptions);
4
5 // Make a RGB color space
6 ColorSpace rgb = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);
7
8 // Get the page size for positioning annotations
9 Size pageSize = outPage.getSize();
10
11 // Get the output page's list of annotations for adding annotations
12 AnnotationList annotations = outPage.getAnnotations();
13
14 // Create a sticky note and add to output page's annotations
15 Paint green = Paint.create(outDoc, rgb, new double[] { 0, 1, 0 }, null);
16 Point stickyNoteTopLeft = new Point(10, pageSize.height - 10 );
17 StickyNote stickyNote = StickyNote.create(outDoc, stickyNoteTopLeft, "Hello world!", green);
18 annotations.add(stickyNote);
19
20 // Create an ellipse and add to output page's annotations
21 Paint blue = Paint.create(outDoc, rgb, new double[] { 0, 0, 1 }, null);
22 Paint yellow = Paint.create(outDoc, rgb, new double[] { 1, 1, 0 }, null);
23 Rectangle ellipseBox = new Rectangle(10, pageSize.height - 60, 70, pageSize.height - 20);
24 EllipseAnnotation ellipse = EllipseAnnotation.create(outDoc, ellipseBox, new Stroke(blue, 1.5), yellow);
25 annotations.add(ellipse);
26
27 // Create a free text and add to output page's annotations
28 Paint yellowTransp = Paint.create(outDoc, rgb, new double[] { 1, 1, 0 }, new Transparency(0.5));
29 Rectangle freeTextBox = new Rectangle(10, pageSize.height - 170, 120, pageSize.height - 70);
30 FreeText freeText = FreeText.create(outDoc, freeTextBox, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", yellowTransp);
31 annotations.add(freeText);
32
33 // A highlight and a web-link to be fitted on existing page content elements
34 Highlight highlight = null;
35 WebLink webLink = null;
36 // Extract content elements from the input page
37 ContentExtractor extractor = new ContentExtractor(inPage.getContent());
38 for (ContentElement element : extractor) {
39 // Take the first text element
40 if (highlight == null && element instanceof TextElement) {
41 TextElement textElement = (TextElement)element;
42 // Get the quadrilaterals of this text element
43 QuadrilateralList quadrilaterals = new QuadrilateralList();
44 for (TextFragment fragment : textElement.getText())
45 quadrilaterals.add(fragment.getTransform().transformRectangle(fragment.getBoundingBox()));
46
47 // Create a highlight and add to output page's annotations
48 highlight = Highlight.createFromQuadrilaterals(outDoc, quadrilaterals, yellow);
49 annotations.add(highlight);
50 }
51
52 // Take the first image element
53 if (webLink == null && element instanceof ImageElement) {
54 // Get the quadrilateral of this image
55 QuadrilateralList quadrilaterals = new QuadrilateralList();
56 quadrilaterals.add(element.getTransform().transformRectangle(element.getBoundingBox()));
57
58 // Create a web-link and add to the output page's links
59 webLink = WebLink.createFromQuadrilaterals(outDoc, quadrilaterals, "https://www.pdf-tools.com");
60 Paint red = Paint.create(outDoc, rgb, new double[] { 1, 0, 0 }, null);
61 webLink.setBorderStyle(new Stroke(red, 1.5));
62 outPage.getLinks().add(webLink);
63 }
64
65 // Exit loop if highlight and webLink have been created
66 if (highlight != null && webLink != null)
67 break;
68 }
69
70 // return the finished page
71 return outPage;
72}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def copy_and_add_annotations(out_doc: Document, in_page: Page, copy_options: PageCopyOptions):
2 # Copy page to output document
3 out_page = Page.copy(out_doc, in_page, copy_options)
4
5 # Make a RGB color space
6 rgb = ColorSpace.create_process_color_space(out_doc, ProcessColorSpaceType.RGB)
7
8 # Get the page size for positioning annotations
9 page_size = out_page.size
10
11 # Get the output page's list of annotations for adding annotations
12 annotations = out_page.annotations
13
14 # Create a sticky note and add to output page's annotations
15 green = Paint.create(out_doc, rgb, [0.0, 1.0, 0.0], None)
16 sticky_note_top_left = Point(x=10.0, y=page_size.height - 10.0)
17 sticky_note = StickyNote.create(out_doc, sticky_note_top_left, "Hello world!", green)
18 annotations.append(sticky_note)
19
20 # Create an ellipse and add to output page's annotations
21 blue = Paint.create(out_doc, rgb, [0.0, 0.0, 1.0], None)
22 yellow = Paint.create(out_doc, rgb, [1.0, 1.0, 0.0], None)
23 ellipse_box = Rectangle(left=10.0, bottom=page_size.height - 60.0, right=70.0, top=page_size.height - 20.0)
24 ellipse = EllipseAnnotation.create(out_doc, ellipse_box, Stroke(blue, 1.5), yellow)
25 annotations.append(ellipse)
26
27 # Create a free text and add to output page's annotations
28 yellow_transp = Paint.create(out_doc, rgb, [1.0, 1.0, 0.0], Transparency(0.5))
29 free_text_box = Rectangle(left=10.0, bottom=page_size.height - 170.0, right=120.0, top=page_size.height - 70.0)
30 free_text = FreeText.create(out_doc, free_text_box, "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", yellow_transp)
31 annotations.append(free_text)
32
33 # A highlight and a web-link to be fitted on existing page content elements
34 highlight = None
35 web_link = None
36 # Extract content elements from the input page
37 extractor = ContentExtractor(in_page.content)
38 for element in extractor:
39 # Take the first text element
40 if highlight is None and isinstance(element, TextElement):
41 # Get the quadrilaterals of this text element
42 quadrilaterals = QuadrilateralList()
43 for fragment in element.text:
44 quadrilaterals.append(fragment.transform.transform_rectangle(fragment.bounding_box))
45
46 # Create a highlight and add to output page's annotations
47 highlight = Highlight.create_from_quadrilaterals(out_doc, quadrilaterals, yellow)
48 annotations.append(highlight)
49
50 # Take the first image element
51 if web_link is None and isinstance(element, ImageElement):
52 # Get the quadrilateral of this image
53 quadrilaterals = QuadrilateralList()
54 quadrilaterals.append(element.transform.transform_rectangle(element.bounding_box))
55
56 # Create a web-link and add to the output page's links
57 web_link = WebLink.create_from_quadrilaterals(out_doc, quadrilaterals, "https://www.pdf-tools.com")
58 red = Paint.create(out_doc, rgb, [1.0, 0.0, 0.0], None)
59 web_link.border_style = Stroke(red, 1.5)
60 out_page.links.append(web_link)
61
62 # Exit loop if highlight and web-link have been created
63 if highlight is not None and web_link is not None:
64 break
65
66 return out_page
Update annotations to PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Stream inFdfStream = new FileStream(inFdfPath, FileMode.Open, FileAccess.Read))
4using (Document inDoc = Document.OpenWithFdf(inStream, inFdfStream, null))
5{
6 // Create output document
7 using var outStream = new FileStream(outPath, FileMode.Create, FileAccess.Write);
8 using var outFdfStream = new FileStream(outFdfPath, FileMode.Create, FileAccess.Write);
9 using var outDoc = Document.CreateWithFdf(outStream, outFdfStream, inDoc.Conformance, null);
10
11 // Copy document-wide data
12 CopyDocumentData(inDoc, outDoc);
13
14 FilterAnnotations(inDoc, outDoc);
15}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void FilterAnnotations(Document inDoc, Document outDoc)
2{
3 // Define page copy options
4 var copyOptions = new PageCopyOptions
5 {
6 // Remove all annotations: we will add the filtered ones later
7 Annotations = CopyStrategy.Remove
8 };
9
10 foreach (var inPage in inDoc.Pages)
11 {
12 // Copy page to output document
13 var outPage = Page.Copy(outDoc, inPage, copyOptions);
14
15 // Hold the annotations from the input document
16 var inAnnotations = inPage.Annotations;
17
18 // Selectively copy annotations (excluding EllipseAnnotations - like Circle)
19 foreach (var inAnnotation in inAnnotations)
20 {
21 // Skip if the annotation is an EllipseAnnotation
22 if (inAnnotation is EllipseAnnotation)
23 {
24 continue;
25 }
26
27 outPage.Annotations.Add(Annotation.Copy(outDoc, inAnnotation));
28 }
29
30 // Add the page to the output document
31 outDoc.Pages.Add(outPage);
32 }
33}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def filter_annotations(in_doc: Document, out_doc: Document):
2 """Filter annotations and remove 'Ellipse' annotations."""
3 # Define page copy options
4 copy_options = PageCopyOptions()
5 # Remove all annotations: we will add the filtered ones later
6 copy_options.annotations = CopyStrategy.REMOVE
7
8 for in_page in in_doc.pages:
9 # Copy page to the output document
10 out_page = Page.copy(out_doc, in_page, copy_options)
11
12 # Hold the annotations from the input document
13 in_annotations = in_page.annotations
14
15 # Selectively copy annotations (excluding EllipseAnnotations - like Circle)
16 for in_annotation in in_annotations:
17 if not isinstance(in_annotation, EllipseAnnotation):
18 out_page.annotations.append(Annotation.copy(out_doc, in_annotation))
19
20 # Add the page to the output document
21 out_doc.pages.append(out_page)
Annotations and Form Fields
Add Form Field
1using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
2using (Document inDoc = Document.Open(inStream, null))
3
4// Create output document
5using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
6using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
7{
8 // Copy document-wide data
9 CopyDocumentData(inDoc, outDoc);
10
11 // Copy all form fields
12 FieldNodeMap inFormFields = inDoc.FormFields;
13 FieldNodeMap outFormFields = outDoc.FormFields;
14 foreach (KeyValuePair<string, FieldNode> inPair in inFormFields)
15 {
16 FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inPair.Value);
17 outFormFields.Add(inPair.Key, outFormFieldNode);
18 }
19
20 // Define page copy options
21 PageCopyOptions copyOptions = new PageCopyOptions
22 {
23 FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
24 UnsignedSignatures = CopyStrategy.Remove,
25 };
26
27 // Copy first page
28 Page inPage = inDoc.Pages[0];
29 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
30
31 // Add different types of form fields to the output page
32 AddCheckBox(outDoc, "Check Box ID", true, outPage, new Rectangle { Left = 50, Bottom = 300, Right = 70, Top = 320 });
33 AddComboBox(outDoc, "Combo Box ID", new string[] { "item 1", "item 2" }, "item 1", outPage, new Rectangle { Left = 50, Bottom = 260, Right = 210, Top = 280 });
34 AddListBox(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 });
35 AddRadioButtonGroup(outDoc, "Radio Button ID", new string[] { "A", "B", "C" }, 0, outPage, new Rectangle { Left = 50, Bottom = 120, Right = 210, Top = 140 });
36 AddGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle { Left = 50, Bottom = 80, Right = 210, Top = 100 });
37
38 // Add page to output document
39 outDoc.Pages.Add(outPage);
40
41 // Copy remaining pages and append to output document
42 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
43 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
44 outDoc.Pages.AddRange(copiedPages);
45}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddCheckBox(Document doc, string id, bool isChecked, Page page, Rectangle rectangle)
2{
3 // Create a check box
4 CheckBox checkBox = CheckBox.Create(doc);
5
6 // Add the check box to the document
7 doc.FormFields.Add(id, checkBox);
8
9 // Set the check box's state
10 checkBox.Checked = isChecked;
11
12 // Create a widget and add it to the page's widgets
13 page.Widgets.Add(checkBox.AddNewWidget(rectangle));
14}
1private static void AddComboBox(Document doc, string id, string[] itemNames, string value, Page page, Rectangle rectangle)
2{
3 // Create a combo box
4 ComboBox comboBox = ComboBox.Create(doc);
5
6 // Add the combo box to the document
7 doc.FormFields.Add(id, comboBox);
8
9 // Loop over all given item names
10 foreach (string itemName in itemNames)
11 {
12 // Create a new choice item
13 ChoiceItem item = comboBox.AddNewItem(itemName);
14
15 // Check whether this is the chosen item name
16 if (value.Equals(itemName))
17 comboBox.ChosenItem = item;
18 }
19 if (comboBox.ChosenItem == null && !string.IsNullOrEmpty(value))
20 {
21 // If no item has been chosen then assume we want to set the editable item
22 comboBox.CanEdit = true;
23 comboBox.EditableItemName = value;
24 }
25
26 // Create a widget and add it to the page's widgets
27 page.Widgets.Add(comboBox.AddNewWidget(rectangle));
28}
1private static void AddListBox(Document doc, string id, string[] itemNames, string[] chosenNames, Page page, Rectangle rectangle)
2{
3 // Create a list box
4 ListBox listBox = ListBox.Create(doc);
5
6 // Add the list box to the document
7 doc.FormFields.Add(id, listBox);
8
9 // Allow multiple selections
10 listBox.AllowMultiSelect = true;
11 ChoiceItemList chosenItems = listBox.ChosenItems;
12
13 // Loop over all given item names
14 foreach (string itemName in itemNames)
15 {
16 // Create a new choice item
17 ChoiceItem item = listBox.AddNewItem(itemName);
18
19 // Check whether to add to the chosen items
20 if (chosenNames.Contains(itemName))
21 chosenItems.Add(item);
22 }
23
24 // Create a widget and add it to the page's widgets
25 page.Widgets.Add(listBox.AddNewWidget(rectangle));
26}
1private static void AddRadioButtonGroup(Document doc, string id, string[] buttonNames, int chosen, Page page, Rectangle rectangle)
2{
3 // Create a radio button group
4 RadioButtonGroup group = RadioButtonGroup.Create(doc);
5
6 // Get the page's widgets
7 WidgetList widgets = page.Widgets;
8
9 // Add the radio button group to the document
10 doc.FormFields.Add(id, group);
11
12 // We partition the given rectangle horizontally into sub-rectangles, one for each button
13 // Compute the width of the sub-rectangles
14 double buttonWidth = (rectangle.Right - rectangle.Left) / buttonNames.Length;
15
16 // Loop over all button names
17 for (int i = 0; i < buttonNames.Length; i++)
18 {
19 // Compute the sub-rectangle for this button
20 Rectangle buttonRectangle = new Rectangle()
21 {
22 Left = rectangle.Left + i * buttonWidth,
23 Bottom = rectangle.Bottom,
24 Right = rectangle.Left + (i + 1) * buttonWidth,
25 Top = rectangle.Top
26 };
27
28 // Create the button and an associated widget
29 RadioButton button = group.AddNewButton(buttonNames[i]);
30 Widget widget = button.AddNewWidget(buttonRectangle);
31
32 // Check if this is the chosen button
33 if (i == chosen)
34 group.ChosenButton = button;
35
36 // Add the widget to the page's widgets
37 widgets.Add(widget);
38 }
39}
1private static void AddGeneralTextField(Document doc, string id, string value, Page page, Rectangle rectangle)
2{
3 // Create a general text field
4 GeneralTextField field = GeneralTextField.Create(doc);
5
6 // Add the field to the document
7 doc.FormFields.Add(id, field);
8
9 // Set the text value
10 field.Text = value;
11
12 // Create a widget and add it to the page's widgets
13 page.Widgets.Add(field.AddNewWidget(rectangle));
14}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Copy all form fields
12 FieldNodeMap inFormFields = inDoc.getFormFields();
13 FieldNodeMap outFormFields = outDoc.getFormFields();
14 for (Entry<String, FieldNode> entry : inFormFields.entrySet())
15 outFormFields.put(entry.getKey(), FieldNode.copy(outDoc, entry.getValue()));
16
17 // Define page copy options
18 PageCopyOptions copyOptions = new PageCopyOptions();
19 copyOptions.setFormFields(FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS);
20 copyOptions.setUnsignedSignatures(CopyStrategy.REMOVE);
21
22 // Copy first page
23 Page inPage = inDoc.getPages().get(0);
24 Page outPage = Page.copy(outDoc, inPage, copyOptions);
25
26 // Add different types of form fields to the output page
27 addCheckBox(outDoc, "Check Box ID", true, outPage, new Rectangle(50, 300, 70, 320));
28 addComboBox(outDoc, "Combo Box ID", new String[] { "item 1", "item 2" }, "item 1", outPage,
29 new Rectangle(50, 260, 210, 280));
30 addListBox(outDoc, "List Box ID", new String[] { "item 1", "item 2", "item 3" },
31 new String[] { "item 1", "item 3" }, outPage, new Rectangle(50, 160, 210, 240));
32 addRadioButtonGroup(outDoc, "Radio Button ID", new String[] { "A", "B", "C" }, 0, outPage,
33 new Rectangle(50, 120, 210, 140));
34 addGeneralTextField(outDoc, "Text ID", "Text", outPage, new Rectangle(50, 80, 210, 100));
35
36 // Add page to output document
37 outDoc.getPages().add(outPage);
38
39 // Copy remaining pages and append to output document
40 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
41 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
42 outDoc.getPages().addAll(copiedPages);
43 }
44}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addCheckBox(Document doc, String id, boolean isChecked, Page page, Rectangle rectangle)
2 throws ToolboxException {
3 // Create a check box
4 CheckBox checkBox = CheckBox.create(doc);
5
6 // Add the check box to the document
7 doc.getFormFields().put(id, checkBox);
8
9 // Set the check box's state
10 checkBox.setChecked(isChecked);
11
12 // Create a widget and add it to the page's widgets
13 page.getWidgets().add(checkBox.addNewWidget(rectangle));
14}
15
1private static void addListBox(Document doc, String id, String[] itemNames, String[] chosenNames, Page page,
2 Rectangle rectangle) throws ToolboxException {
3 List<String> chosenNamesList = Arrays.asList(chosenNames);
4
5 // Create a list box
6 ListBox listBox = ListBox.create(doc);
7
8 // Add the list box to the document
9 doc.getFormFields().put(id, listBox);
10
11 // Allow multiple selections
12 listBox.setAllowMultiSelect(true);
13
14 // Get the list of chosen items
15 ChoiceItemList chosenItems = listBox.getChosenItems();
16
17 // Loop over all given item names
18 for (String itemName : itemNames) {
19 ChoiceItem item = listBox.addNewItem(itemName);
20 // Check whether to add to the chosen items
21 if (chosenNamesList.contains(itemName))
22 chosenItems.add(item);
23 }
24
25 // Create a widget and add it to the page's widgets
26 page.getWidgets().add(listBox.addNewWidget(rectangle));
27}
28
1private static void addComboBox(Document doc, String id, String[] itemNames, String value, Page page,
2 Rectangle rectangle) throws ToolboxException {
3 // Create a combo box
4 ComboBox comboBox = ComboBox.create(doc);
5
6 // Add the combo box to the document
7 doc.getFormFields().put(id, comboBox);
8
9 // Loop over all given item names
10 for (String itemName : itemNames) {
11 ChoiceItem item = comboBox.addNewItem(itemName);
12 // Check whether to add to the chosen items
13 if (value.equals(itemName))
14 comboBox.setChosenItem(item);
15 }
16 if (comboBox.getChosenItem() == null && !(value == null || value.isEmpty())) {
17 // If no item has been chosen then assume we want to set the editable item
18 comboBox.setCanEdit(true);
19 comboBox.setEditableItemName(value);
20 }
21
22 // Create a widget and add it to the page's widgets
23 page.getWidgets().add(comboBox.addNewWidget(rectangle));
24}
25
1private static void addRadioButtonGroup(Document doc, String id, String[] buttonNames, int chosen, Page page,
2 Rectangle rectangle) throws ToolboxException {
3 // Create a radio button group
4 RadioButtonGroup group = RadioButtonGroup.create(doc);
5
6 // Add the radio button group to the document
7 doc.getFormFields().put(id, group);
8
9 // We partition the given rectangle horizontally into sub-rectangles, one for
10 // each button
11 // Compute the width of the sub-rectangles
12 double buttonWidth = (rectangle.right - rectangle.left) / buttonNames.length;
13
14 // Get the page's widgets
15 WidgetList widgets = page.getWidgets();
16
17 // Loop over all button names
18 for (int i = 0; i < buttonNames.length; i++) {
19 // Compute the sub-rectangle for this button
20 Rectangle buttonRectangle = new Rectangle(rectangle.left + i * buttonWidth, rectangle.bottom,
21 rectangle.left + (i + 1) * buttonWidth, rectangle.top);
22
23 // Create the button and an associated widget
24 RadioButton button = group.addNewButton(buttonNames[i]);
25 Widget widget = button.addNewWidget(buttonRectangle);
26
27 // Check if this is the chosen button
28 if (i == chosen)
29 group.setChosenButton(button);
30
31 // Add the widget to the page's widgets
32 widgets.add(widget);
33 }
34}
35
1private static void addGeneralTextField(Document doc, String id, String value, Page page, Rectangle rectangle)
2 throws ToolboxException {
3 // Create a general text field
4 GeneralTextField field = GeneralTextField.create(doc);
5
6 // Add the field to the document
7 doc.getFormFields().put(id, field);
8
9 // Set the check box's state
10 field.setText(value);
11
12 // Create a widget and add it to the page's widgets
13 page.getWidgets().add(field.addNewWidget(rectangle));
14}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_check_box(doc: Document, field_id: str, is_checked: bool, page: Page, rectangle: Rectangle):
2 # Create a check box
3 check_box = CheckBox.create(doc)
4
5 # Add the check box to the document
6 doc.form_fields[field_id] = check_box
7
8 # Set the check box's state
9 check_box.checked = is_checked
10
11 # Create a widget and add it to the page's widgets
12 page.widgets.append(check_box.add_new_widget(rectangle))
1def add_combo_box(doc: Document, field_id: str, item_names: list[str], value: str, page: Page, rectangle: Rectangle):
2 # Create a combo box
3 combo_box = ComboBox.create(doc)
4
5 # Add the combo box to the document
6 doc.form_fields[field_id] = combo_box
7
8 # Loop over all given item names
9 for item_name in item_names:
10 # Create a new choice item
11 item = combo_box.add_new_item(item_name)
12
13 # Check whether this is the chosen item name
14 if value == item_name:
15 combo_box.chosen_item = item
16
17 if combo_box.chosen_item is None and value:
18 # If no item has been chosen then assume we want to set the editable item
19 combo_box.can_edit = True
20 combo_box.editable_item_name = value
21
22 # Create a widget and add it to the page's widgets
23 page.widgets.append(combo_box.add_new_widget(rectangle))
1def add_list_box(doc: Document, field_id: str, item_names: list[str], chosen_names: list[str], page: Page, rectangle: Rectangle):
2 # Create a list box
3 list_box = ListBox.create(doc)
4
5 # Add the list box to the document
6 doc.form_fields[field_id] = list_box
7
8 # Allow multiple selections
9 list_box.allow_multi_select = True
10 chosen_items = list_box.chosen_items
11
12 # Loop over all given item names
13 for item_name in item_names:
14 # Create a new choice item
15 item = list_box.add_new_item(item_name)
16
17 # Check whether to add to the chosen items
18 if item_name in chosen_names:
19 chosen_items.append(item)
20
21 # Create a widget and add it to the page's widgets
22 page.widgets.append(list_box.add_new_widget(rectangle))
1def add_radio_button_group(doc: Document, field_id: str, button_names: list[str], chosen: int, page: Page, rectangle: Rectangle):
2 # Create a radio button group
3 group = RadioButtonGroup.create(doc)
4
5 # Get the page's widgets
6 widgets = page.widgets
7
8 # Add the radio button group to the document
9 doc.form_fields[field_id] = group
10
11 # We partition the given rectangle horizontally into sub-rectangles, one for each button
12 # Compute the width of the sub-rectangles
13 button_width = (rectangle.right - rectangle.left) / len(button_names)
14
15 # Loop over all button names
16 for i, button_name in enumerate(button_names):
17 # Compute the sub-rectangle for this button
18 button_rectangle = Rectangle(
19 left = rectangle.left + i * button_width,
20 bottom = rectangle.bottom,
21 right = rectangle.left + (i + 1) * button_width,
22 top = rectangle.top
23 )
24
25 # Create the button and associated widget
26 button = group.add_new_button(button_name)
27 widget = button.add_new_widget(button_rectangle)
28
29 # Check if this is the chosen button
30 if i == chosen:
31 group.chosen_button = button
32
33 # Add the widget to the page's widgets
34 widgets.append(widget)
1def add_general_text_field(doc: Document, field_id: str, value: str, page: Page, rectangle: Rectangle):
2 # Create a general text field
3 text_field = GeneralTextField.create(doc)
4
5 # Add the field to the document
6 doc.form_fields[field_id] = text_field
7
8 # Set the text value
9 text_field.text = value
10
11 # Create a widget and add it to the page's widgets
12 page.widgets.append(text_field.add_new_widget(rectangle))
Fill Form Fields
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 // Objects that need releasing or closing
4 TPtxPdfContent_IccBasedColorSpace* pInOutputIntent = NULL;
5 TPtxPdfContent_IccBasedColorSpace* pOutOutputIntent = NULL;
6 TPtxPdf_Metadata* pInMetadata = NULL;
7 TPtxPdf_Metadata* pOutMetadata = NULL;
8 TPtxPdfNav_ViewerSettings* pInViewerSettings = NULL;
9 TPtxPdfNav_ViewerSettings* pOutViewerSettings = NULL;
10 TPtxPdf_FileReferenceList* pInFileRefList = NULL;
11 TPtxPdf_FileReferenceList* pOutFileRefList = NULL;
12 TPtxPdf_FileReference* pInFileRef = NULL;
13 TPtxPdf_FileReference* pOutFileRef = NULL;
14
15 iReturnValue = 0;
16
17 // Output intent
18 pInOutputIntent = PtxPdf_Document_GetOutputIntent(pInDoc);
19 if (pInOutputIntent != NULL)
20 {
21 pOutOutputIntent = PtxPdfContent_IccBasedColorSpace_Copy(pOutDoc, pInOutputIntent);
22 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutOutputIntent,
23 _T("Failed to copy ICC-based color space. %s (ErrorCode: 0x%08x)\n"),
24 szErrorBuff, Ptx_GetLastError());
25 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetOutputIntent(pOutDoc, pOutOutputIntent),
26 _T("Failed to set output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
27 Ptx_GetLastError());
28 }
29 else
30 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
31 Ptx_GetLastError());
32
33 // Metadata
34 pInMetadata = PtxPdf_Document_GetMetadata(pInDoc);
35 if (pInMetadata != NULL)
36 {
37 pOutMetadata = PtxPdf_Metadata_Copy(pOutDoc, pInMetadata);
38 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)\n"),
39 szErrorBuff, Ptx_GetLastError());
40 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pOutMetadata),
41 _T("Failed to set metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
42 Ptx_GetLastError());
43 }
44 else
45 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
46 Ptx_GetLastError());
47
48 // Viewer settings
49 pInViewerSettings = PtxPdf_Document_GetViewerSettings(pInDoc);
50 if (pInViewerSettings != NULL)
51 {
52 pOutViewerSettings = PtxPdfNav_ViewerSettings_Copy(pOutDoc, pInViewerSettings);
53 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutViewerSettings,
54 _T("Failed to copy viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
55 Ptx_GetLastError());
56 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetViewerSettings(pOutDoc, pOutViewerSettings),
57 _T("Failed to set viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
58 Ptx_GetLastError());
59 }
60 else
61 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get viewer settings. %s (ErrorCode: 0x%08x)"), szErrorBuff,
62 Ptx_GetLastError());
63
64 // Associated files (for PDF/A-3 and PDF 2.0 only)
65 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
66 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of input document. %s (ErrorCode: 0x%08x)\n"),
67 szErrorBuff, Ptx_GetLastError());
68 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
69 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of output document. %s (ErrorCode: 0x%08x)\n"),
70 szErrorBuff, Ptx_GetLastError());
71 int nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
72 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of associated files. %s (ErrorCode: 0x%08x)\n"),
73 szErrorBuff, Ptx_GetLastError());
74 for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
75 {
76 pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
77 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
78 szErrorBuff, Ptx_GetLastError());
79 pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
80 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
81 szErrorBuff, Ptx_GetLastError());
82 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
83 _T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
84 Ptx_GetLastError());
85 Ptx_Release(pInFileRef);
86 pInFileRef = NULL;
87 Ptx_Release(pOutFileRef);
88 pOutFileRef = NULL;
89 }
90 Ptx_Release(pInFileRefList);
91 pInFileRefList = NULL;
92 Ptx_Release(pOutFileRefList);
93 pOutFileRefList = NULL;
94
95 // Plain embedded files
96 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
97 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
98 pInFileRefList, _T("Failed to get plain embedded files of input document %s (ErrorCode: 0x%08x)\n"),
99 szErrorBuff, Ptx_GetLastError());
100 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
101 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
102 pInFileRefList, _T("Failed to get plain embedded files of output document %s (ErrorCode: 0x%08x)\n"),
103 szErrorBuff, Ptx_GetLastError());
104 nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
105 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of plain embedded files. %s (ErrorCode: 0x%08x)\n"),
106 szErrorBuff, Ptx_GetLastError());
107 for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
108 {
109 pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
110 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
111 szErrorBuff, Ptx_GetLastError());
112 pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
113 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
114 szErrorBuff, Ptx_GetLastError());
115 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
116 _T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
117 Ptx_GetLastError());
118 Ptx_Release(pInFileRef);
119 pInFileRef = NULL;
120 Ptx_Release(pOutFileRef);
121 pOutFileRef = NULL;
122 }
123
124cleanup:
125 if (pInOutputIntent != NULL)
126 Ptx_Release(pInOutputIntent);
127 if (pOutOutputIntent != NULL)
128 Ptx_Release(pOutOutputIntent);
129 if (pInMetadata != NULL)
130 Ptx_Release(pInMetadata);
131 if (pOutMetadata != NULL)
132 Ptx_Release(pOutMetadata);
133 if (pInViewerSettings != NULL)
134 Ptx_Release(pInViewerSettings);
135 if (pOutViewerSettings != NULL)
136 Ptx_Release(pOutViewerSettings);
137 if (pInFileRefList != NULL)
138 Ptx_Release(pInFileRefList);
139 if (pOutFileRefList != NULL)
140 Ptx_Release(pOutFileRefList);
141 if (pInFileRef != NULL)
142 Ptx_Release(pInFileRef);
143 if (pOutFileRef != NULL)
144 Ptx_Release(pOutFileRef);
145 return iReturnValue;
146}
1int copyFields(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 // Objects that need releasing or closing
4 TPtxPdfForms_FieldNodeMap* pInFields = NULL;
5 TPtxPdfForms_FieldNodeMap* pOutFields = NULL;
6 TCHAR* szFieldKey = NULL;
7 TPtxPdfForms_FieldNode* pInFieldNode = NULL;
8 TPtxPdfForms_FieldNode* pOutFieldNode = NULL;
9
10 iReturnValue = 0;
11
12 pInFields = PtxPdf_Document_GetFormFields(pInDoc);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFields,
14 _T("Failed to get form fields of the input document. %s (ErrorCode: 0x%08x).\n"),
15 szErrorBuff, Ptx_GetLastError());
16
17 pOutFields = PtxPdf_Document_GetFormFields(pOutDoc);
18 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFields,
19 _T("Failed to get form fields of the output document. %s (ErrorCode: 0x%08x).\n"),
20 szErrorBuff, Ptx_GetLastError());
21
22 for (int iField = PtxPdfForms_FieldNodeMap_GetBegin(pInFields);
23 iField != PtxPdfForms_FieldNodeMap_GetEnd(pInFields);
24 iField = PtxPdfForms_FieldNodeMap_GetNext(pInFields, iField))
25 {
26 if (iField == 0)
27 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
28 Ptx_GetLastError());
29 // Get key
30 size_t nKey = PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, 0);
31 GOTO_CLEANUP_IF_ZERO(nKey, _T("Failed to get form field key\n"));
32 szFieldKey = (TCHAR*)malloc(nKey * sizeof(TCHAR*));
33 GOTO_CLEANUP_IF_NULL(szFieldKey, _T("Failed to allocate memory for field key\n"));
34 if (PtxPdfForms_FieldNodeMap_GetKey(pInFields, iField, szFieldKey, nKey) != nKey)
35 {
36 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get form field key. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
37 Ptx_GetLastError());
38 }
39 // Get input field node
40 pInFieldNode = PtxPdfForms_FieldNodeMap_GetValue(pInFields, iField);
41 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFieldNode, _T("Failed to get form field. %s (ErrorCode: 0x%08x)\n"),
42 szErrorBuff, Ptx_GetLastError());
43 // Copy field node to output document
44 pOutFieldNode = PtxPdfForms_FieldNode_Copy(pOutDoc, pInFieldNode);
45 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFieldNode, _T("Failed to copy form field. %s (ErrorCode: 0x%08x)\n"),
46 szErrorBuff, Ptx_GetLastError());
47 // Add copied field node to output fields
48 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_FieldNodeMap_Set(pOutFields, szFieldKey, pOutFieldNode),
49 _T("Failed to add form field \"%s\". %s (ErrorCode: 0x%08x)\n"), szFieldKey,
50 szErrorBuff, Ptx_GetLastError());
51 // Clean up for next iteration
52 free(szFieldKey);
53 szFieldKey = NULL;
54 Ptx_Release(pOutFieldNode);
55 pOutFieldNode = NULL;
56 Ptx_Release(pInFieldNode);
57 pInFieldNode = NULL;
58 }
59
60cleanup:
61 if (pOutFieldNode != NULL)
62 Ptx_Release(pOutFieldNode);
63 if (pInFieldNode != NULL)
64 Ptx_Release(pInFieldNode);
65 if (szFieldKey != NULL)
66 free(szFieldKey);
67 if (pOutFields != NULL)
68 Ptx_Release(pOutFields);
69 if (pInFields != NULL)
70 Ptx_Release(pInFields);
71 return iReturnValue;
72}
1int fillFormField(TPtxPdfForms_Field* pField, const TCHAR* szValue)
2{
3 // Objects that need releasing or closing
4 TPtxPdfForms_RadioButtonList* pButtonList = NULL;
5 TPtxPdfForms_RadioButton* pButton = NULL;
6 TPtxPdfForms_ChoiceItemList* pChoiceItemList = NULL;
7 TPtxPdfForms_ChoiceItem* pItem = NULL;
8 TCHAR* szName = NULL;
9
10 // Other variables
11 TPtxPdfForms_FieldType iType = 0;
12 TPtxPdfForms_CheckBox* pCheckBox = NULL;
13 TPtxPdfForms_RadioButtonGroup* pRadioButtonGroup = NULL;
14
15 iReturnValue = 0;
16 iType = PtxPdfForms_Field_GetType(pField);
17
18 if (iType == ePtxPdfForms_FieldType_GeneralTextField || iType == ePtxPdfForms_FieldType_CombTextField)
19 {
20 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_TextField_SetText((TPtxPdfForms_TextField*)pField, szValue),
21 _T("Failed to set text field value. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
22 Ptx_GetLastError());
23 }
24 else if (iType == ePtxPdfForms_FieldType_CheckBox)
25 {
26 pCheckBox = (TPtxPdfForms_CheckBox*)pField;
27 if (_tcscmp(szValue, _T("on")) == 0)
28 {
29 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, TRUE),
30 _T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
31 Ptx_GetLastError());
32 }
33 else
34 {
35 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfForms_CheckBox_SetChecked(pCheckBox, FALSE),
36 _T("Failed to set check box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
37 Ptx_GetLastError());
38 }
39 }
40 else if (iType == ePtxPdfForms_FieldType_RadioButtonGroup)
41 {
42 pRadioButtonGroup = (TPtxPdfForms_RadioButtonGroup*)pField;
43 pButtonList = PtxPdfForms_RadioButtonGroup_GetButtons(pRadioButtonGroup);
44 for (int iButton = 0; iButton < PtxPdfForms_RadioButtonList_GetCount(pButtonList); iButton++)
45 {
46 pButton = PtxPdfForms_RadioButtonList_Get(pButtonList, iButton);
47 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pButton, _T("Failed to get radio button. %s (ErrorCode: 0x%08x)\n"),
48 szErrorBuff, Ptx_GetLastError())
49 size_t nName = PtxPdfForms_RadioButton_GetExportName(pButton, szName, 0);
50 GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get radio button name\n"));
51 szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
52 GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for radio button name\n"));
53 if (PtxPdfForms_RadioButton_GetExportName(pButton, szName, nName) != nName)
54 {
55 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get radio button name. %s (ErrorCode: 0x%08x)\n"),
56 szErrorBuff, Ptx_GetLastError());
57 }
58 if (_tcscmp(szValue, szName) == 0)
59 {
60 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
61 PtxPdfForms_RadioButtonGroup_SetChosenButton(pRadioButtonGroup, pButton),
62 _T("Failed to set radio button. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
63 }
64 free(szName);
65 szName = NULL;
66 Ptx_Release(pButton);
67 pButton = NULL;
68 }
69 }
70 else if (iType == ePtxPdfForms_FieldType_ComboBox || iType == ePtxPdfForms_FieldType_ListBox)
71 {
72 pChoiceItemList = PtxPdfForms_ChoiceField_GetItems((TPtxPdfForms_ChoiceField*)pField);
73 for (int iItem = 0; iItem < PtxPdfForms_ChoiceItemList_GetCount(pChoiceItemList); iItem++)
74 {
75 pItem = PtxPdfForms_ChoiceItemList_Get(pChoiceItemList, iItem);
76 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pItem,
77 _T("Failed to get item from choice field. %s (ErrorCode: 0x%08x)\n"),
78 szErrorBuff, Ptx_GetLastError());
79 size_t nName = PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, 0);
80 GOTO_CLEANUP_IF_ZERO(nName, _T("Failed to get choice item name\n"));
81 szName = (TCHAR*)malloc(nName * sizeof(TCHAR*));
82 GOTO_CLEANUP_IF_NULL(szName, _T("Failed to allocate memory for choice item name\n"));
83 if (PtxPdfForms_ChoiceItem_GetDisplayName(pItem, szName, nName) != nName)
84 {
85 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get choice item name. %s (ErrorCode: 0x%08x)\n"),
86 szErrorBuff, Ptx_GetLastError());
87 }
88 if (_tcscmp(szValue, szName) == 0)
89 {
90 break;
91 }
92 free(szName);
93 szName = NULL;
94 Ptx_Release(pItem);
95 pItem = NULL;
96 }
97 if (pItem != NULL)
98 {
99 free(szName);
100 szName = NULL;
101 if (iType == ePtxPdfForms_FieldType_ComboBox)
102 {
103 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
104 PtxPdfForms_ComboBox_SetChosenItem((TPtxPdfForms_ComboBox*)pField, pItem),
105 _T("Failed to set choice item for combo box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
106 Ptx_GetLastError());
107 }
108 else // iType == ePtxPdfForms_FieldType_ListBox
109 {
110 Ptx_Release(pChoiceItemList);
111 pChoiceItemList = PtxPdfForms_ListBox_GetChosenItems((TPtxPdfForms_ListBox*)pField);
112 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
113 pChoiceItemList, _T("Failed to get list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
114 szErrorBuff, Ptx_GetLastError());
115 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
116 PtxPdfForms_ChoiceItemList_Clear(pChoiceItemList),
117 _T("Failed to clear list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
118 Ptx_GetLastError());
119 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
120 PtxPdfForms_ChoiceItemList_Add(pChoiceItemList, pItem),
121 _T("Failed to add item to list of chosen items for list box. %s (ErrorCode: 0x%08x)\n"),
122 szErrorBuff, Ptx_GetLastError());
123 }
124 }
125 }
126
127cleanup:
128 if (szName != NULL)
129 free(szName);
130 if (pItem == NULL)
131 Ptx_Release(pItem);
132 if (pChoiceItemList == NULL)
133 Ptx_Release(pChoiceItemList);
134 if (pButton != NULL)
135 Ptx_Release(pButton);
136 if (pButtonList != NULL)
137 Ptx_Release(pButton);
138
139 return iReturnValue;
140}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 FieldNodeMap outFields = outDoc.FormFields;
13
14 // Copy all form fields
15 FieldNodeMap inFields = inDoc.FormFields;
16 foreach (var inPair in inFields)
17 {
18 FieldNode inFieldNode = inPair.Value;
19 FieldNode outFormFieldNode = FieldNode.Copy(outDoc, inFieldNode);
20 outFields.Add(inPair.Key, outFormFieldNode);
21 }
22
23 // Find the given field, exception thrown if not found
24 var selectedNode = outFields.Lookup(fieldIdentifier);
25 if (selectedNode is Field selectedField)
26 FillFormField(selectedField, fieldValue);
27
28 // Configure copying options for updating existing widgets and removing signature fields
29 PageCopyOptions copyOptions = new PageCopyOptions
30 {
31 FormFields = FormFieldCopyStrategy.CopyAndUpdateWidgets,
32 UnsignedSignatures = CopyStrategy.Remove,
33 };
34
35 // Copy all pages and append to output document
36 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
37 outDoc.Pages.AddRange(copiedPages);
38}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1static void FillFormField(Field formField, string value)
2{
3 // Apply the value, depending on the field type
4 if (formField is TextField textField)
5 {
6 // Set the text
7 textField.Text = value;
8 }
9 else if (formField is CheckBox checkBox)
10 {
11 // Check or un-check
12 checkBox.Checked = "on".Equals(value, StringComparison.CurrentCultureIgnoreCase);
13 }
14 else if (formField is RadioButtonGroup group)
15 {
16 // Search the buttons for given name
17 foreach (var button in group.Buttons)
18 {
19 if (value.Equals(button.ExportName))
20 {
21 // Found: Select this button
22 group.ChosenButton = button;
23 break;
24 }
25 }
26 }
27 else if (formField is ComboBox comboBox)
28 {
29 // Search for the given item
30 foreach (var item in comboBox.Items)
31 {
32 if (value.Equals(item.DisplayName))
33 {
34 // Found: Select this item.
35 comboBox.ChosenItem = item;
36 break;
37 }
38 }
39 }
40 else if (formField is ListBox listBox)
41 {
42 // Search for the given item
43 foreach (var item in listBox.Items)
44 {
45 if (value.Equals(item.DisplayName))
46 {
47 // Found: Set this item as the only selected item
48 var itemList = listBox.ChosenItems;
49 itemList.Clear();
50 itemList.Add(item);
51 break;
52 }
53 }
54 }
55}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Copy all form fields
12 FieldNodeMap inFormFields = inDoc.getFormFields();
13 FieldNodeMap outFormFields = outDoc.getFormFields();
14 for (Entry<String, FieldNode> entry : inFormFields.entrySet())
15 outFormFields.put(entry.getKey(), FieldNode.copy(outDoc, entry.getValue()));
16
17 // Find the given field, exception thrown if not found
18 Field selectedField = (Field) outFormFields.lookup(fieldIdentifier);
19 fillFormField(selectedField, fieldValue);
20
21 // Configure copying options for updating existing widgets and removing signature fields
22 PageCopyOptions copyOptions = new PageCopyOptions();
23 copyOptions.setFormFields(FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS);
24 copyOptions.setUnsignedSignatures(CopyStrategy.REMOVE);
25
26 // Copy all pages and append to output document
27 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
28 outDoc.getPages().addAll(copiedPages);
29 }
30}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void fillFormField(Field formField, String value) throws ToolboxException {
2 // Apply the value, depending on the field type
3 if (formField instanceof TextField) {
4 // Set the text
5 TextField textField = (TextField) formField;
6 textField.setText(value);
7 } else if (formField instanceof CheckBox) {
8 // Check or un-check
9 CheckBox checkBox = (CheckBox) formField;
10 checkBox.setChecked(value.equalsIgnoreCase("on"));
11 } else if (formField instanceof RadioButtonGroup) {
12 // Search the buttons for given name
13 RadioButtonGroup group = (RadioButtonGroup) formField;
14 for (RadioButton button : group.getButtons()) {
15 if (value.equals(button.getExportName())) {
16 // Found: Select this button
17 group.setChosenButton(button);
18 break;
19 }
20 }
21 } else if (formField instanceof ComboBox) {
22 // Search for the given item
23 ComboBox comboBox = (ComboBox) formField;
24 for (ChoiceItem item : comboBox.getItems()) {
25 if (value.equals(item.getDisplayName())) {
26 // Found: Select this item
27 comboBox.setChosenItem(item);
28 break;
29 }
30 }
31 } else if (formField instanceof ListBox) {
32 // Search for the given item
33 ListBox listBox = (ListBox) formField;
34 for (ChoiceItem item : listBox.getItems()) {
35 if (value.equals(item.getDisplayName())) {
36 // Found: Set this item as the only selected item
37 ChoiceItemList itemList = listBox.getChosenItems();
38 itemList.clear();
39 itemList.add(item);
40 break;
41 }
42 }
43 }
44}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def fill_form_field(form_field: Field, value: str):
2 """Set the value of a form field based on its type."""
3 if isinstance(form_field, TextField):
4 form_field.text = value
5 elif isinstance(form_field, CheckBox):
6 form_field.checked = value.lower() == "on"
7 elif isinstance(form_field, RadioButtonGroup):
8 for button in form_field.buttons:
9 if button.export_name == value:
10 form_field.chosen_button = button
11 break
12 elif isinstance(form_field, ComboBox):
13 for item in form_field.items:
14 if item.display_name == value:
15 form_field.chosen_item = item
16 break
17 elif isinstance(form_field, ListBox):
18 for item in form_field.items:
19 if item.display_name == value:
20 form_field.chosen_items.clear()
21 form_field.chosen_items.append(item)
22 break
Content Addition
Add barcode to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create file stream
10pFontStream = _tfopen(szFontPath, _T("rb"));
11GOTO_CLEANUP_IF_NULL(pFontStream, _T("Failed to open font file."));
12PtxSysCreateFILEStreamDescriptor(&fontDescriptor, pFontStream, 0);
13
14// Create output document
15pOutStream = _tfopen(szOutPath, _T("wb+"));
16GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
17PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
18iConformance = PtxPdf_Document_GetConformance(pInDoc);
19pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
21 szOutPath, szErrorBuff, Ptx_GetLastError());
22pFont = PtxPdfContent_Font_Create(pOutDoc, &fontDescriptor, TRUE);
23GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
24 Ptx_GetLastError());
25
26// Copy document-wide data
27GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
28 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
29 Ptx_GetLastError());
30
31// Configure copy options
32pCopyOptions = PtxPdf_PageCopyOptions_New();
33
34// Get page lists of input and output document
35pInPageList = PtxPdf_Document_GetPages(pInDoc);
36GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
37 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
38 szErrorBuff, Ptx_GetLastError());
39pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
40GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
41 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43
44// Copy first page
45pInPage = PtxPdf_PageList_Get(pInPageList, 0);
46GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
47 szErrorBuff, Ptx_GetLastError());
48pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
49GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
50 Ptx_GetLastError());
51
52// Add barcode image to copied page
53if (addBarcode(pOutDoc, pOutPage, szBarcode, pFont, 50) != 0)
54 goto cleanup;
55
56// Add page to output document
57GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
58 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
59 szErrorBuff, Ptx_GetLastError());
60
61// Get remaining pages from input
62pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
63GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
64 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
65 szErrorBuff, Ptx_GetLastError());
66
67// Copy remaining pages to output
68pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
69GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
70 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
71 szErrorBuff, Ptx_GetLastError());
72
73// Add the copied pages to the output document
74GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
75 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
76 szErrorBuff, Ptx_GetLastError());
77
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addBarcode(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szBarcode, TPtxPdfContent_Font* pFont,
2 double dFontSize)
3{
4 TPtxPdfContent_Content* pContent = NULL;
5 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
6 TPtxPdfContent_Text* pBarcodeText = NULL;
7 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Create text object
17 pBarcodeText = PtxPdfContent_Text_Create(pOutDoc);
18 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pBarcodeText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
19 szErrorBuff, Ptx_GetLastError());
20
21 // Create text generator
22 pTextGenerator = PtxPdfContent_TextGenerator_New(pBarcodeText, pFont, dFontSize, NULL);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
24 szErrorBuff, Ptx_GetLastError());
25
26 // Calculate position
27 TPtxGeomReal_Size size;
28 PtxPdf_Page_GetSize(pOutPage, &size);
29 TPtxGeomReal_Point position;
30 double dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szBarcode);
31 GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
32 double dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
33 GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontAscent, _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
34 double dFontDescent = PtxPdfContent_Font_GetDescent(pFont);
35 GOTO_CLEANUP_IF_NEGATIVE_PRINT_ERROR(dFontDescent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff,
36 Ptx_GetLastError());
37 position.dX = size.dWidth - (dTextWidth + dBorder);
38 position.dY = size.dHeight - (dFontSize * (dFontAscent + dFontDescent) + dBorder);
39
40 // Move to position
41 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
42 _T("Failed to move to position %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
43 Ptx_GetLastError());
44 // Add given barcode string
45 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szBarcode),
46 _T("Failed to add barcode string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
47 Ptx_GetLastError());
48
49 // Close text generator
50 if (pTextGenerator != NULL)
51 PtxPdfContent_TextGenerator_Close(pTextGenerator);
52
53 // Paint the positioned barcode text
54 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pBarcodeText),
55 _T("Failed to paint the positioned barcode text. %s (ErrorCode: 0x%08x).\n"),
56 szErrorBuff, Ptx_GetLastError());
57
58cleanup:
59 if (pGenerator != NULL)
60 PtxPdfContent_ContentGenerator_Close(pGenerator);
61
62 return iReturnValue;
63}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create file stream
6using (Stream fontStream = new FileStream(fontPath, FileMode.Open, FileAccess.Read))
7
8// Create output document
9using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
10using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
11{
12 // Copy document-wide data
13 CopyDocumentData(inDoc, outDoc);
14
15 // Create embedded font in output document
16 Font font = Font.Create(outDoc, fontStream, true);
17
18 // Define page copy options
19 PageCopyOptions copyOptions = new PageCopyOptions();
20
21 // Copy first page, add barcode, and append to output document
22 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
23 AddBarcode(outDoc, outPage, barcode, font, 50);
24 outDoc.Pages.Add(outPage);
25
26 // Copy remaining pages and append to output document
27 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
28 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
29 outDoc.Pages.AddRange(copiedPages);
30}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddBarcode(Document outputDoc, Page outPage, string barcode,
2 Font font, double fontSize)
3{
4 // Create content generator
5 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
6
7 // Create text object
8 Text barcodeText = Text.Create(outputDoc);
9
10 // Create text generator
11 using (TextGenerator textGenerator = new TextGenerator(barcodeText, font, fontSize, null))
12 {
13 // Calculate position
14 Point position = new Point
15 {
16 X = outPage.Size.Width - (textGenerator.GetWidth(barcode) + Border),
17 Y = outPage.Size.Height - (fontSize * (font.Ascent + font.Descent) + Border)
18 };
19
20 // Move to position
21 textGenerator.MoveTo(position);
22 // Add given barcode string
23 textGenerator.ShowLine(barcode);
24 }
25 // Paint the positioned barcode text
26 gen.PaintText(barcodeText);
27}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 // Create file stream
5 FileStream fontStream = new FileStream(fontPath, FileStream.Mode.READ_ONLY);
6 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
7 try (// Create output document
8 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
9
10 // Copy document-wide data
11 copyDocumentData(inDoc, outDoc);
12
13 // Create embedded font in output document
14 Font font = Font.create(outDoc, fontStream, true);
15
16 // Define page copy options
17 PageCopyOptions copyOptions = new PageCopyOptions();
18
19 // Copy first page, add barcode, and append to output document
20 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
21 addBarcode(outDoc, outPage, barcode, font, 50);
22 outDoc.getPages().add(outPage);
23
24 // Copy remaining pages and append to output document
25 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
26 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
27 outDoc.getPages().addAll(copiedPages);
28 }
29}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addBarcode(Document outputDoc, Page outPage, String barcode, Font font, double fontSize) throws ToolboxException, IOException {
2 try (// Create content generator
3 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
4 // Create text object
5 Text barcodeText = Text.create(outputDoc);
6
7 // Create a text generator
8 TextGenerator textgenerator = new TextGenerator(barcodeText, font, fontSize, null);
9
10 // Calculate position
11 Point position = new Point(outPage.getSize().width - (textgenerator.getWidth(barcode) + Border),
12 outPage.getSize().height - (fontSize * (font.getAscent() + font.getDescent()) + Border));
13
14 // Move to position
15 textgenerator.moveTo(position);
16 // Add given barcode string
17 textgenerator.showLine(barcode);
18 // Close text generator
19 textgenerator.close();
20
21 // Paint the positioned barcode text
22 generator.paintText(barcodeText);
23 }
24}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_barcode(out_doc: Document, out_page: Page, barcode: str, font: Font, font_size: float):
2 # Create content generator
3 with ContentGenerator(out_page.content, False) as gen:
4 # Create text object
5 barcode_text = Text.create(out_doc)
6
7 # Create text generator
8 with TextGenerator(barcode_text, font, font_size, None) as text_generator:
9 # Calculate position
10 position = Point(x=out_page.size.width - (text_generator.get_width(barcode) + border),
11 y=out_page.size.height - (font_size * (font.ascent + font.descent) + border))
12
13 # Move to position
14 text_generator.move_to(position)
15 # Add given barcode string
16 text_generator.show_line(barcode)
17
18 # Paint the positioned barcode text
19 gen.paint_text(barcode_text)
Add Data Matrix to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Configure copy options
29pCopyOptions = PtxPdf_PageCopyOptions_New();
30
31// Get page lists of input and output document
32pInPageList = PtxPdf_Document_GetPages(pInDoc);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
34 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
35 szErrorBuff, Ptx_GetLastError());
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40
41// Copy first page
42pInPage = PtxPdf_PageList_Get(pInPageList, 0);
43GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
44 szErrorBuff, Ptx_GetLastError());
45pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
46GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
47 Ptx_GetLastError());
48
49// Add datamatrix image to copied page
50if (addDataMatrix(pOutDoc, pOutPage, szDatamatrixPath) != 0)
51 goto cleanup;
52
53// Add page to output document
54GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
55 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
56 szErrorBuff, Ptx_GetLastError());
57
58// Get remaining pages from input
59pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
60GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
61 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
62 szErrorBuff, Ptx_GetLastError());
63
64// Copy remaining pages to output
65pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
67 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69
70// Add the copied pages to the output document
71GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
72 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
73 szErrorBuff, Ptx_GetLastError());
74
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addDataMatrix(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szDataMatrixPath)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxSys_StreamDescriptor datamatrixDescriptor;
6 FILE* pDatamatrixStream = NULL;
7 TPtxPdfContent_Image* pDatamatrix = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Import data matrix
17 pDatamatrixStream = _tfopen(szDataMatrixPath, _T("rb"));
18 GOTO_CLEANUP_IF_NULL(pDatamatrixStream, _T("Failed to open data matrix file \"%s\".\n"), szDataMatrixPath);
19 PtxSysCreateFILEStreamDescriptor(&datamatrixDescriptor, pDatamatrixStream, 0);
20
21 // Create image object for data matrix
22 pDatamatrix = PtxPdfContent_Image_Create(pOutDoc, &datamatrixDescriptor);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pDatamatrix, _T("Failed to create image object. %s (ErrorCode: 0x%08x).\n"),
24 szErrorBuff, Ptx_GetLastError());
25
26 // Data matrix size
27 double dDatamatrixSize = 85.0;
28
29 // Calculate Rectangle for data matrix
30 TPtxGeomReal_Size size;
31 PtxPdf_Page_GetSize(pOutPage, &size);
32 TPtxGeomReal_Rectangle rect;
33 rect.dLeft = dBorder;
34 rect.dBottom = size.dHeight - (dDatamatrixSize + dBorder);
35 rect.dRight = dDatamatrixSize + dBorder;
36 rect.dTop = size.dHeight - dBorder;
37
38 // Paint image of data matrix into the specified rectangle
39 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
40 PtxPdfContent_ContentGenerator_PaintImage(pGenerator, pDatamatrix, &rect),
41 _T("Failed to paint data matrix into the specified rectangle. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
42 Ptx_GetLastError());
43
44cleanup:
45 if (pGenerator != NULL)
46 PtxPdfContent_ContentGenerator_Close(pGenerator);
47 if (pContent != NULL)
48 Ptx_Release(pContent);
49
50 return iReturnValue;
51}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy first page, add datamatrix image, and append to output document
16 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
17 AddDataMatrix(outDoc, outPage, datamatrixPath);
18 outDoc.Pages.Add(outPage);
19
20 // Copy remaining pages and append to output document
21 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
22 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
23 outDoc.Pages.AddRange(copiedPages);
24}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddDataMatrix(Document document, Page page, string datamatrixPath)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(page.Content, false);
5
6 // Import data matrix
7 using Stream inMatrix = new FileStream(datamatrixPath, FileMode.Open, FileAccess.Read);
8
9 // Create image object for data matrix
10 Image datamatrix = Image.Create(document, inMatrix);
11
12 // Data matrix size
13 double datamatrixSize = 85;
14
15 // Calculate Rectangle for data matrix
16 Rectangle rect = new Rectangle
17 {
18 Left = Border,
19 Bottom = page.Size.Height - (datamatrixSize + Border),
20 Right = datamatrixSize + Border,
21 Top = page.Size.Height - Border
22 };
23
24 // Paint image of data matrix into the specified rectangle
25 generator.PaintImage(datamatrix, rect);
26}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy first page, add data matrix image, and append to output document
15 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
16 addDatamatrix(outDoc, outPage, datamatrixPath);
17 outDoc.getPages().add(outPage);
18
19 // Copy remaining pages and append to output document
20 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
21 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
22 outDoc.getPages().addAll(copiedPages);
23 }
24}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addDatamatrix(Document document, Page page, String datamatrixPath)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(page.getContent(), false);
5 // Import data matrix
6 FileStream inMatrix = new FileStream(datamatrixPath, FileStream.Mode.READ_ONLY)) {
7
8 // Create image object for data matrix
9 Image datamatrix = Image.create(document, inMatrix);
10
11 // Data matrix size
12 double datamatrixSize = 85;
13
14 // Calculate Rectangle for data matrix
15 Rectangle rect = new Rectangle(Border, page.getSize().height - (datamatrixSize + Border),
16 datamatrixSize + Border, page.getSize().height - Border);
17
18 // Paint image of data matrix into the specified rectangle
19 generator.paintImage(datamatrix, rect);
20 }
21}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_data_matrix(document: Document, page: Page, data_matrix_path: str):
2 # Create content generator
3 with ContentGenerator(out_page.content, False) as generator:
4
5 # Import data matrix
6 with io.FileIO(data_matrix_path, 'rb') as in_matrix_stream:
7
8 # Create image object for data matrix
9 data_matrix = Image.create(document, in_matrix_stream)
10
11 # Data matrix size
12 data_matrix_size = 85
13
14 # Calculate Rectangle for data matrix
15 rect = Rectangle(x=border, y=page.size.height - (data_matrix_size + border), width=data_matrix_size + border, height=page.size.height - border)
16
17 # Paint the positioned barcode text
18 generator.paint_image(data_matrix, rect)
Add image to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Get input and output page lists
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
33 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
34 szErrorBuff, Ptx_GetLastError());
35
36// Copy pages preceding selected page
37pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 0, iPageNumber - 1);
38GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange, _T("Failed to get page range. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
41GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange, _T("Failed to copy page range. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
44 _T("Failed to add page range. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
45 Ptx_GetLastError());
46Ptx_Release(pInPageRange);
47pInPageRange = NULL;
48Ptx_Release(pOutPageRange);
49pOutPageRange = NULL;
50
51// Copy selected page an add image
52pInPage = PtxPdf_PageList_Get(pInPageList, iPageNumber - 1);
53GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
54 Ptx_GetLastError());
55pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
56GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
57 Ptx_GetLastError());
58if (addImage(pOutDoc, pOutPage, szImagePath, 150.0, 150.0) != 0)
59 goto cleanup;
60GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
61 _T("Failed to add page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
62 Ptx_GetLastError());
63
64// Copy remaining pages
65pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
67 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
70GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
71 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
72 szErrorBuff, Ptx_GetLastError());
73GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
74 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
75 szErrorBuff, Ptx_GetLastError());
76
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addImage(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szImagePath, double x, double y)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxSys_StreamDescriptor imageDescriptor;
6 FILE* pImageStream = NULL;
7 TPtxPdfContent_Image* pImage = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13
14 // Load image from input path
15 pImageStream = _tfopen(szImagePath, _T("rb"));
16 PtxSysCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);
17
18 // Create image object
19 pImage = PtxPdfContent_Image_Create(pOutDoc, &imageDescriptor);
20
21 double dResolution = 150.0;
22
23 TPtxGeomInt_Size size;
24 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Image_GetSize(pImage, &size),
25 _T("Failed to get image size. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28 // Calculate Rectangle for data matrix
29 TPtxGeomReal_Rectangle rect;
30 rect.dLeft = x;
31 rect.dBottom = y;
32 rect.dRight = x + (double)size.iWidth * 72.0 / dResolution;
33 rect.dTop = y + (double)size.iHeight * 72.0 / dResolution;
34
35 // Paint image into the specified rectangle
36 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintImage(pGenerator, pImage, &rect),
37 _T("Failed to paint image. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
38 Ptx_GetLastError());
39
40cleanup:
41 if (pGenerator != NULL)
42 PtxPdfContent_ContentGenerator_Close(pGenerator);
43 if (pContent != NULL)
44 Ptx_Release(pContent);
45
46 return iReturnValue;
47}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy pages preceding selected page and append to output document
16 PageList inPageRange = inDoc.Pages.GetRange(0, pageNumber - 1);
17 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
18 outDoc.Pages.AddRange(copiedPages);
19
20 // Copy selected page, add image, and append to output document
21 Page outPage = Page.Copy(outDoc, inDoc.Pages[pageNumber - 1], copyOptions);
22 AddImage(outDoc, outPage, imagePath, 150, 150);
23 outDoc.Pages.Add(outPage);
24
25 // Copy remaining pages and append to output document
26 inPageRange = inDoc.Pages.GetRange(pageNumber, inDoc.Pages.Count - pageNumber);
27 copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
28 outDoc.Pages.AddRange(copiedPages);
29}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddImage(Document document, Page page, string imagePath, double x, double y)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(page.Content, false);
5
6 // Load image from input path
7 using Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
8
9 // Create image object
10 Image image = Image.Create(document, inImage);
11 double resolution = 150;
12
13 // Calculate rectangle for image
14 PdfTools.Toolbox.Geometry.Integer.Size size = image.Size;
15 Rectangle rect = new Rectangle
16 {
17 Left = x,
18 Bottom = y,
19 Right = x + size.Width * 72 / resolution,
20 Top = y + size.Height * 72 / resolution
21 };
22
23 // Paint image into the specified rectangle
24 generator.PaintImage(image, rect);
25}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy pages preceding selected page and append to output document
15 PageList inPageRange = inDoc.getPages().subList(0, pageNumber - 1);
16 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
17 outDoc.getPages().addAll(copiedPages);
18
19 // Copy selected page, add image, and append to output document
20 Page outPage = Page.copy(outDoc, inDoc.getPages().get(pageNumber - 1), copyOptions);
21 addImage(outDoc, outPage, imagePath, 150, 150);
22 outDoc.getPages().add(outPage);
23
24 // Copy remaining pages and append to output document
25 inPageRange = inDoc.getPages().subList(pageNumber, inDoc.getPages().size());
26 copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
27 outDoc.getPages().addAll(copiedPages);
28 }
29}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addImage(Document document, Page outPage, String imagePath, double x, double y)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
5 // Load image from input path
6 FileStream inImage = new FileStream(imagePath, FileStream.Mode.READ_ONLY)) {
7 // Create image object
8 Image image = Image.create(document, inImage);
9
10 double resolution = 150;
11
12 // Calculate rectangle for image
13 Size size = image.getSize();
14 Rectangle rect = new Rectangle(x, y, x + size.getWidth() * 72 / resolution,
15 y + size.getHeight() * 72 / resolution);
16
17 // Paint image into the specified rectangle
18 generator.paintImage(image, rect);
19 }
20}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_image(document: Document, page: Page, image_path: str, x: float, y: float):
2 # Create content generator
3 with ContentGenerator(page.content, False) as generator:
4
5 # Load image from input path
6 with io.FileIO(image_path, 'rb') as in_image_stream:
7 # Create image object
8 image = Image.create(document, in_image_stream)
9 resolution = 150
10
11 # Calculate rectangle for image
12 size = image.size
13 rect = Rectangle(
14 left=x,
15 bottom=y,
16 right=x + size.width * 72 / resolution,
17 top=y + size.height * 72 / resolution
18 )
19
20 # Paint image into the specified rectangle
21 generator.paint_image(image, rect)
Add image mask to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
7 Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(_T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
16 Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Get the device color space
24TPtxPdfContent_ColorSpace* pColorSpace =
25 PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
26GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the device color space. %s (ErrorCode: 0x%08x).\n"),
27 szErrorBuff, Ptx_GetLastError());
28
29// Chose the RGB color value
30double color[] = {1.0, 0.0, 0.0};
31size_t nColor = sizeof(color) / sizeof(double);
32
33// Create paint object
34pPaint = PtxPdfContent_Paint_Create(pOutDoc, pColorSpace, color, nColor, NULL);
35GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"),
36 szErrorBuff, Ptx_GetLastError());
37
38// Configure copy options
39pCopyOptions = PtxPdf_PageCopyOptions_New();
40
41// Get input and output page lists
42pInPageList = PtxPdf_Document_GetPages(pInDoc);
43GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
44 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
45 szErrorBuff, Ptx_GetLastError());
46pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
47GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
48 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
49 szErrorBuff, Ptx_GetLastError());
50
51// Copy first page an add image mask
52pInPage = PtxPdf_PageList_Get(pInPageList, 0);
53GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
54 Ptx_GetLastError());
55pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
56GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
57 Ptx_GetLastError());
58if (addImageMask(pOutDoc, pOutPage, szImageMaskPath, 250, 150) != 0)
59 goto cleanup;
60GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
61 _T("Failed to add page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
62 Ptx_GetLastError());
63
64// Copy remaining pages
65pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
67 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
70GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
71 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
72 szErrorBuff, Ptx_GetLastError());
73GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
74 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
75 szErrorBuff, Ptx_GetLastError());
76
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addImageMask(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szImageMaskPath, double x, double y)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 FILE* pImageStream = NULL;
6 TPtxSys_StreamDescriptor imageDescriptor;
7 TPtxPdfContent_ImageMask* pImageMask = NULL;
8
9 pContent = PtxPdf_Page_GetContent(pOutPage);
10
11 // Create content generator
12 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Load image from input path
17 pImageStream = _tfopen(szImageMaskPath, _T("rb"));
18 GOTO_CLEANUP_IF_NULL(pImageStream, _T("Failed to open image mask file \"%s\".\n"), szImageMaskPath);
19 PtxSysCreateFILEStreamDescriptor(&imageDescriptor, pImageStream, 0);
20
21 // Create image mask object
22 pImageMask = PtxPdfContent_ImageMask_Create(pOutDoc, &imageDescriptor);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pImageMask, _T("Failed to create image mask obejct. %s (ErrorCode: 0x%08x).\n"),
24 szErrorBuff, Ptx_GetLastError());
25
26 double dResolution = 150.0;
27 TPtxGeomInt_Size size;
28 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ImageMask_GetSize(pImageMask, &size),
29 _T("Failed to get image mask size. %s(ErrorCode: 0x%08x).\n"), szErrorBuff,
30 Ptx_GetLastError());
31
32 // Calculate Rectangle for data matrix
33 TPtxGeomReal_Rectangle rect;
34 rect.dLeft = x;
35 rect.dBottom = y;
36 rect.dRight = x + (double)size.iWidth * 72.0 / dResolution;
37 rect.dTop = y + (double)size.iHeight * 72.0 / dResolution;
38
39 // Paint image mask into the specified rectangle
40 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
41 PtxPdfContent_ContentGenerator_PaintImageMask(pGenerator, pImageMask, &rect, pPaint),
42 _T("Failed to paint image mask. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
43
44cleanup:
45 if (pGenerator != NULL)
46 PtxPdfContent_ContentGenerator_Close(pGenerator);
47 if (pContent != NULL)
48 Ptx_Release(pContent);
49
50 return iReturnValue;
51}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Get the device color space
13 ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);
14
15 // Create paint object
16 paint = Paint.Create(outDoc, colorSpace, new double[] { 1.0, 0.0, 0.0 }, null);
17
18 // Define page copy options
19 PageCopyOptions copyOptions = new PageCopyOptions();
20
21 // Copy first page, add image mask, and append to output document
22 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
23 AddImageMask(outDoc, outPage, imageMaskPath, 250, 150);
24 outDoc.Pages.Add(outPage);
25
26 // Copy remaining pages and append to output document
27 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
28 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
29 outDoc.Pages.AddRange(copiedPages);
30}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1 private static void AddImageMask(Document document, Page outPage, string imagePath,
2 double x, double y)
3 {
4 // Create content generator
5 using ContentGenerator generator = new ContentGenerator(outPage.Content, false);
6
7 // Load image from input path
8 using Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read);
9
10 // Create image mask object
11 ImageMask imageMask = ImageMask.Create(document, inImage);
12 double resolution = 150;
13
14 // Calculate rectangle for image
15 PdfTools.Toolbox.Geometry.Integer.Size size = imageMask.Size;
16 Rectangle rect = new Rectangle
17 {
18 Left = x,
19 Bottom = y,
20 Right = x + size.Width * 72 / resolution,
21 Top = y + size.Height * 72 / resolution
22 };
23
24 // Paint image mask into the specified rectangle
25 generator.PaintImageMask(imageMask, rect, paint);
26 }
27}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Get the device color space
15 ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);
16
17 // Create paint object
18 paint = Paint.create(outDoc, colorSpace, new double[] { 1.0, 0.0, 0.0 }, null);
19
20 // Copy first page, add image mask, and append to output document
21 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
22 addImageMask(outDoc, outPage, imageMaskPath, 250, 150);
23 outDoc.getPages().add(outPage);
24
25 // Copy remaining pages and append to output document
26 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
27 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
28 outDoc.getPages().addAll(copiedPages);
29 }
30}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addImageMask(Document document, Page outPage, String imagePath, double x, double y)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false);
5 // Load image from input path
6 FileStream inImage = new FileStream(imagePath, FileStream.Mode.READ_ONLY)) {
7 // Create image mask object
8 ImageMask imageMask = ImageMask.create(document, inImage);
9
10 double resolution = 150;
11
12 // Calculate rectangle for image
13 Size size = imageMask.getSize();
14 Rectangle rect = new Rectangle(x, y, x + size.getWidth() * 72 / resolution,
15 y + size.getHeight() * 72 / resolution);
16
17 // Paint image mask into the specified rectangle
18 generator.paintImageMask(imageMask, rect, paint);
19 }
20}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_image_mask(document: Document, page: Page, image_path: str, x: float, y: float):
2 # Create content generator
3 with ContentGenerator(page.content, False) as generator:
4
5 # Load image from input path
6 with io.FileIO(image_path, 'rb') as in_image_stream:
7 # Create image mask object
8 image_mask = ImageMask.create(document, in_image_stream)
9 resolution = 150
10
11 # Calculate rectangle for image
12 size = image_mask.size
13 rect = Rectangle(
14 left=x,
15 bottom=y,
16 right=x + size.width * 72 / resolution,
17 top=y + size.height * 72 / resolution
18 )
19
20 # Paint image mask into the specified rectangle
21 generator.paint_image_mask(image_mask, rect, paint)
Add line numbers to PDF
1 // Open input document
2 using Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read);
3 using Document inDoc = Document.Open(inStream, null);
4
5 // Create output document
6 using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
7 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
8 // Copy document-wide data
9 CopyDocumentData(inDoc, outDoc);
10
11 // Create a font for the line numbers
12 var lineNumberFont = Font.CreateFromSystem(outDoc, "Arial", null, true);
13
14 // Define page copy options
15 PageCopyOptions pageCopyOptions = new();
16
17 // Copy all pages from input to output document
18 var inPages = inDoc.Pages;
19 var outPages = PageList.Copy(outDoc, inPages, pageCopyOptions);
20
21 // Iterate over all input-output page pairs
22 var pages = inPages.Zip(outPages);
23 foreach (var pair in pages)
24 AddLineNumbers(outDoc, lineNumberFont, pair);
25
26 // Add the finished pages to the output document's page list
27 outDoc.Pages.AddRange(outPages);
28 }
29 catch (Exception ex)
30 {
31 Console.WriteLine(ex.Message);
32 }
33}
34
1private static void AddLineNumbers(Document outDoc, Font lineNumberFont, (Page first, Page second) pair)
2{
3 // Add line numbers to all text found in the input page to the output page
4
5 // The input and output page
6 var inPage = pair.first;
7 var outPage = pair.second;
8
9 // Extract all text fragments
10 var extractor = new ContentExtractor(inPage.Content)
11 {
12 Ungrouping = UngroupingSelection.All
13 };
14
15 // The left-most horizontal position of all text fragments
16 double leftX = inPage.Size.Width;
17
18 // A comparison for doubles that considers distances smaller than the font size as equal
19 var comparison = new Comparison<double>(
20 (a, b) =>
21 {
22 var d = b - a;
23 if (Math.Abs(d) < fontSize)
24 return 0;
25 return Math.Sign(d);
26 });
27
28 // A container to hold the vertical positions of all text fragments, sorted and without duplicates
29 SortedSet<double> lineYPositions = new(Comparer<double>.Create(comparison));
30
31 // Iterate over all content elements of the input page
32 foreach (var element in extractor)
33 {
34 // Process only text elements
35 if (element is TextElement textElement)
36 {
37 // Iterate over all text fragments
38 foreach (var fragment in textElement.Text)
39 {
40 // Get the fragments base line starting point
41 var point = fragment.Transform.TransformPoint(new Point { X = fragment.BoundingBox.Left, Y = 0 });
42
43 // Update the left-most position
44 leftX = Math.Min(leftX, point.X);
45
46 // Add the vertical position
47 lineYPositions.Add(point.Y);
48 }
49 }
50 }
51
52 // If at least text fragment was found: add line numbers
53 if (lineYPositions.Count > 0)
54 {
55 // Create a text object and use a text generator
56 var text = Text.Create(outDoc);
57 using (var textGenerator = new TextGenerator(text, lineNumberFont, fontSize, null))
58 {
59 // Iterate over all vertical positions found in the input
60 foreach (var y in lineYPositions)
61 {
62 // The line number string
63 var lineNumberString = string.Format("{0}", ++lineNumber);
64
65 // The width of the line number string when shown on the page
66 var width = textGenerator.GetWidth(lineNumberString);
67
68 // Position line numbers right aligned
69 // with a given distance to the right-most horizontal position
70 // and at the vertical position of the current text fragment
71 textGenerator.MoveTo(new Point { X = leftX - width - distance, Y = y });
72
73 // Show the line number string
74 textGenerator.Show(lineNumberString);
75 }
76 }
77
78 // Use a content generator to paint the text onto the page
79 using var contentGenerator = new ContentGenerator(outPage.Content, false);
80 contentGenerator.PaintText(text);
81 }
82}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
6 // Copy document-wide data
7 copyDocumentData(inDoc, outDoc);
8
9 // Create embedded font in output document
10 Font font = Font.createFromSystem(outDoc, "Arial", null, true);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy all pages from input to output document
16 PageList inPages = inDoc.getPages();
17 PageList outPages = PageList.copy(outDoc, inPages, copyOptions);
18
19 // Iterate over all input-output page pairs and add line numbers
20 for (int i = 0; i < inPages.size(); ++i) {
21 addLineNumbers(outDoc, font, new SimpleEntry<>(inPages.get(i), outPages.get(i)));
22 }
23
24 // Add the finished pages to the output document's page list
25 outDoc.getPages().addAll(outPages);
26 }
27}
1private static void addLineNumbers(Document outDoc, Font lineNumberFont, Entry<Page, Page> pair) throws IOException, ToolboxException {
2 // Add line numbers to all text found in the input page to the output page
3
4 // The input and output page
5 Page inPage = pair.getKey();
6 Page outPage = pair.getValue();
7
8 // Extract all text fragments
9 ContentExtractor extractor = new ContentExtractor(inPage.getContent());
10 extractor.setUngrouping(UngroupingSelection.ALL);
11 // The left-most horizontal position of all text fragments
12 double leftX = inPage.getSize().getWidth();
13
14 Comparator<Double> comparator = new Comparator<Double>() {
15 @Override
16 public int compare(Double d1, Double d2) {
17 Double diff = d2 - d1;
18 if (Math.abs(diff) < fontSize)
19 return 0;
20 return (int) Math.signum(diff);
21 }
22 };
23
24 SortedSet<Double> lineYPositions = new TreeSet<>(comparator);
25
26 for (ContentElement element : extractor) {
27
28 // Process only text elements
29 if (element instanceof TextElement) {
30 TextElement textElement = (TextElement) element;
31 // Iterate over all text fragments
32 for (TextFragment fragment : textElement.getText()) {
33
34 // Get the fragments base line starting point
35 Point point = fragment.getTransform().transformPoint(new Point(fragment.getBoundingBox().left, 0));
36
37 // Update the left-most position
38 leftX = Math.min(leftX, point.x);
39
40 // Add the vertical position
41 lineYPositions.add(point.y);
42 }
43 }
44 }
45
46 // If at least one text fragment was found: add line numbers
47 if (lineYPositions.size() > 0) {
48
49 // Create a text object and use a text generator
50 Text text = Text.create(outDoc);
51 try (TextGenerator textGenerator = new TextGenerator(text, lineNumberFont, fontSize, null)) {
52 // Iterate over all vertical positions found in the input
53 for(double y : lineYPositions) {
54 // The line number string
55 String lineNumberString = String.valueOf(++lineNumber);
56
57 // The width of the line number string when shown on the page
58 double width = textGenerator.getWidth(lineNumberString);
59
60 // Position line numbers right aligned
61 // with a given distance to the right-most horizontal position
62 // and at the vertical position of the current text fragment
63 textGenerator.moveTo(new Point (leftX - width - distance, y));
64
65 // Show the line number string
66 textGenerator.show(lineNumberString);
67 }
68 }
69 try (ContentGenerator contentGenerator = new ContentGenerator(outPage.getContent(), false)) {
70 // Use a content generator to paint the text onto the page
71 contentGenerator.paintText(text);
72 }
73 }
74}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1# Class needed for a sorted list of unique values.
2# The tolerance defines how 2 values are considered different
3class TolerantSortedSet:
4 def add(self, value: float):
5 for existing in self.data:
6 if abs(existing - value) < self.tolerance:
7 return # Do not add duplicate-like value
8
9 self.data.append(value)
10 self.data.sort(reverse=self.sort_reverse)
11
12 def iterator(self):
13 return iter(self.data)
14
15 def display(self):
16 return str(self.data)
1def create_tolerant_sorted_set(tolerance: float, sort_reverse: bool):
2 tolerant_sorted_set = TolerantSortedSet()
3
4 tolerant_sorted_set.tolerance = tolerance
5 tolerant_sorted_set.sort_reverse = sort_reverse
6 tolerant_sorted_set.data = []
7
8 return tolerant_sorted_set
1def add_line_numbers(out_doc: Document, line_number_font: Font, pair: tuple):
2
3 global line_number
4
5 # Add line numbers to all text found in the input page to the output page
6
7 # The input and output page
8 in_page, out_page = pair
9
10 # Extract all text fragments
11 extractor = ContentExtractor(in_page.content)
12 extractor.ungrouping = UngroupingSelection.ALL
13
14 # The left-most horizontal position of all text fragments
15 left_x = in_page.size.width
16
17 # A comparison for doubles that considers distances smaller than the font size as equal
18 def comparison(a, b):
19 d = b - a
20 if abs(d) < font_size:
21 return 0
22 return (d > 0) - (d < 0) # return 1 if d > 0, -1 if d < 0, 0 otherwise
23
24 # A sorted set to hold the vertical positions of all text fragments
25 # Keep the data sorted in reverse oder as the coordinates are reverse in a PDF
26 line_y_positions = create_tolerant_sorted_set(tolerance=font_size, sort_reverse=True)
27
28 # Iterate over all content elements of the input page
29 for element in extractor:
30 # Process only text elements
31 if isinstance(element, TextElement):
32 # Iterate over all text fragments
33 for fragment in element.text:
34 # Get the fragment's baseline starting point
35 point = fragment.transform.transform_point(
36 Point(fragment.bounding_box.left, 0)
37 )
38
39 # Update the left-most position
40 left_x = min(left_x, point.x)
41
42 # Add the vertical position
43 line_y_positions.add(point.y)
44
45 # If at least one text fragment was found, add line numbers
46 if line_y_positions:
47 # Create a text object and use a text generator
48 text = Text.create(out_doc)
49 with TextGenerator(text, line_number_font, font_size, None) as text_generator:
50 # Iterate over all vertical positions found in the input
51 for y in line_y_positions.iterator():
52 # The line number string
53 line_number += 1
54 line_number_string = str(line_number)
55
56 # The width of the line number string when shown on the page
57 width = text_generator.get_width(line_number_string)
58
59 # Position line numbers right-aligned
60 # with a given distance to the right-most horizontal position
61 # and at the vertical position of the current text fragment
62 text_generator.move_to(Point(left_x - width - distance, y))
63
64 # Show the line number string
65 text_generator.show(line_number_string)
66
67 # Use a content generator to paint the text onto the page
68 with ContentGenerator(out_page.content, False) as content_generator:
69 content_generator.paint_text(text)
Add stamp to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&inDescriptor, pInStream, FALSE);
5pInDoc = PtxPdf_Document_Open(&inDescriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file %s.\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file %s cannot be closed. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Embedded font cannot be created. %s (ErrorCode: 0x%08x).\n"),
21 szErrorBuff, Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Get the color space
29TPtxPdfContent_ColorSpace* pColorSpace =
30 PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
31GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pColorSpace, _T("Failed to get the color space. %s (ErrorCode: 0x%08x).\n"),
32 szErrorBuff, Ptx_GetLastError());
33
34// Chose the RGB color values
35double color[] = {1.0, 0.0, 0.0};
36size_t nColor = sizeof(color) / sizeof(double);
37pTransparency = PtxPdfContent_Transparency_New(dAlpha);
38
39// Create paint object
40pPaint = PtxPdfContent_Paint_Create(pOutDoc, pColorSpace, color, nColor, pTransparency);
41GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pPaint, _T("Failed to create a transparent paint. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43
44// Configure copy options
45pCopyOptions = PtxPdf_PageCopyOptions_New();
46
47// Loop through all pages of input
48pInPageList = PtxPdf_Document_GetPages(pInDoc);
49GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
50 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
51 szErrorBuff, Ptx_GetLastError());
52pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
53GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
54 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
55 szErrorBuff, Ptx_GetLastError());
56for (int i = 0; i < PtxPdf_PageList_GetCount(pInPageList); i++)
57{
58 // Get a list of pages
59 pInPage = PtxPdf_PageList_Get(pInPageList, i);
60
61 // Copy page from input to output
62 pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
63 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
64 _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
65 szErrorBuff, Ptx_GetLastError());
66
67 // Add stamp to page
68 if (addStamp(pOutDoc, pOutPage, szStampString, pFont, 50) == 1)
69 {
70 goto cleanup;
71 }
72
73 // Add page to output document
74 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
75 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
76 szErrorBuff, Ptx_GetLastError());
77
78 if (pOutPage != NULL)
79 {
80 Ptx_Release(pOutPage);
81 pOutPage = NULL;
82 }
83
84 if (pInPage != NULL)
85 {
86 Ptx_Release(pInPage);
87 pInPage = NULL;
88 }
89}
90
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addStamp(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szStampString, TPtxPdfContent_Font* pFont,
2 double dFontSize)
3{
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxPdfContent_Text* pText = NULL;
6 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
7 TPtxGeomReal_AffineTransform trans;
8 TPtxGeomReal_Point rotationCenter;
9 double dTextWidth;
10 double dFontAscent;
11
12 TPtxPdfContent_Content* pContent = PtxPdf_Page_GetContent(pOutPage);
13
14 // Create content generator
15 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
16 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
17 szErrorBuff, Ptx_GetLastError());
18
19 // Create text object
20 pText = PtxPdfContent_Text_Create(pOutDoc);
21 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
22 szErrorBuff, Ptx_GetLastError());
23
24 // Create a text generator
25 pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, dFontSize, NULL);
26 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
27 szErrorBuff, Ptx_GetLastError());
28
29 // Get output page size
30 TPtxGeomReal_Size size;
31 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
32 _T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
33 Ptx_GetLastError());
34
35 // Calculate point and angle of rotation
36 rotationCenter.dX = size.dWidth / 2.0;
37 rotationCenter.dY = size.dHeight / 2.0;
38 double dRotationAngle = atan2(size.dHeight, size.dWidth) / M_PI * 180.0;
39
40 // Rotate textinput around the calculated position
41 PtxGeomReal_AffineTransform_GetIdentity(&trans);
42 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
43 PtxGeomReal_AffineTransform_Rotate(&trans, dRotationAngle, &rotationCenter),
44 _T("Failed to rotate textinput around the calculated position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
45 Ptx_GetLastError());
46 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_Transform(pGenerator, &trans),
47 _T("Failed to modify the current transformation. %s (ErrorCode: 0x%08x).\n"),
48 szErrorBuff, Ptx_GetLastError());
49
50 // Calculate position
51 TPtxGeomReal_Point position;
52 dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampString);
53 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
54 dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
55 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
56 position.dX = (size.dWidth - dTextWidth) / 2.0;
57 position.dY = (size.dHeight - dFontAscent * dFontSize) / 2.0;
58
59 // Move to position
60 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
61 _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
62 Ptx_GetLastError());
63 // Set text rendering
64 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_SetFill(pTextGenerator, pPaint),
65 _T("Failed to set fill paint. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
66 Ptx_GetLastError());
67 // Add given stamp string
68 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szStampString),
69 _T("Failed to add stamp. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
70 Ptx_GetLastError());
71
72 // Close text generator
73 if (pTextGenerator != NULL)
74 {
75 PtxPdfContent_TextGenerator_Close(pTextGenerator);
76 pTextGenerator = NULL;
77 }
78
79 // Paint the positioned text
80 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
81 _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
82 Ptx_GetLastError());
83
84cleanup:
85 if (pTextGenerator != NULL)
86 PtxPdfContent_TextGenerator_Close(pTextGenerator);
87 if (pText != NULL)
88 Ptx_Release(pText);
89 if (pGenerator != NULL)
90 PtxPdfContent_ContentGenerator_Close(pGenerator);
91 if (pContent != NULL)
92 Ptx_Release(pContent);
93
94 return iReturnValue;
95}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
13
14 // Get the color space
15 ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, ProcessColorSpaceType.Rgb);
16
17 // Choose the RGB color value
18 double[] color = { 1.0, 0.0, 0.0 };
19 Transparency transparency = new Transparency(alpha);
20
21 // Create paint object with the choosen RGB color
22 paint = Paint.Create(outDoc, colorSpace, color, transparency);
23
24 // Define copy options
25 PageCopyOptions copyOptions = new PageCopyOptions();
26
27 // Copy all pages from input document
28 foreach (Page inPage in inDoc.Pages)
29 {
30 // Copy page from input to output
31 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
32
33 // Add text to page
34 AddStamp(outDoc, outPage, stampString);
35
36 // Add page to document
37 outDoc.Pages.Add(outPage);
38 }
39}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddStamp(Document outputDoc, Page outPage, string stampString)
2{
3 // Create content generator and text object
4 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
5 Text text = Text.Create(outputDoc);
6
7 // Create text generator
8 using (TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null))
9 {
10 // Calculate point and angle of rotation
11 Point rotationCenter = new Point
12 {
13 X = outPage.Size.Width / 2.0,
14 Y = outPage.Size.Height / 2.0
15 };
16 double rotationAngle = Math.Atan2(outPage.Size.Height,
17 outPage.Size.Width) / Math.PI * 180.0;
18
19 // Rotate text input around the calculated position
20 AffineTransform trans = AffineTransform.Identity;
21 trans.Rotate(rotationAngle, rotationCenter);
22 gen.Transform(trans);
23
24 // Calculate position
25 Point position = new Point
26 {
27 X = (outPage.Size.Width - textgenerator.GetWidth(stampString)) / 2.0,
28 Y = (outPage.Size.Height - font.Ascent * fontSize) / 2.0
29 };
30
31 // Move to position
32 textgenerator.MoveTo(position);
33
34 // Set text paint
35 textgenerator.Fill = paint;
36
37 // Add given stamp string
38 textgenerator.ShowLine(stampString);
39 }
40 // Paint the positioned text
41 gen.PaintText(text);
42}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7 // Copy document-wide data
8 copyDocumentData(inDoc, outDoc);
9
10 // Create embedded font in output document
11 font = Font.createFromSystem(outDoc, "Arial", "Italic", true);
12
13 // Get the color space
14 ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, ProcessColorSpaceType.RGB);
15
16 // Choose the RGB color value
17 double[] color = { 1.0, 0.0, 0.0 };
18 Transparency transparency = new Transparency(alpha);
19
20 // Create paint object
21 paint = Paint.create(outDoc, colorSpace, color, transparency);
22
23 // Define page copy options
24 PageCopyOptions copyOptions = new PageCopyOptions();
25
26 // Loop throw all pages of input
27 for (Page inPage : inDoc.getPages()) {
28 // Copy page from input to output
29 Page outPage = Page.copy(outDoc, inPage, copyOptions);
30
31 // Add text to page
32 addStamp(outDoc, outPage, stampString);
33
34 // Add page to document
35 outDoc.getPages().add(outPage);
36 }
37 }
38}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addStamp(Document outputDoc, Page outPage, String stampString)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outputDoc);
7 try (// Create text generator
8 TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
9 // Calculate point and angle of rotation
10 Point rotationCenter = new Point(outPage.getSize().width / 2.0, outPage.getSize().height / 2.0);
11
12 // Calculate rotation angle
13 double rotationAngle = Math.atan2(outPage.getSize().height, outPage.getSize().width) / Math.PI * 180.0;
14
15 // Rotate text input around the calculated position
16 AffineTransform trans = AffineTransform.getIdentity();
17 trans.rotate(rotationAngle, rotationCenter);
18 generator.transform(trans);
19
20 // Calculate position
21 Point position = new Point((outPage.getSize().width - textgenerator.getWidth(stampString)) / 2.0,
22 (outPage.getSize().height - font.getAscent() * fontSize) / 2.0);
23
24 // Move to position
25 textgenerator.moveTo(position);
26
27 // Set text paint
28 textgenerator.setFill(paint);
29
30 // Add given stamp string
31 textgenerator.showLine(stampString);
32 }
33
34 // Paint the positioned text
35 generator.paintText(text);
36 }
37}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_stamp(output_doc: Document, out_page: Page, stamp_string: str):
2 # Create content generator and text object
3 with ContentGenerator(out_page.content, False) as gen:
4 text = Text.create(output_doc)
5
6 # Create text generator
7 with TextGenerator(text, font, font_size, None) as text_generator:
8 # Calculate point and angle of rotation
9 rotation_center = Point(
10 x=out_page.size.width / 2.0,
11 y=out_page.size.height / 2.0
12 )
13 rotation_angle = math.atan2(out_page.size.height, out_page.size.width) / math.pi * 180.0
14
15 # Rotate text input around the calculated position
16 trans = AffineTransform.get_identity()
17 trans.rotate(rotation_angle, rotation_center)
18 gen.transform(trans)
19
20 # Calculate position
21 position = Point(
22 x=(out_page.size.width - text_generator.get_width(stamp_string)) / 2.0,
23 y=(out_page.size.height - font.ascent * font_size) / 2.0
24 )
25
26 # Move to position
27 text_generator.move_to(position)
28
29 # Set text paint
30 text_generator.fill = paint
31
32 # Add given stamp string
33 text_generator.show_line(stamp_string)
34
35 # Paint the positioned text
36 gen.paint_text(text)
Add text to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T("Italic"), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Configure copy options
29pCopyOptions = PtxPdf_PageCopyOptions_New();
30
31// Get page lists of input and output document
32pInPageList = PtxPdf_Document_GetPages(pInDoc);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
34 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
35 szErrorBuff, Ptx_GetLastError());
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40
41// Copy first page
42pInPage = PtxPdf_PageList_Get(pInPageList, 0);
43GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get the first page. %s (ErrorCode: 0x%08x).\n"),
44 szErrorBuff, Ptx_GetLastError());
45pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
46GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to copy page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
47 Ptx_GetLastError());
48
49// Add text to copied page
50if (addText(pOutDoc, pOutPage, szTextString, pFont, 15) != 0)
51 goto cleanup;
52
53// Add page to output document
54GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
55 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
56 szErrorBuff, Ptx_GetLastError());
57
58// Get remaining pages from input
59pInPageRange = PtxPdf_PageList_GetRange(pInPageList, 1, PtxPdf_PageList_GetCount(pInPageList) - 1);
60GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
61 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x).\n"),
62 szErrorBuff, Ptx_GetLastError());
63
64// Copy remaining pages to output
65pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
66GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageRange,
67 _T("Failed to copy page range to output document. %s (ErrorCode: 0x%08x).\n"),
68 szErrorBuff, Ptx_GetLastError());
69
70// Add the copied pages to the output document
71GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
72 _T("Failed to add page range to output page list. %s (ErrorCode: 0x%08x).\n"),
73 szErrorBuff, Ptx_GetLastError());
74
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addText(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TCHAR* szTextString, TPtxPdfContent_Font* pFont,
2 double dFontSize)
3{
4 TPtxPdfContent_Content* pContent = NULL;
5 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
6 TPtxPdfContent_Text* pText = NULL;
7 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
8 TPtxGeomReal_Size size;
9 TPtxGeomReal_Point position;
10 double dFontAscent;
11
12 pContent = PtxPdf_Page_GetContent(pOutPage);
13 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content of output file. %s (ErrorCode: 0x%08x).\n"),
14 szErrorBuff, Ptx_GetLastError());
15
16 // Create content generator
17 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
18 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
19 szErrorBuff, Ptx_GetLastError());
20
21 // Create text object
22 pText = PtxPdfContent_Text_Create(pOutDoc);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
24 Ptx_GetLastError());
25
26 // Create a text generator
27 pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, dFontSize, NULL);
28 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
29 szErrorBuff, Ptx_GetLastError());
30
31 // Get output page size
32 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
33 _T("Failed to read page size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
34 Ptx_GetLastError());
35
36 dFontAscent = PtxPdfContent_Font_GetAscent(pFont);
37 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dFontAscent, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
38
39 // Calculate position
40 position.dX = dBorder;
41 position.dY = size.dHeight - dBorder - dFontSize * dFontAscent;
42
43 // Move to position
44 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
45 _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
46 Ptx_GetLastError());
47 // Add given text string
48 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szTextString),
49 _T("Failed to add text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
50 Ptx_GetLastError());
51 // Close text generator
52 PtxPdfContent_TextGenerator_Close(pTextGenerator);
53 pTextGenerator = NULL;
54
55 // Paint the positioned text
56 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
57 _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
58 Ptx_GetLastError());
59
60cleanup:
61 if (pTextGenerator != NULL)
62 PtxPdfContent_TextGenerator_Close(pTextGenerator);
63 if (pText != NULL)
64 Ptx_Release(pText);
65 if (pGenerator != NULL)
66 PtxPdfContent_ContentGenerator_Close(pGenerator);
67 if (pContent != NULL)
68 Ptx_Release(pContent);
69
70 return iReturnValue;
71}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Create a font
13 font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
14
15 // Define page copy options
16 PageCopyOptions copyOptions = new PageCopyOptions();
17
18 // Copy first page, add text, and append to output document
19 Page outPage = Page.Copy(outDoc, inDoc.Pages[0], copyOptions);
20 AddText(outDoc, outPage, textString);
21 outDoc.Pages.Add(outPage);
22
23 // Copy remaining pages and append to output document
24 PageList inPageRange = inDoc.Pages.GetRange(1, inDoc.Pages.Count - 1);
25 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
26 outDoc.Pages.AddRange(copiedPages);
27}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddText(Document outputDoc, Page outPage, string textString)
2{
3 // Create content generator and text object
4 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
5 Text text = Text.Create(outputDoc);
6
7 // Create text generator
8 using (TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null))
9 {
10 // Calculate position
11 Point position = new Point
12 {
13 X = border,
14 Y = outPage.Size.Height - border - fontSize * font.Ascent
15 };
16
17 // Move to position
18 textGenerator.MoveTo(position);
19 // Add given text string
20 textGenerator.ShowLine(textString);
21 }
22 // Paint the positioned text
23 gen.PaintText(text);
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7 // Copy document-wide data
8 copyDocumentData(inDoc, outDoc);
9
10 // Create embedded font in output document
11 font = Font.createFromSystem(outDoc, "Arial", "Italic", true);
12
13 // Define page copy options
14 PageCopyOptions copyOptions = new PageCopyOptions();
15
16 // Copy first page, add text, and append to output document
17 Page outPage = Page.copy(outDoc, inDoc.getPages().get(0), copyOptions);
18 addText(outDoc, outPage, textString);
19 outDoc.getPages().add(outPage);
20
21 // Copy remaining pages and append to output document
22 PageList inPageRange = inDoc.getPages().subList(1, inDoc.getPages().size());
23 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
24 outDoc.getPages().addAll(copiedPages);
25 }
26}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data (excluding metadata)
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Viewer settings
9 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
10
11 // Associated files (for PDF/A-3 and PDF 2.0 only)
12 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
13 for (FileReference inFileRef : inDoc.getAssociatedFiles())
14 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
15
16 // Plain embedded files
17 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
18 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
19 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
20}
1private static void addText(Document outputDoc, Page outPage, String textString)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outputDoc);
7
8 try (// Create a text generator
9 TextGenerator textgenerator = new TextGenerator(text, font, fontSize, null)) {
10 // Calculate position
11 Point position = new Point(border, outPage.getSize().height - border - fontSize * font.getAscent());
12
13 // Move to position
14 textgenerator.moveTo(position);
15 // Add given text string
16 textgenerator.showLine(textString);
17 }
18
19 // Paint the positioned text
20 generator.paintText(text);
21 }
22}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_text(output_doc: Document, output_page: Page, text_string: str):
2 # Create content generator and text object
3 with ContentGenerator(output_page.content, False) as gen:
4 text = Text.create(output_doc)
5
6 # Create text generator
7 with TextGenerator(text, font, font_size, None) as textGenerator:
8 # Calculate position
9 position = Point(border, output_page.size.height - border - font_size * font.ascent)
10
11 # Move to position
12 textGenerator.move_to(position)
13 # Add given text string
14 textGenerator.show_line(text_string)
15
16 # Paint the positioned text
17 gen.paint_text(text)
Add vector graphic to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Loop through all pages of input
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
33 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
34 szErrorBuff, Ptx_GetLastError());
35for (int iPage = 1; iPage <= PtxPdf_PageList_GetCount(pInPageList); iPage++)
36{
37 pInPage = PtxPdf_PageList_Get(pInPageList, iPage - 1);
38
39 // Copy page from input to output
40 pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
41 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
42 _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
43 szErrorBuff, Ptx_GetLastError());
44 PtxPdf_Page_GetSize(pOutPage, &size);
45
46 // Add text on first page
47 if (addLine(pOutDoc, pOutPage) == 1)
48 {
49 goto cleanup;
50 }
51
52 // Add page to output document
53 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
54 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
55 szErrorBuff, Ptx_GetLastError());
56
57 if (pOutPage != NULL)
58 {
59 Ptx_Release(pOutPage);
60 pOutPage = NULL;
61 }
62
63 if (pInPage != NULL)
64 {
65 Ptx_Release(pInPage);
66 pInPage = NULL;
67 }
68}
69
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addLine(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxPdfContent_Path* pPath = NULL;
6 TPtxPdfContent_PathGenerator* pPathGenerator = NULL;
7 TPtxPdfContent_ColorSpace* pDeviceRgbColorSpace = NULL;
8 double aColor[3];
9 TPtxPdfContent_Paint* pPaint = NULL;
10 TPtxPdfContent_Stroke* pStroke;
11 TPtxGeomReal_Size pageSize;
12 TPtxGeomReal_Point point;
13
14 pContent = PtxPdf_Page_GetContent(pOutPage);
15 PtxPdf_Page_GetSize(pOutPage, &pageSize);
16
17 // Create content generator
18 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
19 GOTO_CLEANUP_IF_NULL(pGenerator, szErrorBuff, Ptx_GetLastError());
20
21 // Create a path
22 pPath = PtxPdfContent_Path_New();
23 GOTO_CLEANUP_IF_NULL(pPath, szErrorBuff, Ptx_GetLastError());
24
25 // Create a path generator
26 pPathGenerator = PtxPdfContent_PathGenerator_New(pPath);
27 GOTO_CLEANUP_IF_NULL(pPathGenerator, szErrorBuff, Ptx_GetLastError());
28
29 // Draw a line diagonally across the page
30 point.dX = 10.0;
31 point.dY = 10.0;
32 GOTO_CLEANUP_IF_FALSE(PtxPdfContent_PathGenerator_MoveTo(pPathGenerator, &point), szErrorBuff, Ptx_GetLastError());
33 point.dX = pageSize.dWidth - 10.0;
34 point.dY = pageSize.dHeight - 10.0;
35 GOTO_CLEANUP_IF_FALSE(PtxPdfContent_PathGenerator_LineTo(pPathGenerator, &point), szErrorBuff, Ptx_GetLastError());
36
37 // Close the path generator in order to finish the path
38 PtxPdfContent_PathGenerator_Close(pPathGenerator);
39 pPathGenerator = NULL;
40
41 // Create a RGB color space
42 pDeviceRgbColorSpace =
43 PtxPdfContent_ColorSpace_CreateProcessColorSpace(pOutDoc, ePtxPdfContent_ProcessColorSpaceType_Rgb);
44 GOTO_CLEANUP_IF_NULL(pDeviceRgbColorSpace, szErrorBuff, Ptx_GetLastError());
45
46 // Initialize a red color
47 aColor[0] = 1.0;
48 aColor[1] = 0.0;
49 aColor[2] = 0.0;
50
51 // Create a paint
52 pPaint =
53 PtxPdfContent_Paint_Create(pOutDoc, pDeviceRgbColorSpace, aColor, sizeof(aColor) / sizeof(aColor[0]), NULL);
54 GOTO_CLEANUP_IF_NULL(pPaint, szErrorBuff, Ptx_GetLastError());
55
56 // Setup stroking parameters with given paint and line width
57 pStroke = PtxPdfContent_Stroke_New(pPaint, 10.0);
58 GOTO_CLEANUP_IF_NULL(pStroke, szErrorBuff, Ptx_GetLastError());
59
60 // Draw the path onto the page
61 GOTO_CLEANUP_IF_FALSE(PtxPdfContent_ContentGenerator_PaintPath(pGenerator, pPath, NULL, pStroke), szErrorBuff,
62 Ptx_GetLastError());
63
64cleanup:
65 if (pPathGenerator != NULL)
66 PtxPdfContent_PathGenerator_Close(pPathGenerator);
67 if (pGenerator != NULL)
68 PtxPdfContent_ContentGenerator_Close(pGenerator);
69 if (pContent != NULL)
70 Ptx_Release(pContent);
71
72 return iReturnValue;
73}
1// Open input document
2using (System.IO.Stream inStream = new System.IO.FileStream(inPath, System.IO.FileMode.Open, System.IO.FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (System.IO.Stream outStream = new System.IO.FileStream(outPath, System.IO.FileMode.Create, System.IO.FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy all pages from input document
16 foreach (Page inPage in inDoc.Pages)
17 {
18 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
19
20 // Add a line
21 AddLine(outDoc, outPage);
22
23 // Add page to output document
24 outDoc.Pages.Add(outPage);
25 }
26}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddLine(Document document, Page page)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(page.Content, false);
5
6 // Create a path
7 Path path = new Path();
8 using (PathGenerator pathGenerator = new PathGenerator(path))
9 {
10 // Draw a line diagonally across the page
11 Size pageSize = page.Size;
12 pathGenerator.MoveTo(new Point() { X = 10.0, Y = 10.0 });
13 pathGenerator.LineTo(new Point() { X = pageSize.Width - 10.0, Y = pageSize.Height - 10.0 });
14 }
15
16 // Create a RGB color space
17 ColorSpace deviceRgbColorSpace = ColorSpace.CreateProcessColorSpace(document, ProcessColorSpaceType.Rgb);
18
19 // Create a red color
20 double[] color = new double[] { 1.0, 0.0, 0.0 };
21
22 // Create a paint
23 Paint paint = Paint.Create(document, deviceRgbColorSpace, color, null);
24
25 // Create stroking parameters with given paint and line width
26 Stroke stroke = new Stroke(paint, 10.0);
27
28 // Draw the path onto the page
29 generator.PaintPath(path, null, stroke);
30}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy all pages
15 for (Page inPage : inDoc.getPages()) {
16 // Copy page from input to output
17 Page outPage = Page.copy(outDoc, inPage, copyOptions);
18
19 // Add a line
20 addLine(outDoc, outPage);
21
22 // Add page to output document
23 outDoc.getPages().add(outPage);
24 }
25 }
26}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void addLine(Document document, Page outPage)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5
6 // Create a path
7 Path path = new Path();
8 try (// Create a path generator
9 PathGenerator pathGenerator = new PathGenerator(path)) {
10 // Draw a line diagonally across the page
11 Size pageSize = outPage.getSize();
12 pathGenerator.moveTo(new Point(10.0, 10.0));
13 pathGenerator.lineTo(new Point(pageSize.width - 10.0, pageSize.height - 10.0));
14 }
15
16 // Create a RGB color space
17 ColorSpace deviceRgbColorSpace = ColorSpace.createProcessColorSpace(document, ProcessColorSpaceType.RGB);
18
19 // Create a red color
20 double[] color = new double[] { 1.0, 0.0, 0.0 };
21
22 // Create a paint
23 Paint paint = Paint.create(document, deviceRgbColorSpace, color, null);
24
25 // Create stroking parameters with given paint and line width
26 Stroke stroke = new Stroke(paint, 10.0);
27
28 // Draw the path onto the page
29 generator.paintPath(path, null, stroke);
30 }
31}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_line(out_doc: Document, page: Page):
2 # Extract content generator
3 with ContentGenerator(page.content, False) as generator:
4
5 # Create a path
6 path = Path()
7 with PathGenerator(path) as path_generator:
8 # Draw a line diagonally across the page
9 page_size = page.size
10 path_generator.move_to(Point(x = 10.0, y = 10.0))
11 path_generator.line_to(Point(x = page_size.width - 10.0, y=page_size.height - 10.0))
12
13 # Create a RGB color space
14 device_rgb_color_space = ColorSpace.create_process_color_space(out_doc, ProcessColorSpaceType.RGB)
15
16 # Create a red color
17 red = [1.0, 0.0, 0.0]
18
19 # Create a paint
20 paint = Paint.create(out_doc, device_rgb_color_space, red, None)
21
22 # Create stroking parameters with given paint and line width
23 stroke = Stroke(paint, 10.0)
24
25 # Draw the path onto the page
26 generator.paint_path(path, None, stroke)
Layout text on PDF page
1// Create output document
2using (Stream outStream = new FileStream(outPath, FileMode.CreateNew, FileAccess.ReadWrite))
3using (Document outDoc = Document.Create(outStream, null, null))
4{
5 Font font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
6
7 // Create page
8 Page outPage = Page.Create(outDoc, PageSize);
9
10 // Add text as justified text
11 LayoutText(outDoc, outPage, textPath, font, 20);
12
13 // Add page to document
14 outDoc.Pages.Add(outPage);
15}
1private static void LayoutText(Document outputDoc, Page outPage, string textPath, Font font,
2 double fontSize)
3{
4 // Create content generator
5 using ContentGenerator gen = new ContentGenerator(outPage.Content, false);
6
7 // Create text object
8 Text text = Text.Create(outputDoc);
9
10 // Create text generator
11 using TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null);
12
13 // Calculate position
14 Point position = new Point
15 {
16 X = Border,
17 Y = outPage.Size.Height - Border
18 };
19
20 // Move to position
21 textGenerator.MoveTo(position);
22
23 // Loop through all lines of the textinput
24 string[] lines = File.ReadAllLines(textPath, Encoding.Default);
25 foreach (string line in lines)
26 {
27 // Split string in substrings
28 string[] substrings = line.Split(new char[] { ' ' }, StringSplitOptions.None);
29 string currentLine = null;
30 double maxWidth = outPage.Size.Width - Border * 2;
31 int wordcount = 0;
32
33 // Loop through all words of input strings
34 foreach (string word in substrings)
35 {
36 string tempLine;
37
38 // Concatenate substrings to line
39 if (currentLine != null)
40 tempLine = currentLine + " " + word;
41 else
42 tempLine = word;
43
44 // Calculate the current width of line
45 double width = textGenerator.GetWidth(currentLine);
46 if (textGenerator.GetWidth(tempLine) > maxWidth)
47 {
48 // Calculate the word spacing
49 textGenerator.WordSpacing = (maxWidth - width) / (wordcount - 1);
50 // Paint on new line
51 textGenerator.ShowLine(currentLine);
52 textGenerator.WordSpacing = 0;
53 currentLine = word;
54 wordcount = 1;
55 }
56 else
57 {
58 currentLine = tempLine;
59 wordcount++;
60 }
61 }
62 textGenerator.WordSpacing = 0;
63 // Add given stamp string
64 textGenerator.ShowLine(currentLine);
65 }
66 // Paint the positioned text
67 gen.PaintText(text);
68}
1try (
2 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
3 try (// Create output document
4 Document outDoc = Document.create(outStream, null, null)) {
5 // Create embedded font in output document
6 Font font = Font.createFromSystem(outDoc, "Arial", "Italic", true);
7
8 // Create page
9 Page outPage = Page.create(outDoc, new Size(595, 842));
10
11 // Add text to document
12 layoutText(outDoc, outPage, textPath, font, 20);
13
14 // Add page to output document
15 outDoc.getPages().add(outPage);
16 }
17}
1private static void layoutText(Document outputDoc, Page outPage, String textPath, Font font, double fontSize)
2 throws ToolboxException, IOException {
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outputDoc);
7
8 try (// Create a text generator
9 TextGenerator textGenerator = new TextGenerator(text, font, fontSize, null)) {
10
11 // Calculate position
12 Point position = new Point(Border, outPage.getSize().height - Border);
13
14 // Move to position
15 textGenerator.moveTo(position);
16
17 // Loop throw all lines of the textinput
18 List<String> lines = Files.readAllLines(Paths.get(textPath), Charset.defaultCharset());
19 for (String line : lines) {
20 // Split string in substrings
21 String[] substrings = line.split(" ");
22 String currentLine = null;
23 double maxWidth = outPage.getSize().width - (Border * 2);
24
25 int wordCount = 0;
26
27 // Loop throw all words of input strings
28 for (String word : substrings) {
29 String tempLine;
30
31 // Concatenate substrings to line
32 if (currentLine != null) {
33 tempLine = currentLine + " " + word;
34 } else {
35 tempLine = word;
36 }
37
38 // Calculate the current width of line
39 double width = textGenerator.getWidth(currentLine);
40
41 if ((textGenerator.getWidth(tempLine) > maxWidth)) {
42 // Calculate the word spacing
43 textGenerator.setWordSpacing((maxWidth - width) / (double) (wordCount - 1));
44
45 // Paint on new line
46 textGenerator.showLine(currentLine);
47 textGenerator.setWordSpacing(0);
48 currentLine = word;
49 wordCount = 1;
50 } else {
51 currentLine = tempLine;
52 wordCount++;
53 }
54 }
55 textGenerator.setWordSpacing(0);
56 // Add given stamp string
57 textGenerator.showLine(currentLine);
58 }
59 }
60 // Paint the positioned text
61 generator.paintText(text);
62 }
63}
1
2
3# Create output document
4with io.FileIO(output_file_path, "wb+") as out_stream:
5 with Document.create(out_stream, None, None) as out_doc:
6
7 font = Font.create_from_system(out_doc, "Arial", "Italic", True)
8
9 # Create page
10 out_page = Page.create(out_doc, PAGE_SIZE)
11
12 # Add text as justified text
13 layout_text(out_doc, out_page, input_text_path, font, font_size=20)
14
15 # Add page to document
16 out_doc.pages.append(out_page)
17
1def layout_text(output_doc: Document, out_page: Page, text_path: str, font: Font, font_size: float):
2 """
3 Layout and justify text on the PDF page.
4 """
5 # Create content generator
6 with ContentGenerator(out_page.content, False) as generator:
7
8 # Create text object
9 text = Text.create(output_doc)
10
11 # Create text generator
12 with TextGenerator(text, font, font_size, None) as text_generator:
13
14 # Calculate starting position
15 position = Point(x=BORDER, y=out_page.size.height - BORDER)
16
17 # Move to position
18 text_generator.move_to(position)
19
20 with open(text_path, "r", encoding="utf-8") as file:
21 lines = file.readlines()
22
23 # Loop through all lines of the textinput
24 for line in lines:
25 # Split string in substrings
26 substrings = line.split(" ")
27 current_line = ""
28 max_width = out_page.size.width - BORDER * 2
29 word_count = 0
30
31 # Loop through all words of input strings
32 for word in substrings:
33 # Concatenate substrings to line
34 temp_line = f"{current_line} {word}".strip()
35
36 # Calculate the current width of line
37 current_width = text_generator.get_width(current_line)
38
39 if text_generator.get_width(temp_line) > max_width:
40 # Calculate the word spacing
41 text_generator.word_spacing = (max_width - current_width) / (word_count - 1)
42 text_generator.show_line(current_line)
43 text_generator.word_spacing = 0
44 current_line = word
45 word_count = 1
46 else:
47 current_line = temp_line
48 word_count += 1
49
50 text_generator.word_spacing = 0
51 # Add given stamp string
52 text_generator.show_line(current_line)
53
54 # Paint the positioned text
55 generator.paint_text(text)
Stamp page number to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Create embedded font in output document
19pFont = PtxPdfContent_Font_CreateFromSystem(pOutDoc, _T("Arial"), _T(""), TRUE);
20GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pFont, _T("Failed to create font. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Copy document-wide data
24GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
25 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
26 Ptx_GetLastError());
27
28// Configure copy options
29pCopyOptions = PtxPdf_PageCopyOptions_New();
30
31// Copy all pages
32pInPageList = PtxPdf_Document_GetPages(pInDoc);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
34 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
35 szErrorBuff, Ptx_GetLastError());
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40for (int iPage = 0; iPage < PtxPdf_PageList_GetCount(pInPageList); iPage++)
41{
42 pInPage = PtxPdf_PageList_Get(pInPageList, iPage);
43
44 // Copy page from input to output
45 pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
46 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
47 _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
48 szErrorBuff, Ptx_GetLastError());
49 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pOutPage, &size),
50 _T("Failed to get size. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
51 Ptx_GetLastError());
52
53 // Stamp page number on current page of output document
54 if (addPageNumber(pOutDoc, pOutPage, pFont, iPage + 1) == 1)
55 {
56 goto cleanup;
57 }
58
59 // Add page to output document
60 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
61 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
62 szErrorBuff, Ptx_GetLastError());
63
64 if (pOutPage != NULL)
65 {
66 Ptx_Release(pOutPage);
67 pOutPage = NULL;
68 }
69
70 if (pInPage != NULL)
71 {
72 Ptx_Release(pInPage);
73 pInPage = NULL;
74 }
75}
76
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1int addPageNumber(TPtxPdf_Document* pOutDoc, TPtxPdf_Page* pOutPage, TPtxPdfContent_Font* pFont, int nPageNumber)
2{
3 TPtxPdfContent_Content* pContent = NULL;
4 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
5 TPtxPdfContent_Text* pText = NULL;
6 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
7
8 pContent = PtxPdf_Page_GetContent(pOutPage);
9
10 // Create content generator
11 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
12 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
13 szErrorBuff, Ptx_GetLastError());
14
15 // Create text object
16 pText = PtxPdfContent_Text_Create(pOutDoc);
17 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create a text object. %s (ErrorCode: 0x%08x).\n"),
18 szErrorBuff, Ptx_GetLastError());
19
20 // Create a text generator with the given font, size and position
21 pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, 8, NULL);
22 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create a text generator. %s (ErrorCode: 0x%08x).\n"),
23 szErrorBuff, Ptx_GetLastError());
24
25 // Generate string to be stamped as page number
26 char szStampBuffer[50];
27 snprintf(szStampBuffer, sizeof(szStampBuffer), _T("Page %d"), nPageNumber);
28 TCHAR* szStampText = szStampBuffer;
29
30 double dTextWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampText);
31 GOTO_CLEANUP_IF_ZERO_PRINT_ERROR(dTextWidth, _T("Failed to get text width. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
32 Ptx_GetLastError());
33
34 // Calculate position
35 TPtxGeomReal_Point position;
36 position.dX = (size.dWidth / 2) - (dTextWidth / 2);
37 position.dY = 10;
38
39 // Move to position
40 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &position),
41 _T("Failed to move to position. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
42 Ptx_GetLastError());
43 // Add given text string
44 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_ShowLine(pTextGenerator, szStampText),
45 _T("Failed to add given text string. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
46 Ptx_GetLastError());
47
48 // Close text generator
49 PtxPdfContent_TextGenerator_Close(pTextGenerator);
50 pTextGenerator = NULL;
51
52 // Paint the positioned text
53 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
54 _T("Failed to paint the positioned text. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
55 Ptx_GetLastError());
56
57cleanup:
58 if (pTextGenerator != NULL)
59 PtxPdfContent_TextGenerator_Close(pTextGenerator);
60 if (pGenerator != NULL)
61 PtxPdfContent_ContentGenerator_Close(pGenerator);
62 if (pText != NULL)
63 Ptx_Release(pText);
64 if (pContent != NULL)
65 Ptx_Release(pContent);
66
67 return iReturnValue;
68}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Create embedded font in output document
16 Font font = Font.CreateFromSystem(outDoc, "Arial", string.Empty, true);
17
18 // Copy all pages from input document
19 int currentPageNumber = 1;
20 foreach (Page inPage in inDoc.Pages)
21 {
22 // Copy page from input to output
23 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
24
25 // Stamp page number on current page of output document
26 AddPageNumber(outDoc, outPage, font, currentPageNumber++);
27
28 // Add page to output document
29 outDoc.Pages.Add(outPage);
30 }
31}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void AddPageNumber(Document outDoc, Page outPage, Font font, int pageNumber)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(outPage.Content, false);
5
6 // Create text object
7 Text text = Text.Create(outDoc);
8
9 // Create a text generator with the given font, size and position
10 using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
11 {
12 // Generate string to be stamped as page number
13 string stampText = string.Format("Page {0}", pageNumber);
14
15 // Calculate position for centering text at bottom of page
16 Point position = new Point
17 {
18 X = (outPage.Size.Width / 2) - (textgenerator.GetWidth(stampText) / 2),
19 Y = 10
20 };
21
22 // Position the text
23 textgenerator.MoveTo(position);
24 // Add page number
25 textgenerator.Show(stampText);
26 }
27 // Paint the positioned text
28 generator.PaintText(text);
29}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy pages from input to output
15 int pageNo = 1;
16
17 // Create embedded font in output document
18 Font font = Font.createFromSystem(outDoc, "Arial", "", true);
19
20 // Loop through all pages of input
21 for (Page inPage : inDoc.getPages()) {
22 // Copy page from input to output
23 Page outPage = Page.copy(outDoc, inPage, copyOptions);
24
25 // Stamp page number on current page of output document
26 applyStamps(outDoc, outPage, font, pageNo++);
27
28 // Add page to output document
29 outDoc.getPages().add(outPage);
30 }
31 }
32}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void applyStamps(Document doc, Page page, Font font, int pageNo) throws ToolboxException, IOException {
2
3 try (// Create content generator
4 ContentGenerator generator = new ContentGenerator(page.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(doc);
7
8 try (// Create a text generator with the given font, size and position
9 TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
10
11 // Generate string to be stamped as page number
12 String stampText = String.format("Page %d", pageNo);
13
14 // Calculate position for centering text at bottom of page
15 Point position = new Point((page.getSize().width / 2) - (textgenerator.getWidth(stampText) / 2), 10);
16
17 // Position the text
18 textgenerator.moveTo(position);
19 // Add page number
20 textgenerator.show(stampText);
21 }
22
23 // Paint the positioned text
24 generator.paintText(text);
25 }
26}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def add_page_number(out_doc, out_page, font, page_number):
2 """Stamp the page number on the specified page."""
3 # Create content generator
4 with ContentGenerator(out_page.content, False) as generator:
5 # Create text object
6 text = Text.create(out_doc)
7
8 # Create a text generator with the given font, size, and position
9 with TextGenerator(text, font, 8, None) as text_generator:
10 # Generate string to be stamped as the page number
11 stamp_text = f"Page {page_number}"
12
13 # Calculate position for centering text at the bottom of the page
14 position = Point(
15 x=(out_page.size.width / 2) - (text_generator.get_width(stamp_text) / 2),
16 y=10
17 )
18
19 # Position the text
20 text_generator.move_to(position)
21 # Add page number
22 text_generator.show(stamp_text)
23
24 # Paint the positioned text
25 generator.paint_text(text)
Content Modification
Remove glyphs
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Process each page
13 foreach (var inPage in inDoc.Pages)
14 {
15 // Create empty output page
16 Page outPage = Page.Create(outDoc, inPage.Size);
17 // Copy page content from input to output and remove glyphs
18 CopyContentAndRemoveGlyphs(inPage.Content, outPage.Content, outDoc);
19 // Add the new page to the output document's page list
20 outDoc.Pages.Add(outPage);
21 }
22}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void CopyContentAndRemoveGlyphs(Content inContent, Content outContent, Document outDoc)
2{
3 // Use a content extractor and a content generator to copy content
4 ContentExtractor extractor = new ContentExtractor(inContent);
5 using ContentGenerator generator = new ContentGenerator(outContent, false);
6
7 // Iterate over all content elements
8 foreach (ContentElement inElement in extractor)
9 {
10 ContentElement outElement;
11 // Special treatment for group elements
12 if (inElement is GroupElement inGroupElement)
13 {
14 // Create empty output group element
15 GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
16 outElement = outGroupElement;
17 // Call CopyContentAndRemoveGlyphs() recursively for the group element's content
18 CopyContentAndRemoveGlyphs(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc);
19 }
20 else
21 {
22 // Copy the content element to the output document
23 outElement = ContentElement.Copy(outDoc, inElement);
24 if (outElement is TextElement outTextElement)
25 {
26 // Special treatment for text element
27 Text text = outTextElement.Text;
28 // Remove the first two glyphs from each text fragment
29 foreach (var fragment in text)
30 {
31 // Ensure that the fragment has more than two glyphs
32 if (fragment.Count > 2)
33 {
34 // Call RemoveAt twice
35 fragment.RemoveAt(0);
36 fragment.RemoveAt(0);
37 }
38 }
39 }
40 }
41 // Append the finished output element to the content generator
42 generator.AppendContentElement(outElement);
43 }
44}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Process each page
12 for (Page inPage : inDoc.getPages()) {
13 // Create empty output page
14 Page outPage = Page.create(outDoc, inPage.getSize());
15 // Copy page content from input to output and remove glyphs
16 copyContentAndRemoveGlyphs(inPage.getContent(), outPage.getContent(), outDoc);
17 // Add the new page to the output document's page list
18 outDoc.getPages().add(outPage);
19 }
20 }
21}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void copyContentAndRemoveGlyphs(Content inContent, Content outContent, Document outDoc) throws ToolboxException, IOException {
2 // Use a content extractor and a content generator to copy content
3 ContentExtractor extractor = new ContentExtractor(inContent);
4 try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
5 // Iterate over all content elements
6 for (ContentElement inElement : extractor) {
7 ContentElement outElement = null;
8 // Special treatment for group elements
9 if (inElement instanceof GroupElement) {
10 GroupElement inGroupElement = (GroupElement)inElement;
11 // Create empty output group element
12 GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
13 outElement = outGroupElement;
14 // Call copyContentAndRemoveGlyphs() recursively for the group element's content
15 copyContentAndRemoveGlyphs(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc);
16 } else {
17 // Copy the content element to the output document
18 outElement = ContentElement.copy(outDoc, inElement);
19 if (outElement instanceof TextElement) {
20 // Special treatment for text element
21 TextElement outTextElement = (TextElement)outElement;
22 Text text = outTextElement.getText();
23 // Remove the first two glyphs from each text fragment
24 for (int iFragment = 0; iFragment < text.size(); ++iFragment) {
25 // Ensure that the fragment has more than two glyphs
26 if (text.get(iFragment).size() > 2) {
27 // Call remove twice
28 text.get(iFragment).remove(0);
29 text.get(iFragment).remove(0);
30 }
31 }
32 }
33 }
34 // Append the finished output element to the content generator
35 generator.appendContentElement(outElement);
36 }
37 }
38}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def copy_content_and_remove_glyphs(in_content: Content, out_content: Content, out_doc: Document):
2 """Process content to remove the first two glyphs from text fragments."""
3 # Use a content extractor and a content generator to copy content
4 extractor = ContentExtractor(in_content)
5 with ContentGenerator(out_content, False) as generator:
6
7 # Iterate over all content elements
8 for in_element in extractor:
9 # Special treatment for group elements
10 if isinstance(in_element, GroupElement):
11 # Create empty output group element
12 out_group_element = GroupElement.copy_without_content(out_doc, in_element)
13 out_element = out_group_element
14 copy_content_and_remove_glyphs(in_element.group.content, out_group_element.group.content, out_doc)
15 else:
16 # Copy the content element to the output document
17 out_element = ContentElement.copy(out_doc, in_element)
18 if isinstance(out_element, TextElement):
19 # Special treatment for text element
20 text = out_element.text
21 # Remove the first two glyphs from each text fragment
22 for fragment in text:
23 # Ensure that the fragment has more than two glyphs
24 if len(fragment) > 2:
25 # Call RemoveAt twice
26 fragment.remove(0)
27 fragment.remove(0)
28
29 # Append the finished output element to the content generator
30 generator.append_content_element(out_element)
Remove White Text from PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Process each page
13 foreach (var inPage in inDoc.Pages)
14 {
15 // Create empty output page
16 Page outPage = Page.Create(outDoc, inPage.Size);
17 // Copy page content from input to output
18 CopyContent(inPage.Content, outPage.Content, outDoc);
19 // Add the new page to the output document's page list
20 outDoc.Pages.Add(outPage);
21 }
22}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void CopyContent(Content inContent, Content outContent, Document outDoc)
2{
3 // Use a content extractor and a content generator to copy content
4 ContentExtractor extractor = new ContentExtractor(inContent);
5 using ContentGenerator generator = new ContentGenerator(outContent, false);
6
7 // Iterate over all content elements
8 foreach (ContentElement inElement in extractor)
9 {
10 ContentElement outElement;
11 // Special treatment for group elements
12 if (inElement is GroupElement inGroupElement)
13 {
14 // Create empty output group element
15 GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
16 outElement = outGroupElement;
17 // Call CopyContent() recursively for the group element's content
18 CopyContent(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc);
19 }
20 else
21 {
22 // Copy the content element to the output document
23 outElement = ContentElement.Copy(outDoc, inElement);
24 if (outElement is TextElement outTextElement)
25 {
26 // Special treatment for text element
27 Text text = outTextElement.Text;
28 // Remove all those text fragments whose fill and stroke paint is white
29 for (int iFragment = text.Count - 1; iFragment >= 0; iFragment--)
30 {
31 TextFragment fragment = text[iFragment];
32 if ((fragment.Fill == null || IsWhite(fragment.Fill.Paint)) &&
33 (fragment.Stroke == null || IsWhite(fragment.Stroke.Paint)))
34 text.RemoveAt(iFragment);
35 }
36 // Prevent appending an empty text element
37 if (text.Count == 0)
38 outElement = null;
39 }
40 }
41 // Append the finished output element to the content generator
42 if (outElement != null)
43 generator.AppendContentElement(outElement);
44 }
45}
1private static bool IsWhite(Paint paint)
2{
3 ColorSpace colorSpace = paint.ColorSpace;
4 if (colorSpace is DeviceGrayColorSpace || colorSpace is CalibratedGrayColorSpace ||
5 colorSpace is DeviceRgbColorSpace || colorSpace is CalibratedRgbColorSpace)
6 {
7 // These color spaces are additive: white is 1.0
8 return paint.Color.Min() == 1.0;
9 }
10 if (colorSpace is DeviceCmykColorSpace)
11 {
12 // This color space is subtractive: white is 0.0
13 return paint.Color.Max() == 0.0;
14 }
15 return false;
16}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Process each page
12 for (Page inPage : inDoc.getPages()) {
13 // Create empty output page
14 Page outPage = Page.create(outDoc, inPage.getSize());
15 // Copy page content from input to output
16 copyContent(inPage.getContent(), outPage.getContent(), outDoc);
17 // Add page to output document
18 outDoc.getPages().add(outPage);
19 }
20 }
21}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void copyContent(Content inContent, Content outContent, Document outDoc) throws ToolboxException, IOException {
2 // Use a content extractor and a content generator to copy content
3 ContentExtractor extractor = new ContentExtractor(inContent);
4 try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
5 // Iterate over all content elements
6 for (ContentElement inElement : extractor) {
7 ContentElement outElement = null;
8 // Special treatment for group elements
9 if (inElement instanceof GroupElement) {
10 GroupElement inGroupElement = (GroupElement)inElement;
11 // Create empty output group element
12 GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
13 outElement = outGroupElement;
14 // Call copyContent() recursively for the group element's content
15 copyContent(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc);
16 } else {
17 // Copy the content element to the output document
18 outElement = ContentElement.copy(outDoc, inElement);
19 if (outElement instanceof TextElement) {
20 // Special treatment for text element
21 TextElement outTextElement = (TextElement)outElement;
22 Text text = outTextElement.getText();
23 // Remove all those text fragments whose fill and stroke paint is white
24 for (int iFragment = text.size() - 1; iFragment >= 0; iFragment--) {
25 TextFragment fragment = text.get(iFragment);
26 if ((fragment.getFill() == null || isWhite(fragment.getFill().getPaint())) &&
27 (fragment.getStroke() == null || isWhite(fragment.getStroke().getPaint())))
28 text.remove(iFragment);
29 }
30 // Prevent appending an empty text element
31 if (text.size() == 0)
32 outElement = null;
33 }
34 }
35 // Append the finished output element to the content generator
36 if (outElement != null)
37 generator.appendContentElement(outElement);
38 }
39 }
40}
1private static boolean isWhite(Paint paint) {
2 double[] color = paint.getColor();
3 ColorSpace colorSpace = paint.getColorSpace();
4 if (colorSpace instanceof DeviceGrayColorSpace || colorSpace instanceof CalibratedGrayColorSpace ||
5 colorSpace instanceof DeviceRgbColorSpace || colorSpace instanceof CalibratedRgbColorSpace) {
6 // These color spaces are additive: white is 1.0
7 for (double value : color)
8 if (value != 1.0)
9 return false;
10 return true;
11 }
12 if (colorSpace instanceof DeviceCmykColorSpace) {
13 // This color space is subtractive: white is 0.0
14 for (double value : color)
15 if (value != 0.0)
16 return false;
17 return true;
18 }
19 return false;
20}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def is_white(paint: Paint) -> bool:
2 """Determine if a paint is white based on its color space."""
3 color_space = paint.color_space
4 color = paint.color
5
6 if isinstance(color_space, (DeviceGrayColorSpace, CalibratedGrayColorSpace, DeviceRgbColorSpace, CalibratedRgbColorSpace)):
7 # These color spaces are additive: white is 1.0
8 return min(color) == 1.0
9 if isinstance(color_space, DeviceCmykColorSpace):
10 # This color space is subtractive: white is 0.0
11 return max(color) == 0.0
12
13 return False
1def copy_content_and_remove_white_text(in_content: Content, out_content: Content, out_doc: Document):
2 """Process content to remove white text fragments."""
3 # Use a content extractor and a content generator to copy content
4 extractor = ContentExtractor(in_content)
5 with ContentGenerator(out_content, False) as generator:
6
7 # Iterate over all content elements
8 for in_element in extractor:
9 # Special treatment for group elements
10 if isinstance(in_element, GroupElement):
11 # Create empty output group element
12 out_group_element = GroupElement.copy_without_content(out_doc, in_element)
13 out_element = out_group_element
14 copy_content_and_remove_white_text(in_element.group.content, out_group_element.group.content, out_doc)
15 else:
16 # Copy the content element to the output document
17 out_element = ContentElement.copy(out_doc, in_element)
18 if isinstance(out_element, TextElement):
19 text = out_element.text
20 # Remove all those text fragments whose fill and stroke paint is white
21 for i_fragment in range(len(text) - 1, -1, -1):
22 fragment = text[i_fragment]
23 if ((fragment.fill is None or is_white(fragment.fill.paint)) and
24 (fragment.stroke is None or is_white(fragment.stroke.paint))):
25 text.remove(i_fragment)
26 # Prevent appending an empty text element
27 if len(text) == 0:
28 out_element = None
29
30 # Append the finished output element to the content generator
31 if out_element:
32 generator.append_content_element(out_element)
Replace Text Fragment in PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Process each page
13 foreach (var inPage in inDoc.Pages)
14 {
15 // Create empty output page
16 Page outPage = Page.Create(outDoc, inPage.Size);
17 // Copy page content from input to output and search for string
18 CopyContent(inPage.Content, outPage.Content, outDoc, searchString);
19 // If the text was found and deleted, add the replacement text
20 if (fragment != null)
21 AddText(outDoc, outPage, replString);
22 // Add the new page to the output document's page list
23 outDoc.Pages.Add(outPage);
24 }
25}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void CopyContent(Content inContent, Content outContent, Document outDoc, string searchString)
2{
3 // Use a content extractor and a content generator to copy content
4 ContentExtractor extractor = new ContentExtractor(inContent);
5 using ContentGenerator generator = new ContentGenerator(outContent, false);
6
7 // Iterate over all content elements
8 foreach (ContentElement inElement in extractor)
9 {
10 ContentElement outElement;
11 // Special treatment for group elements
12 if (inElement is GroupElement inGroupElement)
13 {
14 // Create empty output group element
15 GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
16 outElement = outGroupElement;
17 // Save transform for later restore
18 AffineTransform currentTransform = overallTransform;
19 // Update the transform
20 overallTransform.Concatenate(inGroupElement.Transform);
21 // Call CopyContent() recursively for the group element's content
22 CopyContent(inGroupElement.Group.Content, outGroupElement.Group.Content, outDoc, searchString);
23 // Restore the transform
24 overallTransform = currentTransform;
25 }
26 else
27 {
28 // Copy the content element to the output document
29 outElement = ContentElement.Copy(outDoc, inElement);
30 if (fragment == null && outElement is TextElement outTextElement)
31 {
32 // Special treatment for text element
33 Text text = outTextElement.Text;
34 // Find text fragment with string to replace
35 for (int iFragment = text.Count - 1; iFragment >= 0; iFragment--)
36 {
37 // In this sample, the fragment text must match in its entirety
38 if (text[iFragment].Text == searchString)
39 {
40 // Keep the found fragment for later use
41 fragment = text[iFragment];
42 // Update the transform
43 overallTransform.Concatenate(fragment.Transform);
44 // Remove the found text fragment from the output
45 text.RemoveAt(iFragment);
46 break;
47 }
48 }
49 // Prevent appending an empty text element
50 if (text.Count == 0)
51 outElement = null;
52 }
53 }
54 // Append the finished output element to the content generator
55 if (outElement != null)
56 generator.AppendContentElement(outElement);
57 }
58}
1private static void AddText(Document doc, Page page, string replString)
2{
3 // Create a new text object
4 Text text = Text.Create(doc);
5 // Heuristic to map the extracted font base name to a font name and font family
6 string[] parts = fragment.Font.BaseFont.Split('-');
7 string family = parts[0];
8 string style = parts.Length > 1 ? parts[1] : null;
9 // Create a new font object
10 Font font = Font.CreateFromSystem(doc, family, style, true);
11 // Create a text generator and set the original fragment's properties
12 using (TextGenerator textGenerator = new TextGenerator(text, font, fragment.FontSize, null))
13 {
14 textGenerator.CharacterSpacing = fragment.CharacterSpacing;
15 textGenerator.WordSpacing = fragment.WordSpacing;
16 textGenerator.HorizontalScaling = fragment.HorizontalScaling;
17 textGenerator.Rise = fragment.Rise;
18 textGenerator.Show(replString);
19 }
20 // Create a content generator
21 using ContentGenerator contentGenerator = new ContentGenerator(page.Content, false);
22 // Apply the computed transform
23 contentGenerator.Transform(overallTransform);
24 // Paint the new text
25 contentGenerator.PaintText(text);
26}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Process each page
12 for (Page inPage : inDoc.getPages()) {
13 // Create empty output page
14 Page outPage = Page.create(outDoc, inPage.getSize());
15 // Copy page content from input to output and search for string
16 copyContent(inPage.getContent(), outPage.getContent(), outDoc, searchString);
17 // If the text was found and deleted, add the replacement text
18 if (fragment != null)
19 addText(outDoc, outPage, replString);
20 // Add page to output document
21 outDoc.getPages().add(outPage);
22 }
23 }
24}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void copyContent(Content inContent, Content outContent, Document outDoc, String searchString) throws ToolboxException, IOException {
2 // Use a content extractor and a content generator to copy content
3 ContentExtractor extractor = new ContentExtractor(inContent);
4 try (ContentGenerator generator = new ContentGenerator(outContent, false)) {
5 // Iterate over all content elements
6 for (ContentElement inElement : extractor) {
7 ContentElement outElement = null;
8 // Special treatment for group elements
9 if (inElement instanceof GroupElement) {
10 GroupElement inGroupElement = (GroupElement)inElement;
11 // Create empty output group element
12 GroupElement outGroupElement = GroupElement.copyWithoutContent(outDoc, inGroupElement);
13 outElement = outGroupElement;
14 // Save transform for later restor
15 AffineTransform currentTransform = overallTransform;
16 // Update the transform
17 overallTransform.concatenate(inGroupElement.getTransform());
18 // Call copyContent() recursively for the group element's content
19 copyContent(inGroupElement.getGroup().getContent(), outGroupElement.getGroup().getContent(), outDoc, searchString);
20 // Restor the transform
21 overallTransform = currentTransform;
22 } else {
23 // Copy the content element to the output document
24 outElement = ContentElement.copy(outDoc, inElement);
25 if (fragment == null && outElement instanceof TextElement) {
26 // Special treatment for text element
27 TextElement outTextElement = (TextElement)outElement;
28 Text text = outTextElement.getText();
29 // Find text fragment with string to replace
30 for (int iFragment = text.size() - 1; iFragment >= 0; iFragment--) {
31 // In this sample, the fragment text must match in its entirety
32 if (text.get(iFragment).getText().equals(searchString)) {
33 // Keep the found fragment for later use
34 fragment = text.get(iFragment);
35 // Update the transform
36 overallTransform.concatenate(fragment.getTransform());
37 // Remove the found text fragment from the output
38 text.remove(iFragment);
39 break;
40 }
41 }
42 // Prevent appending an empty text element
43 if (text.size() == 0)
44 outElement = null;
45 }
46 }
47 // Append the finished output element to the content generator
48 if (outElement != null)
49 generator.appendContentElement(outElement);
50 }
51 }
52}
1private static void addText(Document doc, Page page, String replString) throws CorruptException, ToolboxException, IOException {
2 // Create a new text object
3 Text text = Text.create(doc);
4 // Heuristic to map the extracted fon base name to a font family and font style
5 String[] parts = fragment.getFont().getBaseFont().split("-");
6 String family = parts[0];
7 String style = parts.length > 1 ? parts[1] : null;
8 // Create a new font object
9 Font font = Font.createFromSystem(doc, family, style, true);
10 // Create a text generator and set the original fragment's properties
11 try (TextGenerator textGenerator = new TextGenerator(text, font, fragment.getFontSize(), null)) {
12 textGenerator.setCharacterSpacing(fragment.getCharacterSpacing());
13 textGenerator.setWordSpacing(fragment.getWordSpacing());
14 textGenerator.setHorizontalScaling(fragment.getHorizontalScaling());
15 textGenerator.setRise(fragment.getRise());
16 textGenerator.show(replString);
17 }
18 // Create a content generator
19 try (ContentGenerator contentGenerator = new ContentGenerator(page.getContent(), false)) {
20 // Apply the computed transform
21 contentGenerator.transform(overallTransform);
22 // Paint the new text
23 contentGenerator.paintText(text);
24 }
25}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def copy_content_and_remove_text(in_content: Content, out_content: Content, out_doc: Document, search_text: str):
2 """Process content to find and remove a specific text fragment."""
3 global overall_transform, fragment
4
5 # Use a content extractor and a content generator to copy content
6 extractor = ContentExtractor(in_content)
7 with ContentGenerator(out_content, False) as generator:
8
9 # Iterate over all content elements
10 for in_element in extractor:
11 # Special treatment for group elements
12 if isinstance(in_element, GroupElement):
13 out_group_element = GroupElement.copy_without_content(out_doc, in_element)
14 out_element = out_group_element
15 # Save transform for later restore
16 current_transform = overall_transform
17 # Update the transform
18 copy_content_and_remove_text(in_element.group.content, out_group_element.group.content, out_doc, search_text)
19 # Restore the transform
20 overall_transform = current_transform
21 else:
22 # Copy the content element to the output document
23 out_element = ContentElement.copy(out_doc, in_element)
24 if isinstance(out_element, TextElement) and fragment is None:
25 # Special treatment for text element
26 text = out_element.text
27 # Find text fragment with string to replace
28 for index_fragment in range(len(text) - 1, -1, -1):
29 # In this sample, the fragment text must match in its entirety (Text might contain null characters)
30 if text[index_fragment].text.replace("\x00", "") == search_text:
31 # Keep the found fragment for later use
32 fragment = text[index_fragment]
33 # Update the transform
34 overall_transform.concatenate(fragment.transform)
35 # Remove the fragment from the text element
36 text.remove(index_fragment)
37
38 # Prevent appending an empty text element
39 if len(text) == 0:
40 out_element = None
41
42 # Append the finished output element to the content generator
43 if out_element:
44 generator.append_content_element(out_element)
1def add_text(out_doc: Document, page, replacement_text):
2 """Add the replacement text at the location of the removed fragment."""
3 # Create a new text object
4 text = Text.create(out_doc)
5 # Heuristic to map the extracted font base name to a font name and font family
6 font_parts = fragment.font.base_font.split("-")
7 font_family = font_parts[0]
8 font_style = font_parts[1] if len(font_parts) > 1 else None
9
10 # Create a new font object
11 font = Font.create_from_system(out_doc, font_family, font_style, True)
12
13 # Create a text generator and set the original fragment's properties
14 with TextGenerator(text, font, fragment.font_size, None) as text_gen:
15 text_gen.character_spacing = fragment.character_spacing
16 text_gen.word_spacing = fragment.word_spacing
17 text_gen.horizontal_scaling = fragment.horizontal_scaling
18 text_gen.rise = fragment.rise
19 text_gen.show(replacement_text)
20
21 # Create a content generator
22 with ContentGenerator(page.content, False) as content_gen:
23 # Apply the computed transform
24 content_gen.transform(overall_transform)
25 # Paint the new text
26 content_gen.paint_text(text)
Custom Validation
Validate custom properties of a PDF file
1var iniFile = new IniFile(args[1]);
2var password = args.Length == 3 ? args[2] : null;
3var documentValidator = new DocumentValidator(iniFile, args[0], password);
4
5try
6{
7 if (documentValidator.ValidateDocument())
8 Console.WriteLine("\nThe document does conform the specified properties.");
9 else
10 Console.WriteLine("\nThe document does not conform the specified properties.");
11}
12catch (Exception ex)
13{
14 Console.WriteLine("The document could not be validated. The following error happened: " + ex.Message);
15 return;
16}
1public class IniFile
2{
3 private Dictionary<string, Dictionary<string, string>> _data;
4
5 public IniFile(string path)
6 {
7 _data = new Dictionary<string, Dictionary<string, string>>();
8 Load(path);
9 }
10
11 private void Load(string path)
12 {
13 var lines = File.ReadAllLines(path);
14 var currentSection = "";
15
16 foreach (var line in lines)
17 {
18 var trimmedLine = line.Trim();
19
20 if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith(";") || trimmedLine.StartsWith("#"))
21 {
22 continue; // Skip empty lines and comments
23 }
24
25 if (trimmedLine.StartsWith("[") && trimmedLine.EndsWith("]"))
26 {
27 currentSection = trimmedLine.Substring(1, trimmedLine.Length - 2).Trim();
28 if (!_data.ContainsKey(currentSection))
29 {
30 _data[currentSection] = new Dictionary<string, string>();
31 }
32 else
33 {
34 throw new FormatException("Duplicate section: " + currentSection);
35 }
36 }
37 else if (currentSection != null)
38 {
39 var keyValuePair = trimmedLine.Split(new[] { '=' });
40 if (keyValuePair.Length == 2)
41 {
42 var key = keyValuePair[0].Trim();
43 var value = keyValuePair[1].Trim();
44 _data[currentSection][key] = value;
45 }
46 }
47 }
48 }
49
50 public string? GetValue(string section, string key, string? defaultValue = null)
51 {
52 if (_data.TryGetValue(section, out var sectionData))
53 {
54 if (sectionData.TryGetValue(key, out var value))
55 {
56 return value;
57 }
58 }
59 return defaultValue;
60 }
61
62 public List<string> GetKeysMatchingPattern(string section, string pattern)
63 {
64 var matchingKeys = new List<string>();
65
66 if (_data.TryGetValue(section, out var sectionData))
67 {
68 foreach (var key in sectionData.Keys)
69 {
70 if (Regex.IsMatch(key, pattern, RegexOptions.IgnoreCase))
71 {
72 matchingKeys.Add(sectionData[key]);
73 }
74 }
75 }
76
77 return matchingKeys;
78 }
79}
1public class DocumentValidator
2{
3 private readonly IniFile _iniFile;
4 private readonly string _inputPath;
5 private readonly string? _pdfPassword;
6
7 // Tolerance used for size comparison: default 3pt
8 private string _sizeTolerance = "3.0";
9 private string? _iniMaxPageSize;
10 private string? _iniMaxPdfVersionStr;
11 private string? _iniEncryption;
12 private string? _iniFileSize;
13 private string? _iniEmbedding;
14 private readonly List<string> _embeddingExceptionFonts;
15
16 public DocumentValidator(IniFile iniFile, string inputPath, string? pdfPassword = null)
17 {
18 _iniFile = iniFile;
19 _inputPath = inputPath;
20 _pdfPassword = pdfPassword;
21
22 // Extract values from INI file
23 string? iniSizeTolerance = iniFile.GetValue("Pages", "SizeTolerance");
24 _sizeTolerance = !string.IsNullOrEmpty(iniSizeTolerance) ? iniSizeTolerance : _sizeTolerance;
25 _iniMaxPageSize = _iniFile.GetValue("Pages", "MaxPageSize");
26 _iniMaxPdfVersionStr = _iniFile.GetValue("File", "MaxPdfVersion");
27 _iniEncryption = _iniFile.GetValue("File", "Encryption");
28 _iniFileSize = _iniFile.GetValue("File", "FileSize");
29 _iniEmbedding = _iniFile.GetValue("Fonts", "Embedding");
30 _embeddingExceptionFonts = _iniFile.GetKeysMatchingPattern("Fonts", @"EmbeddingExcFont\d+");
31 }
32
33 public bool ValidateDocument()
34 {
35 var isValid = ValidateFileSize();
36
37 try
38 {
39 using var inpath = File.OpenRead(_inputPath);
40 using var inDoc = Document.Open(inpath, _pdfPassword);
41
42 isValid &= ValidateConformance(inDoc.Conformance);
43 isValid &= ValidateEncryption(inDoc.Permissions);
44 isValid &= ValidatePagesSize(inDoc);
45 isValid &= ValidateFonts(inDoc);
46 }
47 catch (PasswordException)
48 {
49 if (_pdfPassword == null)
50 Console.WriteLine("The content of the document could not be validated as it is password protected. Please provide a password.");
51 else
52 Console.WriteLine("The content of the document could not be validated as the password provided is not correct.");
53
54 return false;
55 }
56
57 return isValid;
58 }
59
60 private bool ValidateFileSize()
61 {
62 var fileInfo = new FileInfo(_inputPath);
63 var fileSizeInMB = fileInfo.Length / (1024.0 * 1024.0);
64
65 if (_iniFileSize != null)
66 {
67 var iniFileSizeInMB = Convert.ToDouble(_iniFileSize);
68 if (fileSizeInMB <= iniFileSizeInMB)
69 {
70 Console.WriteLine("The PDF file size does not exceed the specified custom limit.");
71
72 return true;
73 }
74 else
75 {
76 Console.WriteLine("The PDF file size exceeds the specified custom limit.");
77
78 return false;
79 }
80 }
81
82 return true;
83 }
84
85 private bool ValidateConformance(Conformance currentConformance)
86 {
87 if (_iniMaxPdfVersionStr != null)
88 {
89 if (ConformanceValidator.ValidateConformance(_iniMaxPdfVersionStr, currentConformance))
90 {
91 Console.WriteLine("The PDF version does not exceed the specified custom maximum version.");
92
93 return true;
94 }
95 else
96 {
97 Console.WriteLine("The PDF version exceeds the specified custom maximum version.");
98
99 return false;
100 }
101 }
102
103 return true;
104 }
105
106 private bool ValidateEncryption(Permission? permissions)
107 {
108 if (_iniEncryption != null)
109 {
110 if (_iniEncryption.ToLower() == "true" && permissions == null)
111 {
112 Console.WriteLine("Encryption not conform: the PDF file is not encrypted. The custom encryption value specifies that the PDF file should be encrypted.");
113
114 return false;
115 }
116 else if (_iniEncryption.ToLower() == "false" && permissions != null)
117 {
118 Console.WriteLine("Encryption not conform: the PDF file is encrypted. The custom encryption value specifies that the PDF file should not be encrypted.");
119
120 return false;
121 }
122 else
123 {
124 Console.WriteLine("The PDF encryption is conform to the specified custom value.");
125
126 return true;
127 }
128 }
129
130 return true;
131 }
132
133 private bool ValidatePagesSize(Document inDoc)
134 {
135 var isValid = true;
136
137 if (_iniMaxPageSize != null)
138 {
139 var pageNumber = 0;
140 foreach (var page in inDoc.Pages)
141 {
142 pageNumber++;
143 var sizeWithInt = new Size { Width = (int)page.Size.Width, Height = (int)page.Size.Height };
144
145 isValid &= ValidatePageSize(pageNumber, sizeWithInt);
146 }
147 }
148
149 return isValid;
150 }
151
152 private bool ValidatePageSize(int pageNumber, Size pageSize)
153 {
154 if (_iniMaxPageSize != null)
155 {
156 var validator = new PageSizeValidator(_iniMaxPageSize, _sizeTolerance);
157 if (validator.ValidatePageSize(pageNumber, pageSize))
158 {
159 Console.WriteLine("The size of page " + pageNumber + " is within the specified custom maximum page size value.");
160
161 return true;
162 }
163 else
164 {
165 Console.WriteLine("The size of page " + pageNumber + " exceeds the specified custom maximum page size value.");
166
167 return false;
168 }
169 }
170
171 return true;
172 }
173
174 private bool ValidateFonts(Document inDoc)
175 {
176 var isValid = true;
177
178 if (_iniEmbedding != null)
179 {
180 var embeddingRequired = _iniEmbedding.ToLower() == "true";
181 var pageNumber = 0;
182
183 foreach (var page in inDoc.Pages)
184 {
185 pageNumber++;
186 var extractor = new ContentExtractor(page.Content)
187 {
188 Ungrouping = UngroupingSelection.SafelyUngroupable
189 };
190
191 foreach (ContentElement element in extractor)
192 {
193 if (element is TextElement textElement)
194 {
195 foreach (var fragment in textElement.Text)
196 {
197 var fontName = fragment.Font.BaseFont;
198 var isEmbedded = fragment.Font.IsEmbedded;
199
200 // Check if the font is in the exception list
201 var isCurrentFontAnException = _embeddingExceptionFonts.Exists(exception => Regex.IsMatch(fontName, exception.Replace("*", ".*"), RegexOptions.IgnoreCase));
202
203 // Validate based on the embedding setting
204 // _iniEmbedding = true => The font has to be embedded or it should appear in the exception list
205 // _iniEmbedding = false => The font cannot be embedded or it should appear in the exception list
206 if ((embeddingRequired && !isEmbedded && !isCurrentFontAnException) || (!embeddingRequired && isEmbedded && !isCurrentFontAnException))
207 {
208 isValid = false;
209 var statusText = embeddingRequired ? "be embedded" : "not be embedded";
210 Console.WriteLine("The font '" + fontName + "' on page " + pageNumber + " should " + statusText + " as specified by the property 'Embedding' or it should be added to the list of exceptions.");
211 }
212 else
213 {
214 var statusText = embeddingRequired != isEmbedded ? "in the exception list" : isEmbedded ? "embedded" : "not embedded";
215 Console.WriteLine("The font '" + fontName + "' on page " + pageNumber + " is conform to the 'Embedding' property as it is " + statusText + ".");
216 }
217 }
218 }
219 }
220 }
221 }
222
223 return isValid;
224 }
225}
1public class PageSizeValidator
2{
3 private readonly Size maxSize;
4 private readonly double sizeTolerance;
5
6 // Named page sizes like "Letter", "A4", etc.
7 private static readonly Dictionary<string, Size> NamedPageSizes = new Dictionary<string, Size>(StringComparer.OrdinalIgnoreCase)
8 {
9 { "Letter", new Size { Width = 612, Height = 792 } }, // 8.5 x 11 inches in points
10 { "A0", new Size { Width = 2384, Height = 3370 } },
11 { "A1", new Size { Width = 1684, Height = 2384 } },
12 { "A2", new Size { Width = 1191, Height = 1684 } },
13 { "A3", new Size { Width = 842, Height = 1191 } },
14 { "A4", new Size { Width = 595, Height = 842 } }, // 210 x 297 mm in points
15 { "A5", new Size { Width = 420, Height = 595 } },
16 { "A6", new Size { Width = 298, Height = 420 } },
17 { "A7", new Size { Width = 210, Height = 298 } },
18 { "A8", new Size { Width = 147, Height = 210 } },
19 { "A9", new Size { Width = 105, Height = 147 } },
20 { "A10", new Size { Width = 74, Height = 105 } },
21 { "DL", new Size { Width = 283, Height = 595 } } // 99 x 210 mm in points
22 };
23
24 public PageSizeValidator(string maxPageSizeStr, string sizeToleranceStr)
25 {
26 maxSize = ParsePageSize(maxPageSizeStr);
27 sizeTolerance = ParseSizeTolerance(sizeToleranceStr);
28 }
29
30 private Size ParsePageSize(string maxPageSize)
31 {
32 // First, check if it's a named size
33 if (NamedPageSizes.TryGetValue(maxPageSize, out var namedSize))
34 {
35 return namedSize;
36 }
37
38 // If not a named size, try to parse it as a custom size
39 var match = Regex.Match(maxPageSize, @"(\d+(\.\d+)?)\s*x\s*(\d+(\.\d+)?)(\s*(pt|in|cm|mm))?", RegexOptions.IgnoreCase);
40 if (!match.Success) throw new ArgumentException("Invalid MaxPageSize format: " + maxPageSize);
41
42 double width = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
43 double height = double.Parse(match.Groups[3].Value, CultureInfo.InvariantCulture);
44 string unit = match.Groups[6].Value.ToLower();
45
46 return unit switch
47 {
48 "in" => new Size { Width = (int)(width * 72), Height = (int)(height * 72) },
49 "cm" => new Size { Width = (int)(width * 28.3465), Height = (int)(height * 28.3465) },
50 "mm" => new Size { Width = (int)(width * 2.83465), Height = (int)(height * 2.83465) },
51 "pt" or "" => new Size { Width = (int)width, Height = (int)height },
52 _ => throw new ArgumentException("Unsupported unit: " + unit),
53 };
54 }
55
56 private double ParseSizeTolerance(string sizeToleranceStr)
57 {
58 if (string.IsNullOrEmpty(sizeToleranceStr)) return 3; // Default tolerance in points
59
60 var match = Regex.Match(sizeToleranceStr, @"(\d+(\.\d+)?)\s*(%)?", RegexOptions.IgnoreCase);
61 if (!match.Success) throw new ArgumentException("Invalid SizeTolerance format: " + sizeToleranceStr);
62
63 double value = double.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
64 return match.Groups[3].Success ? value / 100.0 : value; // Percentage tolerance or direct value
65 }
66
67 public bool ValidatePageSize(int pageNumber, Size actualSize)
68 {
69 // Check both portrait and landscape orientations
70 bool isValid = (actualSize.Width <= maxSize.Width + sizeTolerance && actualSize.Height <= maxSize.Height + sizeTolerance) ||
71 (actualSize.Height <= maxSize.Width + sizeTolerance && actualSize.Width <= maxSize.Height + sizeTolerance);
72
73 return isValid;
74 }
75}
1public class ConformanceValidator
2{
3 private static readonly Dictionary<string, Conformance> VersionMap = new Dictionary<string, Conformance>(StringComparer.OrdinalIgnoreCase)
4 {
5 { "1.0", Conformance.Pdf10 },
6 { "1.1", Conformance.Pdf11 },
7 { "1.2", Conformance.Pdf12 },
8 { "1.3", Conformance.Pdf13 },
9 { "1.4", Conformance.Pdf14 },
10 { "1.5", Conformance.Pdf15 },
11 { "1.6", Conformance.Pdf16 },
12 { "1.7", Conformance.Pdf17 },
13 { "2.0", Conformance.Pdf20 }
14 };
15
16 public static Conformance ParseVersionString(string version)
17 {
18 // Split the version string into parts based on the '.' delimiter
19 string[] versionParts = version.Split('.');
20
21 // Ensure there are only two parts (major and minor)
22 if (versionParts.Length == 2)
23 {
24 // Construct the major.minor version string (e.g., "1.7")
25 string majorMinorVersion = versionParts[0] + "." + versionParts[1];
26
27 // Try to get the corresponding Conformance enum value from the dictionary
28 if (VersionMap.TryGetValue(majorMinorVersion, out Conformance conformance))
29 {
30 return conformance;
31 }
32 }
33
34 // If the version is not supported, throw an exception
35 throw new ArgumentException("Unsupported version or conformance level: " + version);
36 }
37
38 public static bool ValidateConformance(string maxPdfVersionStr, Conformance currentConformance)
39 {
40 var maxPdfConformance = ParseVersionString(maxPdfVersionStr);
41 // Convert the current conformance level to the corresponding PDF version (Major.Minor) as it can be based on the PDF/A version
42 var currentConformanceVersion = GetVersionFromConformance(currentConformance);
43
44 return (int)currentConformanceVersion <= (int)maxPdfConformance;
45 }
46
47 public static Conformance GetVersionFromConformance(Conformance conformance)
48 {
49 if (VersionMap.ContainsValue(conformance))
50 {
51 return conformance;
52 }
53
54 switch (conformance)
55 {
56 case Conformance.PdfA1A:
57 case Conformance.PdfA1B:
58 return Conformance.Pdf14; // PDF/A-1 is based on PDF 1.4
59
60 case Conformance.PdfA2A:
61 case Conformance.PdfA2B:
62 case Conformance.PdfA2U:
63 case Conformance.PdfA3A:
64 case Conformance.PdfA3B:
65 case Conformance.PdfA3U:
66 return Conformance.Pdf17; // PDF/A-2 and PDF/A-3 are based on PDF 1.7
67
68 default:
69 throw new ArgumentException("Unsupported conformance level: " + conformance.ToString());
70 }
71 }
72}
1String pdfPath = args[0];
2String iniPath = args[1];
3String password = null;
4if (args.length == 3)
5 password = args[2];
6
7IniFile iniFile = new IniFile(iniPath);
8DocumentValidator documentValidator = new DocumentValidator(iniFile, pdfPath, password);
9
10try {
11 if (documentValidator.validateDocument())
12 System.out.println("\nThe document does conform the specified properties.");
13 else
14 System.out.println("\nThe document does not conform the specified properties.");
15}
16catch(Exception e) {
17 System.out.println("The document could not be validated. The following error happened: " + e.getMessage());
18
19 System.exit(-1);
20}
21
1public static class IniFile {
2 private final Map<String, Map<String, String>> sections = new LinkedHashMap<>();
3
4 public IniFile(String path) throws IOException {
5 load(path);
6 }
7
8 private void load(String path) throws IOException {
9 try (BufferedReader reader = new BufferedReader(new FileReader(path))) {
10 String currentSection = null;
11 String line;
12
13 while ((line = reader.readLine()) != null) {
14 line = line.trim();
15
16 if (line.isEmpty() || line.startsWith(";") || line.startsWith("#")) {
17 // Skip empty lines and comments
18 continue;
19 }
20
21 if (line.startsWith("[") && line.endsWith("]")) {
22 // New section
23 currentSection = line.substring(1, line.length() - 1).trim();
24 sections.putIfAbsent(currentSection, new LinkedHashMap<>());
25 } else if (currentSection != null) {
26 // Key-value pair within a section
27 String[] keyValue = line.split("=", 2);
28 if (keyValue.length == 2) {
29 sections.get(currentSection).put(keyValue[0].trim(), keyValue[1].trim());
30 }
31 }
32 }
33 }
34 }
35
36 public String getValue(String section, String key, String defaultValue) {
37 Map<String, String> sectionData = sections.get(section);
38 if (sectionData != null) {
39 return sectionData.getOrDefault(key, defaultValue);
40 }
41 return defaultValue;
42 }
43
44 public String getValue(String section, String key) {
45 return getValue(section, key, null);
46 }
47
48 public List<String> getKeysMatchingPattern(String section, String pattern) {
49 List<String> matchingKeys = new ArrayList<>();
50
51 Map<String, String> sectionData = sections.get(section);
52 if (sectionData != null) {
53 Pattern regexPattern = Pattern.compile(pattern, Pattern.CASE_INSENSITIVE);
54 for (String key : sectionData.keySet()) {
55 Matcher matcher = regexPattern.matcher(key);
56 if (matcher.find()) {
57 matchingKeys.add(sectionData.get(key));
58 }
59 }
60 }
61
62 return matchingKeys;
63 }
64}
1 public static class DocumentValidator {
2
3 private final String inputPath;
4 private String pdfPassword;
5
6 // Tolerance used for size comparison: default 3pt
7 private String sizeTolerance = "3.0";
8 private String iniMaxPageSize;
9 private String iniMaxPdfVersionStr;
10 private String iniEncryption;
11 private String iniFileSize;
12 private String iniEmbedding;
13 private final List<String> embeddingExceptionFonts;
14
15
16 public DocumentValidator(IniFile iniFile, String inputPath, String pdfPassword) {
17 this.inputPath = inputPath;
18 this.pdfPassword = pdfPassword;
19
20 // Extract values from INI file
21 String iniSizeTolerance = iniFile.getValue("Pages", "SizeTolerance");
22 this.sizeTolerance = (iniSizeTolerance != null && !iniSizeTolerance.isEmpty()) ? iniSizeTolerance : this.sizeTolerance;
23 this.iniMaxPageSize = iniFile.getValue("Pages", "MaxPageSize");
24 this.iniMaxPdfVersionStr = iniFile.getValue("File", "MaxPdfVersion");
25 this.iniEncryption = iniFile.getValue("File", "Encryption");
26 this.iniFileSize = iniFile.getValue("File", "FileSize");
27 this.iniEmbedding = iniFile.getValue("Fonts", "Embedding");
28 this.embeddingExceptionFonts = iniFile.getKeysMatchingPattern("Fonts", "EmbeddingExcFont\\d+");
29 }
30
31 public boolean validateDocument() throws IOException, CorruptException, ConformanceException, UnsupportedFeatureException, ToolboxException {
32 boolean isValid = validateFileSize(inputPath);
33
34 try (FileStream inStream = new FileStream(inputPath, FileStream.Mode.READ_ONLY);
35 Document inDoc = Document.open(inStream, pdfPassword)) {
36
37 isValid &= validateConformance(inDoc.getConformance());
38 isValid &= validateEncryption(inDoc.getPermissions());
39 isValid &= validatePagesSize(inDoc);
40 isValid &= validateFonts(inDoc);
41 }
42 catch(PasswordException e) {
43 if (pdfPassword == null)
44 System.out.println("The content of the document could not be validated as it is password protected. Please provide a password.");
45 else
46 System.out.println("The content of the document could not be validated as the password provided is not correct.");
47
48 return false;
49 }
50
51 return isValid;
52 }
53
54 private boolean validateFileSize(String inputPath) {
55 File file = new File(inputPath);
56 double fileSizeInMB = file.length() / (1024.0 * 1024.0);
57
58 if (iniFileSize != null) {
59 double iniFileSizeInMB = Double.parseDouble(iniFileSize);
60 if (fileSizeInMB <= iniFileSizeInMB) {
61 System.out.println("The PDF file size does not exceed the specified custom limit.");
62 return true;
63 } else {
64 System.out.println("The PDF file size exceeds the specified custom limit.");
65 return false;
66 }
67 }
68 return true;
69 }
70
71 private boolean validateConformance(Conformance currentConformance) {
72 if (iniMaxPdfVersionStr != null) {
73 if (ConformanceValidator.validateConformance(iniMaxPdfVersionStr, currentConformance)) {
74 System.out.println("The PDF version does not exceed the specified custom maximum version.");
75 return true;
76 } else {
77 System.out.println("The PDF version exceeds the specified custom maximum version.");
78 return false;
79 }
80 }
81
82 return true;
83 }
84
85 private boolean validateEncryption(EnumSet<Permission> enumSet) {
86 if (iniEncryption != null) {
87 boolean isEncrypted = enumSet != null;
88
89 if ("true".equalsIgnoreCase(iniEncryption) && !isEncrypted) {
90 System.out.println("Encryption not conform: the PDF file is not encrypted. The custom encryption value specifies that the PDF file should be encrypted.");
91 return false;
92 } else if ("false".equalsIgnoreCase(iniEncryption) && isEncrypted) {
93 System.out.println("Encryption not conform: the PDF file is encrypted. The custom encryption value specifies that the PDF file should not be encrypted.");
94 return false;
95 } else {
96 System.out.println("The PDF encryption is conform to the specified custom value.");
97 return true;
98 }
99 }
100 return true;
101 }
102
103 private boolean validatePagesSize(Document inDoc) {
104 boolean isValid = true;
105
106 if (iniMaxPageSize != null) {
107 int pageNumber = 0;
108 for (Page page : inDoc.getPages()) {
109 pageNumber++;
110 com.pdftools.toolbox.geometry.real.Size pageSize = page.getSize();
111 isValid &= validatePageSize(pageNumber, pageSize);
112 }
113 }
114
115 return isValid;
116 }
117
118 private boolean validatePageSize(int pageNumber, com.pdftools.toolbox.geometry.real.Size pageSize) {
119 if (iniMaxPageSize != null) {
120 PageSizeValidator validator = new PageSizeValidator(iniMaxPageSize, sizeTolerance);
121 if (validator.validatePageSize(pageSize.getWidth(), pageSize.getHeight())) {
122 System.out.println(String.format("The size of page %d is within the specified custom maximum page size value.", pageNumber));
123 return true;
124 } else {
125 System.out.println(String.format("The size of page %d exceeds the specified custom maximum page size value.", pageNumber));
126 return false;
127 }
128 }
129
130 return true;
131 }
132
133 public boolean validateFonts(Document inDoc) throws CorruptException, IOException {
134 boolean isValid = true;
135
136 if (iniEmbedding != null)
137 {
138 boolean embeddingRequired = "true".equalsIgnoreCase(iniEmbedding);
139 int pageNumber = 0;
140
141 for (Page page : inDoc.getPages()) {
142 pageNumber++;
143 ContentExtractor extractor = new ContentExtractor(page.getContent());
144 extractor.setUngrouping(UngroupingSelection.ALL);
145
146 for (ContentElement element : extractor) {
147 if (element instanceof TextElement) {
148 TextElement textElement = (TextElement) element;
149 Text text = textElement.getText();
150
151 for (int iFragment = 0; iFragment < text.size(); iFragment++) {
152 TextFragment currFragment = text.get(iFragment);
153 String fontName = currFragment.getFont().getBaseFont();
154 boolean isEmbedded = currFragment.getFont().getIsEmbedded();
155
156 // Check if the font is in the exception list
157 boolean isCurrentFontAnException = embeddingExceptionFonts.stream()
158 .anyMatch(exception -> Pattern.compile(exception.replace("*", ".*"), Pattern.CASE_INSENSITIVE).matcher(fontName).matches());
159
160 // Validate based on the embedding setting
161 // _iniEmbedding = true => The font has to be embedded or it should appear in the exception list
162 // _iniEmbedding = false => The font cannot be embedded or it should appear in the exception list
163 if ((embeddingRequired && !isEmbedded && !isCurrentFontAnException) || (!embeddingRequired && isEmbedded && !isCurrentFontAnException)) {
164 isValid = false;
165 String statusText = embeddingRequired ? "be embedded" : "not be embedded";
166 System.out.println("The font '" + fontName + "' on page " + pageNumber + " should " + statusText + " as specified by the property 'Embedding' or it should be added to the list of exceptions.");
167 }
168 else {
169 String statusText = embeddingRequired != isEmbedded ? "in the exception list" : isEmbedded ? "embedded" : "not embedded";
170 System.out.println("The font '" + fontName + "' on page " + pageNumber + " is conform to the 'Embedding' property as it is " + statusText + ".");
171 }
172 }
173 }
174 }
175 }
176 }
177
178 return isValid;
179 }
180 }
1public static class ConformanceValidator {
2 private static final Map<String, Conformance> versionMap = new HashMap<>();
3
4 static {
5 versionMap.put("1.0", Conformance.PDF10);
6 versionMap.put("1.1", Conformance.PDF11);
7 versionMap.put("1.2", Conformance.PDF12);
8 versionMap.put("1.3", Conformance.PDF13);
9 versionMap.put("1.4", Conformance.PDF14);
10 versionMap.put("1.5", Conformance.PDF15);
11 versionMap.put("1.6", Conformance.PDF16);
12 versionMap.put("1.7", Conformance.PDF17);
13 versionMap.put("2.0", Conformance.PDF20);
14 }
15
16 public static Conformance parseVersionString(String version) {
17 // Extract the major and minor version numbers (e.g., "1.7")
18 String[] versionParts = version.split("\\.");
19 if (versionParts.length == 2) {
20 String majorMinorVersion = versionParts[0] + "." + versionParts[1];
21 Conformance conformance = versionMap.get(majorMinorVersion);
22 if (conformance != null) {
23 return conformance;
24 }
25 }
26
27 throw new IllegalArgumentException("Unsupported version or conformance level: " + version);
28 }
29
30 public static boolean validateConformance(String maxPdfVersionStr, Conformance currentConformance) {
31 Conformance maxPdfConformance = parseVersionString(maxPdfVersionStr);
32 // Convert the current conformance level to the corresponding PDF version (Major.Minor) as it can be based on the PDF/A version
33 Conformance currentConformanceVersion = getVersionFromConformance(currentConformance);
34
35 return currentConformanceVersion.ordinal() <= maxPdfConformance.ordinal();
36 }
37
38 public static Conformance getVersionFromConformance(Conformance conformance) {
39 if (versionMap.containsValue(conformance)) {
40 return conformance;
41 }
42
43 switch (conformance) {
44 case PDF_A1_A:
45 case PDF_A1_B:
46 return Conformance.PDF14; // PDF/A-1 is based on PDF 1.4
47
48 case PDF_A2_A:
49 case PDF_A2_B:
50 case PDF_A2_U:
51 case PDF_A3_A:
52 case PDF_A3_B:
53 case PDF_A3_U:
54 return Conformance.PDF17; // PDF/A-2 and PDF/A-3 are based on PDF 1.7
55
56 default:
57 throw new IllegalArgumentException("Unsupported conformance level: " + conformance);
58 }
59 }
60}
1public static class PageSizeValidator {
2 private final double maxWidth;
3 private final double maxHeight;
4 private final double sizeTolerance;
5
6 // Named page sizes like "Letter", "A4", etc.
7 private static final Map<String, double[]> NAMED_PAGE_SIZES = new HashMap<>();
8
9 static {
10 NAMED_PAGE_SIZES.put("Letter", new double[]{612, 792}); // 8.5 x 11 inches in points
11 NAMED_PAGE_SIZES.put("A0", new double[]{2384, 3370});
12 NAMED_PAGE_SIZES.put("A1", new double[]{1684, 2384});
13 NAMED_PAGE_SIZES.put("A2", new double[]{1191, 1684});
14 NAMED_PAGE_SIZES.put("A3", new double[]{842, 1191});
15 NAMED_PAGE_SIZES.put("A4", new double[]{595, 842}); // 210 x 297 mm in points
16 NAMED_PAGE_SIZES.put("A5", new double[]{420, 595});
17 NAMED_PAGE_SIZES.put("A6", new double[]{298, 420});
18 NAMED_PAGE_SIZES.put("A7", new double[]{210, 298});
19 NAMED_PAGE_SIZES.put("A8", new double[]{147, 210});
20 NAMED_PAGE_SIZES.put("A9", new double[]{105, 147});
21 NAMED_PAGE_SIZES.put("A10", new double[]{74, 105});
22 NAMED_PAGE_SIZES.put("DL", new double[]{283, 595}); // 99 x 210 mm in points
23 }
24
25 public PageSizeValidator(String maxPageSize, String sizeToleranceStr) {
26 double[] size = parsePageSize(maxPageSize);
27 this.maxWidth = size[0];
28 this.maxHeight = size[1];
29 this.sizeTolerance = parseSizeTolerance(sizeToleranceStr);
30 }
31
32 private double[] parsePageSize(String maxPageSize) {
33 if (maxPageSize == null || maxPageSize.isEmpty()) {
34 throw new IllegalArgumentException("MaxPageSize cannot be null or empty");
35 }
36
37 // First, check if it's a named size
38 if (NAMED_PAGE_SIZES.containsKey(maxPageSize)) {
39 return NAMED_PAGE_SIZES.get(maxPageSize);
40 }
41
42 // If not a named size, try to parse it as a custom size
43 Pattern pattern = Pattern.compile("(\\d+(\\.\\d+)?)\\s*x\\s*(\\d+(\\.\\d+)?)(\\s*(pt|in|cm|mm))?", Pattern.CASE_INSENSITIVE);
44 Matcher matcher = pattern.matcher(maxPageSize);
45 if (!matcher.matches()) {
46 throw new IllegalArgumentException("Invalid MaxPageSize format: " + maxPageSize);
47 }
48
49 double width = Double.parseDouble(matcher.group(1));
50 double height = Double.parseDouble(matcher.group(3));
51 String unit = matcher.group(6).toLowerCase();
52
53 switch (unit) {
54 case "in":
55 return new double[]{width * 72, height * 72};
56 case "cm":
57 return new double[]{width * 28.3465, height * 28.3465};
58 case "mm":
59 return new double[]{width * 2.83465, height * 2.83465};
60 case "pt":
61 default:
62 return new double[]{width, height};
63 }
64 }
65
66 private double parseSizeTolerance(String sizeToleranceStr) {
67 if (sizeToleranceStr == null || sizeToleranceStr.isEmpty()) {
68 return 3; // Default tolerance in points
69 }
70
71 Pattern pattern = Pattern.compile("(\\d+(\\.\\d+)?)\\s*(%)?", Pattern.CASE_INSENSITIVE);
72 Matcher matcher = pattern.matcher(sizeToleranceStr);
73 if (!matcher.matches()) {
74 throw new IllegalArgumentException("Invalid SizeTolerance format: " + sizeToleranceStr);
75 }
76
77 double value = Double.parseDouble(matcher.group(1));
78 return matcher.group(3) != null ? value / 100.0 : value; // Percentage tolerance or direct value
79 }
80
81 public boolean validatePageSize(double actualWidth, double actualHeight) {
82 // Check both portrait and landscape orientations
83 boolean isValid = (actualWidth <= maxWidth + sizeTolerance && actualHeight <= maxHeight + sizeTolerance) ||
84 (actualHeight <= maxWidth + sizeTolerance && actualWidth <= maxHeight + sizeTolerance);
85
86 return isValid;
87 }
88}
1class IniFile:
2 def get_value(self, section: str, key: str, default_value: str = None) -> str:
3 return self.config.get(section, key, fallback=default_value)
4
5 def get_keys_matching_pattern(self, section: str, pattern: str) -> list:
6 matching_keys = []
7 if section in self.config:
8 for key in self.config[section]:
9 if re.match(pattern, key, re.IGNORECASE):
10 matching_keys.append(self.config[section][key])
11 return matching_keys
1def open_ini_file(path: str) -> IniFile:
2 ini_file = IniFile()
3
4 ini_file.config = configparser.ConfigParser()
5 ini_file.config.read(path)
6
7 return ini_file
1class DocumentValidator:
2 def validate_document(self) -> bool:
3 is_valid = self.validate_file_size()
4
5 try:
6 with open(self.input_path, "rb") as in_stream:
7 with Document.open(in_stream, self.pdf_password) as in_doc:
8 is_valid &= self.validate_conformance(in_doc.conformance)
9 is_valid &= self.validate_encryption(in_doc.permissions)
10 is_valid &= self.validate_pages_size(in_doc)
11 is_valid &= self.validate_fonts(in_doc)
12 except PasswordError as e:
13 print(f"The document could not be validated. Error: {e}")
14 return False
15
16 return is_valid
17
18 def validate_file_size(self) -> bool:
19 file_size_in_mb = os.path.getsize(self.input_path) / (1024 * 1024)
20
21 if self.ini_file_size:
22 ini_file_size_in_mb = float(self.ini_file_size)
23 if file_size_in_mb > ini_file_size_in_mb:
24 print("The PDF file size exceeds the specified custom limit.")
25 return False
26 else:
27 print("The PDF file size does not exceed the specified custom limit.")
28 return True
29 return True
30
31 def validate_conformance(self, current_conformance: Conformance) -> bool:
32 if self.ini_max_pdf_version_str:
33 if ConformanceValidator.validate_conformance(self.ini_max_pdf_version_str, current_conformance):
34 print("The PDF version does not exceed the specified custom maximum version.")
35 return True
36 else:
37 print("The PDF version exceeds the specified custom maximum version.")
38 return False
39 return True
40
41 def validate_encryption(self, permissions: Permission) -> bool:
42 if self.ini_encryption:
43 encryption_required = self.ini_encryption.lower() == "true"
44 if encryption_required and not permissions:
45 print("Encryption not conform: the PDF file is not encrypted. The custom encryption value specifies that the PDF file should be encrypted.")
46 return False
47 elif not encryption_required and permissions:
48 print("Encryption not conform: the PDF file is encrypted. The custom encryption value specifies that the PDF file should not be encrypted.")
49 return False
50 else:
51 print("The PDF encryption is conform to the specified custom value.")
52 return True
53 return True
54
55 def validate_pages_size(self, in_doc: Document) -> bool:
56 is_valid = True
57
58 if self.ini_max_page_size is not None:
59 page_number = 0
60 for page in in_doc.pages:
61 page_number += 1
62 size_with_int = Size(
63 width=int(page.size.width), height=int(page.size.height)
64 )
65 is_valid &= self.validate_page_size(page_number, size_with_int)
66
67 return is_valid
68
69
70 def validate_page_size(self, page_number: int, page_size: Size) -> bool:
71 if self.ini_max_page_size is not None:
72 validator = create_page_size_validator(self.ini_max_page_size, self.size_tolerance)
73 if validator.validate_page_size(page_size):
74 print(
75 f"The size of page {page_number} is within the specified custom maximum page size value."
76 )
77 return True
78 else:
79 print(
80 f"The size of page {page_number} exceeds the specified custom maximum page size value."
81 )
82 return False
83
84 return True
85
86 def validate_fonts(self, in_doc: Document) -> bool:
87 is_valid = True
88
89 if self.ini_embedding:
90 embedding_required = self.ini_embedding.lower() == "true"
91
92 for page_number in range(len(in_doc.pages)):
93 page_number += 1
94 page = in_doc.pages[page_number-1]
95
96 extractor = ContentExtractor(page.content)
97 extractor.ungrouping = UngroupingSelection.ALL
98
99 for element in extractor:
100 if isinstance(element, TextElement):
101 for fragment in element.text:
102 font_name = fragment.font.base_font
103 is_embedded = fragment.font.is_embedded
104
105 # Check if the font is in the exception list
106 is_current_font_an_exception = any(
107 re.match(exc.replace("*", ".*"), font_name, re.IGNORECASE)
108 for exc in self.embedding_exception_fonts
109 )
110
111 # Validate based on the embedding setting
112 # _iniEmbedding = true => The font has to be embedded or it should appear in the exception list
113 # _iniEmbedding = false => The font cannot be embedded or it should appear in the exception list
114 if (embedding_required and not is_embedded and not is_current_font_an_exception) or (
115 not embedding_required and is_embedded and not is_current_font_an_exception
116 ):
117 is_valid = False
118 status_text = "be embedded" if embedding_required else "not be embedded"
119 print(
120 f"The font '{font_name}' on page {page_number} should {status_text} as specified by the property 'Embedding' or it should be added to the list of exceptions."
121 )
122 else:
123 status_text = (
124 "in the exception list" if embedding_required != is_embedded
125 else "embedded" if is_embedded
126 else "not be embedded"
127 )
128 print(
129 f"The font '{font_name}' on page {page_number} is conform to the 'Embedding' property as it is {status_text}."
130 )
131 return is_valid
1def create_document_validator(ini_file: IniFile, input_path: str, pdf_password: str = None) -> DocumentValidator:
2 document_validator = DocumentValidator()
3
4 document_validator.ini_file = ini_file
5 document_validator.input_path = input_path
6 document_validator.pdf_password = pdf_password
7
8 # Extract values from INI file
9 # Tolerance used for size comparison: default 3pt
10 document_validator.size_tolerance = ini_file.get_value("Pages", "SizeTolerance", "3.0")
11 document_validator.ini_max_page_size = ini_file.get_value("Pages", "MaxPageSize")
12 document_validator.ini_max_pdf_version_str = ini_file.get_value("File", "MaxPdfVersion")
13 document_validator.ini_encryption = ini_file.get_value("File", "Encryption")
14 document_validator.ini_file_size = ini_file.get_value("File", "FileSize")
15 document_validator.ini_embedding = ini_file.get_value("Fonts", "Embedding")
16 document_validator.embedding_exception_fonts = ini_file.get_keys_matching_pattern("Fonts", r"EmbeddingExcFont\d+")
17
18 return document_validator
1class PageSizeValidator:
2 named_page_sizes = {
3 "Letter": Size(width=612, height=792), # 8.5 x 11 inches in points
4 "A0": Size(width=2384, height=3370),
5 "A1": Size(width=1684, height=2384),
6 "A2": Size(width=1191, height=1684),
7 "A3": Size(width=842, height=1191),
8 "A4": Size(width=595, height=842), # 210 x 297 mm in points
9 "A5": Size(width=420, height=595),
10 "A6": Size(width=298, height=420),
11 "A7": Size(width=210, height=298),
12 "A8": Size(width=147, height=210),
13 "A9": Size(width=105, height=147),
14 "A10": Size(width=74, height=105),
15 "DL": Size(width=283, height=595), # 99 x 210 mm in points
16 }
17
18 def parse_page_size(self, max_page_size: str) -> Size:
19 # First, check if it's a named size
20 named_size = self.named_page_sizes.get(max_page_size)
21 if named_size:
22 return named_size
23
24 # If not a named size, try to parse it as a custom size
25 match = re.match(
26 r"(\d+(\.\d+)?)\s*x\s*(\d+(\.\d+)?)(\s*(pt|in|cm|mm))?", max_page_size, re.IGNORECASE
27 )
28 if not match:
29 raise ValueError(f"Invalid MaxPageSize format: {max_page_size}")
30
31 width = float(match.group(1))
32 height = float(match.group(3))
33 unit = match.group(6).lower() if match.group(6) else "pt"
34
35 if unit == "in":
36 return Size(width=int(width * 72), height=int(height * 72))
37 elif unit == "cm":
38 return Size(width=int(width * 28.3465), height=int(height * 28.3465))
39 elif unit == "mm":
40 return Size(width=int(width * 2.83465), height=int(height * 2.83465))
41 elif unit in ["pt", ""]:
42 return Size(width=int(width), height=int(height))
43 else:
44 raise ValueError(f"Unsupported unit: {unit}")
45
46 def parse_size_tolerance(self, size_tolerance_str: str) -> float:
47 if not size_tolerance_str:
48 return 3.0 # Default tolerance in points
49
50 match = re.match(r"(\d+(\.\d+)?)\s*(%)?", size_tolerance_str, re.IGNORECASE)
51 if not match:
52 raise ValueError(f"Invalid SizeTolerance format: {size_tolerance_str}")
53
54 value = float(match.group(1)) # Extract the numeric value
55 return value / 100.0 if match.group(3) else value # Percentage tolerance or direct value
56
57 def validate_page_size(self, page_size: Size) -> bool:
58 is_valid = (
59 (page_size.width <= self.max_size.width + self.size_tolerance
60 and page_size.height <= self.max_size.height + self.size_tolerance
61 ) or
62 (page_size.height <= self.max_size.width + self.size_tolerance
63 and page_size.width <= self.max_size.height + self.size_tolerance)
64 )
65 return is_valid
1def create_page_size_validator(max_page_size_str: str, size_tolerance_str: str) -> PageSizeValidator:
2 page_size_validator = PageSizeValidator()
3
4 page_size_validator.max_size = page_size_validator.parse_page_size(max_page_size_str)
5 page_size_validator.size_tolerance = page_size_validator.parse_size_tolerance(size_tolerance_str)
6
7 return page_size_validator
1class ConformanceValidator:
2 version_map = {
3 "1.0": Conformance.PDF10,
4 "1.1": Conformance.PDF11,
5 "1.2": Conformance.PDF12,
6 "1.3": Conformance.PDF13,
7 "1.4": Conformance.PDF14,
8 "1.5": Conformance.PDF15,
9 "1.6": Conformance.PDF16,
10 "1.7": Conformance.PDF17,
11 "2.0": Conformance.PDF20,
12 }
13
14 @staticmethod
15 def parse_version_string(version: str) -> Conformance:
16 # Split the version string into major and minor parts
17 version_parts = version.split(".")
18
19 # Ensure there are exactly two parts
20 if len(version_parts) == 2:
21 major_minor_version = f"{version_parts[0]}.{version_parts[1]}"
22
23 # Retrieve the corresponding Conformance value
24 conformance = ConformanceValidator.version_map.get(major_minor_version)
25 if conformance:
26 return conformance
27
28 # Raise an exception if the version is not supported
29 raise ValueError(f"Unsupported version or conformance level: {version}")
30
31 @staticmethod
32 def validate_conformance(max_pdf_version_str: str, current_conformance: Conformance) -> bool:
33 # Parse the maximum PDF version string into a Conformance enum
34 max_pdf_conformance = ConformanceValidator.parse_version_string(max_pdf_version_str)
35
36 # Convert current conformance level to a major.minor version
37 current_conformance_version = ConformanceValidator.get_version_from_conformance(current_conformance)
38
39 # Compare the integer values of the two Conformance enums
40 return current_conformance_version.value <= max_pdf_conformance.value
41
42
43 @staticmethod
44 def get_version_from_conformance(conformance: Conformance) -> Conformance:
45 # Return the exact match if available in the version_map values
46 if conformance in ConformanceValidator.version_map.values():
47 return conformance
48
49 # Map PDF/A conformance levels to their base PDF versions
50 if conformance in {Conformance.PDF_A1_A, Conformance.PDF_A1_B}:
51 return Conformance.PDF14 # PDF/A-1 is based on PDF 1.4
52
53 if conformance in {
54 Conformance.PDF_A2_A,
55 Conformance.PDF_A2_B,
56 Conformance.PDF_A2_U,
57 Conformance.PDF_A3_A,
58 Conformance.PDF_A3_B,
59 Conformance.PDF_A3_U,
60 }:
61 return Conformance.PDF17 # PDF/A-2 and PDF/A-3 are based on PDF 1.7
62
63 # Raise an exception for unsupported conformance levels
64 raise ValueError(f"Unsupported conformance level: {conformance}")
Document Setup
Add metadata to PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Copy all pages
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
33 Ptx_GetLastError());
34
35// Add copied pages to output
36pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
38 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
41 _T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43
44if (argc == 4)
45{
46 // Add metadata from a input file
47 pMdataStream = _tfopen(szMdatafile, _T("rb"));
48 GOTO_CLEANUP_IF_NULL(pMdataStream, _T("Failed to open metadata file \"%s\".\n"), szMdatafile);
49 PtxSysCreateFILEStreamDescriptor(&mdataDescriptor, pMdataStream, 0);
50
51 // Get file extension
52 TCHAR* szExt = _tcsrchr(szMdatafile, '.');
53 _tcscpy(szExtension, szExt);
54
55 if (_tcscmp(szExtension, _T(".pdf")) == 0)
56 {
57 // Use the metadata of another PDF file
58 TPtxPdf_Document* pMetaDoc = PtxPdf_Document_Open(&mdataDescriptor, _T(""));
59 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetaDoc, _T("Failed to open metadata file. %s (ErrorCode: 0x%08x).\n"),
60 szErrorBuff, Ptx_GetLastError());
61 TPtxPdf_Metadata* pMetadata = PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pMetaDoc));
62 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)."),
63 szErrorBuff, Ptx_GetLastError());
64 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pMetadata),
65 _T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
66 Ptx_GetLastError());
67 }
68 else
69 {
70 // Use the content of an XMP metadata file
71 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
72 PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Create(pOutDoc, &mdataDescriptor)),
73 _T("Failed to set metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
74 }
75}
76else
77{
78 // Set some metadata properties
79 TPtxPdf_Metadata* pMetadata = PtxPdf_Document_GetMetadata(pOutDoc);
80 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to get metadata. %s (ErrorCode: 0x%08x).\n"),
81 szErrorBuff, Ptx_GetLastError());
82 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetAuthor(pMetadata, _T("Your Author")),
83 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
84 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetTitle(pMetadata, _T("Your Title")),
85 _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
86 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetSubject(pMetadata, _T("Your Subject")),
87 _T("%s(ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
88 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Metadata_SetCreator(pMetadata, _T("Your Creator")),
89 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
90}
91
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 // Copy document-wide data (excluding metadata)
4
5 TPtxPdf_FileReferenceList* pInFileRefList;
6 TPtxPdf_FileReferenceList* pOutFileRefList;
7
8 // Output intent
9 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
10 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
11 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
12 return FALSE;
13
14 // Viewer settings
15 if (PtxPdf_Document_SetViewerSettings(
16 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
17 return FALSE;
18
19 // Associated files (for PDF/A-3 and PDF 2.0 only)
20 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
21 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
22 if (pInFileRefList == NULL || pOutFileRefList == NULL)
23 return FALSE;
24 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
25 if (PtxPdf_FileReferenceList_Add(
26 pOutFileRefList,
27 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
28 return FALSE;
29
30 // Plain embedded files
31 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
32 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
33 if (pInFileRefList == NULL || pOutFileRefList == NULL)
34 return FALSE;
35 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
36 if (PtxPdf_FileReferenceList_Add(
37 pOutFileRefList,
38 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
39 return FALSE;
40
41 return TRUE;
42}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Set Metadata
13 if (args.Length == 3)
14 {
15 Metadata mdata;
16
17 // Add metadata from a input file
18 using FileStream metaStream = File.OpenRead(mdatafile);
19 if (mdatafile.EndsWith(".pdf"))
20 {
21 // Use the metadata of another PDF file
22 using Document metaDoc = Document.Open(metaStream, "");
23 mdata = Metadata.Copy(outDoc, metaDoc.Metadata);
24 }
25 else
26 {
27 // Use the content of an XMP metadata file
28 mdata = Metadata.Create(outDoc, metaStream);
29 }
30 outDoc.Metadata = mdata;
31 }
32 else
33 {
34 // Set some metadata properties
35 Metadata metadata = outDoc.Metadata;
36 metadata.Author = "Your Author";
37 metadata.Title = "Your Title";
38 metadata.Subject = "Your Subject";
39 metadata.Creator = "Your Creator";
40 }
41
42 // Define page copy options
43 PageCopyOptions copyOptions = new PageCopyOptions();
44
45 // Copy all pages and append to output document
46 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
47 outDoc.Pages.AddRange(copiedPages);
48}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data (except metadata)
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Viewer settings
10 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
11
12 // Associated files (for PDF/A-3 and PDF 2.0 only)
13 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
14 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
15 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
16
17 // Plain embedded files
18 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
19 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
20 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
21}
1 try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy all pages and append to output document
15 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
16 outDoc.getPages().addAll(copiedPages);
17
18 if (args.length == 3) {
19 Metadata mdata;
20
21 // Add metadata from a input file
22 try (
23 FileStream metaStream = new FileStream(mdatafile, FileStream.Mode.READ_ONLY)) {
24
25 if (mdatafile.toLowerCase().endsWith(".pdf")) {
26 // Use the metadata of another PDF file
27 try (
28 Document metaDoc = Document.open(metaStream, null)) {
29
30 mdata = Metadata.copy(outDoc, metaDoc.getMetadata());
31 }
32 } else {
33 // Use the content of an XMP metadata file
34 mdata = Metadata.create(outDoc, metaStream);
35 }
36 }
37 outDoc.setMetadata(mdata);
38 } else {
39 // Set some metadata properties
40 Metadata metadata = outDoc.getMetadata();
41 metadata.setAuthor("Your Author");
42 metadata.setTitle("Your Title");
43 metadata.setSubject("Your Subject");
44 metadata.setCreator("Your Creator");
45 }
46 }
47 }
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data (excluding metadata)
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Viewer settings
9 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
10
11 // Associated files (for PDF/A-3 and PDF 2.0 only)
12 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
13 for (FileReference inFileRef : inDoc.getAssociatedFiles())
14 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
15
16 // Plain embedded files
17 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
18 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
19 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
20}
1
2
3# Open input document
4with io.FileIO(input_file_path, 'rb') as content_pdf_stream:
5 with Document.open(content_pdf_stream, None) as content_pdf_document:
6
7 # Create output document
8 with io.FileIO(output_file_path, 'wb+') as output_stream:
9 with Document.create(output_stream, content_pdf_document.conformance, None) as output_document:
10 # Copy document-wide data
11 copy_document_data(content_pdf_document, output_document)
12
13 # Set Metadata
14 if metadata_file_path is not None:
15 with io.FileIO(metadata_file_path, 'rb') as metadata_stream:
16 if metadata_file_path.endswith(".pdf"):
17 # Use the metadata of another PDF file
18 with Document.open(metadata_stream, "") as meta_doc:
19 mdata = Metadata.copy(output_document, meta_doc.metadata)
20 else:
21 # Use the content of an XMP metadata file
22 mdata = Metadata.create(output_document, metadata_stream)
23 else:
24 metadata = output_document.metadata
25 metadata.author = "Your Author"
26 metadata.title = "Your Title"
27 metadata.subject = "Your Subject"
28 metadata.creator = "Your Creator"
29
30 output_document.metadata = mdata
31
32 # Define page copy options
33 copy_options = PageCopyOptions()
34
35 # Copy all pages and append to output document
36 copied_pages = PageList.copy(output_document, content_pdf_document.pages, copy_options)
37 output_document.pages.extend(copied_pages)
38
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data (excluding metadata)
3
4 # Output intent
5 if content_pdf_document.output_intent is not None:
6 content_pdf_document.output_intent = IccBasedColorSpace.copy(out_doc, content_pdf_document.output_intent)
7
8 # Viewer settings
9 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
10
11 # Associated files (for PDF/A-3 and PDF 2.0 only)
12 outAssociatedFiles = out_doc.associated_files
13 for in_file_ref in in_doc.associated_files:
14 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
15
16 # Plain embedded files
17 out_embedded_files = out_doc.plain_embedded_files
18 for in_file_ref in in_doc.plain_embedded_files:
19 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Encrypt PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9pEncryption =
10 PtxPdf_Encryption_New(szUserPwd, szOwnerPwd, ePtxPdf_Permission_Print | ePtxPdf_Permission_DigitalPrint);
11
12// Create output document
13pOutStream = _tfopen(szOutPath, _T("wb+"));
14GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
15PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
16iConformance = PtxPdf_Document_GetConformance(pInDoc);
17pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, pEncryption);
18GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
19 szOutPath, szErrorBuff, Ptx_GetLastError());
20
21// Copy document-wide data
22GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
23 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
24 Ptx_GetLastError());
25
26// Configure copy options
27pCopyOptions = PtxPdf_PageCopyOptions_New();
28
29// Copy all pages
30pInPageList = PtxPdf_Document_GetPages(pInDoc);
31GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
32 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
33 szErrorBuff, Ptx_GetLastError());
34pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
35GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
36 Ptx_GetLastError());
37
38// Add copied pages to output
39pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
40GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
41 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
42 szErrorBuff, Ptx_GetLastError());
43GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
44 _T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
45 szErrorBuff, Ptx_GetLastError());
46
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Create encryption parameters
2Encryption encryptionParams = new Encryption(UserPwd, OwnerPwd, Permission.Print |
3 Permission.DigitalPrint);
4
5// Open input document
6using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
7using (Document inDoc = Document.Open(inStream, null))
8
9// Create output document and set a user and owner password
10using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
11using (Document outDoc = Document.Create(outStream, inDoc.Conformance, encryptionParams))
12{
13 // Copy document-wide data
14 CopyDocumentData(inDoc, outDoc);
15
16 // Define page copy options
17 PageCopyOptions copyOptions = new PageCopyOptions();
18
19 // Copy all pages and append to output document
20 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
21 outDoc.Pages.AddRange(copiedPages);
22}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1// Create encryption parameters
2Encryption encryptionParams = new Encryption(userPwd, ownerPwd,
3 EnumSet.of(Permission.PRINT, Permission.DIGITAL_PRINT));
4
5try (// Open input document
6 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
7 Document inDoc = Document.open(inStream, null);
8 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
9 try (// Create output document and set a user and owner password
10 Document outDoc = Document.create(outStream, inDoc.getConformance(), encryptionParams)) {
11
12 // Copy document-wide data
13 copyDocumentData(inDoc, outDoc);
14
15 // Define page copy options
16 PageCopyOptions copyOptions = new PageCopyOptions();
17
18 // Copy all pages and append to output document
19 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
20 outDoc.getPages().addAll(copiedPages);
21 }
22}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1
2
3# Open input document
4with io.FileIO(input_file_path, "rb") as in_stream:
5 with Document.open(in_stream, None) as in_doc:
6
7 # Create encryption parameters
8 encryption_params = Encryption(
9 user_pwd,
10 owner_pwd,
11 Permission.PRINT | Permission.DIGITAL_PRINT,
12 )
13
14 # Create output document and set a user and owner password
15 with io.FileIO(output_file_path, "wb+") as out_stream:
16 with Document.create(out_stream, in_doc.conformance, encryption_params) as out_doc:
17
18 # Copy document-wide data
19 copy_document_data(in_doc, out_doc)
20
21 # Define page copy options
22 copy_options = PageCopyOptions()
23
24 # Copy all pages and append to output document
25 copied_pages = PageList.copy(out_doc, in_doc.pages, copy_options)
26 out_doc.pages.extend(copied_pages)
27
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Flatten form fields in PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options: enable form field flattening
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25PtxPdf_PageCopyOptions_SetFormFields(pCopyOptions, ePtxPdfForms_FormFieldCopyStrategy_Flatten);
26
27// Copy all pages
28pInPageList = PtxPdf_Document_GetPages(pInDoc);
29GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
30 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
31 szErrorBuff, Ptx_GetLastError());
32pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
33GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
34 Ptx_GetLastError());
35
36// Add copied pages to output
37pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
38GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
39 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
40 szErrorBuff, Ptx_GetLastError());
41GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
42 _T("Failed to add copied pages to output. %s (ErrorCode: 0x%08x).\n"),
43 szErrorBuff, Ptx_GetLastError());
44
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define copy options including form field flattening
13 PageCopyOptions copyOptions = new PageCopyOptions();
14 copyOptions.FormFields = FormFieldCopyStrategy.Flatten;
15
16 // Copy all pages and append to output document
17 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
18 outDoc.Pages.AddRange(copiedPages);
19}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define copy options including form field flattening
12 PageCopyOptions copyOptions = new PageCopyOptions();
13 copyOptions.setFormFields(FormFieldCopyStrategy.FLATTEN);
14
15 // Copy all pages and append to output document
16 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
17 outDoc.getPages().addAll(copiedPages);
18 }
19}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1
2
3# Open input document
4with io.FileIO(input_file_path, "rb") as in_stream:
5 with Document.open(in_stream, None) as in_doc:
6
7 # Create output document
8 with io.FileIO(output_file_path, "wb+") as out_stream:
9 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
10
11 # Copy document-wide data
12 copy_document_data(in_doc, out_doc)
13
14 # Set form field flattening options
15 copy_options = PageCopyOptions()
16 copy_options.form_fields = FormFieldCopyStrategy.FLATTEN
17
18 # Copy all pages with flattening options
19 copied_pages = PageList.copy(out_doc, in_doc.pages, copy_options)
20 out_doc.pages.extend(copied_pages)
21
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Merge multiple PDFs and create a table of contents page
1// Create output document
2using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
3using (Document outDoc = Document.Create(outStream, null, null))
4{
5 // Create embedded font in output document
6 Font font = Font.CreateFromSystem(outDoc, "Arial", string.Empty, true);
7
8 // Define page copy options
9 PageCopyOptions pageCopyOptions = new PageCopyOptions();
10
11 var copiedPageLists = new List<Tuple<string, PageList>>(inPaths.Length);
12
13 // A page number counter
14 int pageNumber = 2;
15
16 // Copy all input documents pages
17 foreach (string inPath in inPaths)
18 {
19 // Open input document
20 using Stream inFs = new FileStream(inPath, FileMode.Open, FileAccess.Read);
21 using Document inDoc = Document.Open(inFs, null);
22
23 // Copy all pages and append to output document
24 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, pageCopyOptions);
25
26 // Add page numbers to copied pages
27 foreach (var copiedPage in copiedPages)
28 {
29 AddPageNumber(outDoc, copiedPage, font, pageNumber++);
30 }
31
32 // Create outline item
33 string title = inDoc.Metadata.Title ?? System.IO.Path.GetFileNameWithoutExtension(inPath);
34 copiedPageLists.Add(new Tuple<string, PageList>(title, copiedPages));
35 }
36
37 // Create table of contents page
38 var contentsPage = CreateTableOfContents(outDoc, copiedPageLists);
39 AddPageNumber(outDoc, contentsPage, font, 1);
40
41 // Add pages to the output document
42 PageList outPages = outDoc.Pages;
43 outPages.Add(contentsPage);
44 foreach (var tuple in copiedPageLists)
45 {
46 outPages.AddRange(tuple.Item2);
47 }
1private static void AddPageNumber(Document outDoc, Page copiedPage, Font font, int pageNumber)
2{
3 // Create content generator
4 using ContentGenerator generator = new ContentGenerator(copiedPage.Content, false);
5
6 // Create text object
7 Text text = Text.Create(outDoc);
8
9 // Create a text generator with the given font, size and position
10 using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
11 {
12 // Generate string to be stamped as page number
13 string stampText = string.Format("Page {0}", pageNumber);
14
15 // Calculate position for centering text at bottom of page
16 Point position = new Point
17 {
18 X = (copiedPage.Size.Width / 2) - (textgenerator.GetWidth(stampText) / 2),
19 Y = 10
20 };
21
22 // Position the text
23 textgenerator.MoveTo(position);
24 // Add page number
25 textgenerator.Show(stampText);
26 }
27 // Paint the positioned text
28 generator.PaintText(text);
29}
1private static Page CreateTableOfContents(Document outDoc, List<Tuple<string, PageList>> copiedPageLists)
2{
3 // Create a new page with size equal to the first page copied
4 var page = Page.Create(outDoc, copiedPageLists[0].Item2[0].Size);
5
6 // Create a font
7 var font = Font.CreateFromSystem(outDoc, "Arial", null, true);
8
9 // Parameters for layout computation
10 double border = 30;
11 double textWidth = page.Size.Width - 2 * border;
12 double chapterTitleSize = 24;
13 double titleSize = 12;
14
15 // The current text location
16 var location = new Point() { X = border, Y = page.Size.Height - border - chapterTitleSize };
17
18 // The page number of the current item in the table of content
19 int pageNumber = 2;
20
21 // Create a content generator for the table of contents page
22 using (var contentGenerator = new ContentGenerator(page.Content, false))
23 {
24 // Create a text object
25 var text = Text.Create(outDoc);
26
27 // Create a text generator to generate the table of contents. Initially, use the chapter title font size
28 using (var textGenerator = new TextGenerator(text, font, chapterTitleSize, location))
29 {
30 // Show a chapter title
31 textGenerator.ShowLine("Table of Contents");
32
33 // Advance the vertical position
34 location.Y -= 1.7 * chapterTitleSize;
35
36 // Select the font size for an entry in the table of contents
37 textGenerator.FontSize = titleSize;
38
39 // Iterate over all copied page ranges
40 foreach (var tuple in copiedPageLists)
41 {
42 // The title string for the current entry
43 string title = tuple.Item1;
44
45 // The page number string of the target page for this entry
46 string pageNumberString = string.Format("{0}", pageNumber);
47
48 // The width of the page number string
49 double pageNumberWidth = textGenerator.GetWidth(pageNumberString);
50
51 // Compute the number of filler dots to be displayed between the entry title and the page number
52 int numberOfDots = (int)Math.Floor((textWidth - textGenerator.GetWidth(title) - pageNumberWidth) / textGenerator.GetWidth("."));
53
54 // Move to the current location and show the entry's title and the filler dots
55 textGenerator.MoveTo(location);
56 textGenerator.Show(title + new string('.', numberOfDots));
57
58 // Show the page number
59 textGenerator.MoveTo(new Point() { X = page.Size.Width - border - pageNumberWidth, Y = location.Y });
60 textGenerator.Show(pageNumberString);
61
62 // Compute the rectangle for the link
63 var linkRectangle = new Rectangle()
64 {
65 Left = border,
66 Bottom = location.Y + font.Descent * titleSize,
67 Right = border + textWidth,
68 Top = location.Y + font.Ascent * titleSize
69 };
70
71 // Create a destination to the first page of the current page range and create a link for this destination
72 var pageList = tuple.Item2;
73 var targetPage = pageList[0];
74 var destination = LocationZoomDestination.Create(outDoc, targetPage, 0, targetPage.Size.Height, null);
75 var link = InternalLink.Create(outDoc, linkRectangle, destination);
76
77 // Add the link to the table of contents page
78 page.Links.Add(link);
79
80 // Advance the location for the next entry
81 location.Y -= 1.8 * titleSize;
82 pageNumber += pageList.Count;
83 }
84 }
85
86 // Paint the generated text
87 contentGenerator.PaintText(text);
88 }
89
90 // Return the finished table-of-contents page
91 return page;
92}
1try (
2 // Open input document
3 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
4 try (// Create output document
5 Document outDoc = Document.create(outStream, null, null)) {
6
7 // Create embedded font in output document
8 Font font = Font.createFromSystem(outDoc, "Arial", "", true);
9
10 // Configure page copy options
11 PageCopyOptions copyOptions = new PageCopyOptions();
12
13 Set<Map.Entry<String, PageList>> copiedPageLists = new HashSet<>(inPaths.length);
14
15 // A page number counter
16 int pageNumber = 2;
17
18
19 // Copy all input documents pages
20 for (String inPath : inPaths) {
21 try (// Open input document
22 Stream inFs = new FileStream(inPath, FileStream.Mode.READ_ONLY);
23 Document inDoc = Document.open(inFs, null)) {
24
25 // Copy all pages and append to output document
26 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
27
28 // Add page numbers to copied pages
29 for ( Page copiedPage : copiedPages)
30 {
31 addPageNumber(outDoc, copiedPage, font, pageNumber++);
32 }
33
34 // Hold the file name without extension
35 if (inPath == null)
36 continue;
37 // Get position of last '.'.
38 int pos = inPath.lastIndexOf(".");
39 // If there was a '.', hold the file name only
40 if (pos != -1)
41 inPath = inPath.substring(0, pos);
42
43 // Create outline item
44 String title = (inDoc.getMetadata().getTitle() == null ? inPath : inDoc.getMetadata().getTitle());
45 copiedPageLists.add(new AbstractMap.SimpleEntry<String, PageList>(title, copiedPages));
46 }
47 }
48
49 // Create table of contents page
50 Page contentsPage = createTableOfContents(outDoc, copiedPageLists);
51 addPageNumber(outDoc, contentsPage, font, 1);
52
53 // Add pages to the output document
54 PageList outPages = outDoc.getPages();
55 outPages.add(contentsPage);
56 for (Map.Entry<String, PageList> entry : copiedPageLists)
57 {
58 outPages.addAll(entry.getValue());
59 }
1private static void addPageNumber(Document outDoc, Page copiedPage, Font font, int pageNumber) throws ToolboxException, IOException
2{
3 // Create content generator
4 try (ContentGenerator generator = new ContentGenerator(copiedPage.getContent(), false)) {
5 // Create text object
6 Text text = Text.create(outDoc);
7
8 // Create a text generator with the given font, size and position
9 try (TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
10 // Generate string to be stamped as page number
11 String stampText = String.format("Page %d", pageNumber);
12
13 // Calculate position for centering text at bottom of page
14 Point position = new Point();
15 position.x = (copiedPage.getSize().getWidth() / 2) - (textgenerator.getWidth(stampText) / 2);
16 position.y = 10;
17
18 // Position the text
19 textgenerator.moveTo(position);
20 // Add page number
21 textgenerator.show(stampText);
22 }
23
24 // Paint the positioned text
25 generator.paintText(text);
26 }
27}
1private static Page createTableOfContents(Document outDoc, Set<Map.Entry<String, PageList>> copiedPageLists) throws IOException, ToolboxException
2{
3 // Create a new page with size equal to the first page copied
4 Page page = Page.create(outDoc, copiedPageLists.iterator().next().getValue().get(0).getSize());
5
6 // Create a font
7 Font font = Font.createFromSystem(outDoc, "Arial", null, true);
8
9 // Parameters for layout computation
10 double border = 30;
11 double textWidth = page.getSize().getWidth() - 2 * border;
12 double chapterTitleSize = 24;
13 double titleSize = 12;
14
15 // The current text location
16 Point location = new Point();
17 location.x = border;
18 location.y = page.getSize().getHeight() - border - chapterTitleSize;
19
20 // The page number of the current item in the table of content
21 int pageNumber = 2;
22
23 // Creat a content generator for the table of contents page
24 try (ContentGenerator contentGenerator = new ContentGenerator(page.getContent(), false)) {
25 // Create a text object
26 Text text = Text.create(outDoc);
27
28 // Create a text generator to generate the table of contents. Initially, use the chapter title font size
29 try (TextGenerator textGenerator = new TextGenerator(text, font, chapterTitleSize, location)) {
30 // Show a chapter title
31 textGenerator.showLine("Table of Contents");
32
33 // Advance the vertical position
34 location.y -= 1.7 * chapterTitleSize;
35
36 // Select the font size for an entry in the table of contents
37 textGenerator.setFontSize(titleSize);
38
39 // Iterate over all copied page ranges
40 for (Map.Entry<String, PageList> entry : copiedPageLists)
41 {
42 // The title string for the current entry
43 String title = entry.getKey();
44
45 // The page number string of the target page for this entry
46 String pageNumberString = String.format("%d", pageNumber);
47
48 // The width of the page number string
49 double pageNumberWidth = textGenerator.getWidth(pageNumberString);
50
51 // Compute the number of filler dots to be displayed between the entry title and the page number
52 int numberOfDots = (int)Math.floor((textWidth - textGenerator.getWidth(title) - pageNumberWidth) / textGenerator.getWidth("."));
53
54 // Move to the current location and show the entry's title and the filler dots
55 textGenerator.moveTo(location);
56 String dots = new String();
57 for (int i = 0; i < numberOfDots; i++)
58 {
59 dots += '.';
60 }
61 textGenerator.show(title + dots);
62
63 // Show the page number
64 Point point = new Point();
65 point.x = page.getSize().getWidth() - border - pageNumberWidth;
66 point.y = location.y;
67 textGenerator.moveTo(point);
68 textGenerator.show(pageNumberString);
69
70 // Compute the rectangle for the link
71 Rectangle linkRectangle = new Rectangle();
72 linkRectangle.setLeft(border);
73 linkRectangle.setBottom(location.y + font.getDescent() * titleSize);
74 linkRectangle.setRight(border + textWidth);
75 linkRectangle.setTop(location.y + font.getAscent() * titleSize);
76
77 // Create a destination to the first page of the current page range and create a link for this destination
78 PageList pageList = entry.getValue();
79 Page targetPage = pageList.get(0);
80 LocationZoomDestination destination = LocationZoomDestination.create(outDoc, targetPage, (double) 0, targetPage.getSize().getHeight(), null);
81 InternalLink link = InternalLink.create(outDoc, linkRectangle, destination);
82
83 // Add the link to the table of contents page
84 page.getLinks().add(link);
85
86 // Advance the location for the next entry
87 location.y -= 1.8 * titleSize;
88 pageNumber += pageList.size();
89 }
90 }
91
92 // Paint the generated text
93 contentGenerator.paintText(text);
94 }
95
96 // Return the finished table-of-contents page
97 return page;
98}
1def add_page_number(out_doc: Document, page: Page, font: Font, page_number: int):
2 """Add a page number to the bottom center of a page."""
3 # Create content generator
4 with ContentGenerator(page.content, False) as generator:
5
6 # Create text object
7 text = Text.create(out_doc)
8
9 # Create a text generator with the given font, size and position
10 with TextGenerator(text, font, 8, None) as text_generator:
11 # Generate string to be stamped as page number
12 stamp_text = f"Page {page_number}"
13
14 # Calculate position for centering text at bottom of page
15 position = Point(
16 x=(page.size.width / 2) - (text_generator.get_width(stamp_text) / 2),
17 y=10,
18 )
19
20 # Position the text
21 text_generator.move_to(position)
22 # Add page number
23 text_generator.show(stamp_text)
24
25 # Paint the positioned text
26 generator.paint_text(text)
1def create_table_of_contents(out_doc:Document, toc_entries: tuple, font: Font):
2 """Create a table of contents (TOC) page."""
3 # Create a new page with size equal to the first page copied
4 page = Page.create(out_doc, toc_entries[0][1][0].size)
5
6 # Parameters for layout computation
7 border = 30
8 text_width = page.size.width - 2 * border
9 chapter_title_size = 24
10 title_size = 12
11
12 # The current text location
13 location = Point(x=border, y=page.size.height - border - chapter_title_size)
14
15 # The page number of the current item in the table of content
16 page_number = 2
17
18 # Create a content generator for the table of contents page
19 with ContentGenerator(page.content, False) as content_generator:
20 # Create a text object
21 text = Text.create(out_doc)
22
23 # Create a text generator to generate the table of contents. Initially, use the chapter title font size
24 with TextGenerator(text, font, chapter_title_size, location) as text_gen:
25 # Show a chapter title
26 text_gen.show_line("Table of Contents")
27
28 # Advance the vertical position
29 location.y -= 1.7 * chapter_title_size
30
31 # Select the font size for an entry in the table of contents
32 text_gen.font_size = title_size
33
34 # Iterate over all copied page ranges
35 for title, page_list in toc_entries:
36 # The title string for the current entry
37 title_text = title
38
39 # The page number string of the target page for this entry
40 page_number_text = f"{page_number}"
41
42 # The width of the page number string
43 page_number_width = text_gen.get_width(page_number_text)
44
45 # Compute the number of filler dots to be displayed between the entry title and the page number
46 filler_dots_count = int(
47 (text_width - text_gen.get_width(title_text) - page_number_width)
48 / text_gen.get_width(".")
49 )
50
51 # Move to the current location and show the entry's title and the filler dots
52 text_gen.move_to(location)
53 text_gen.show(title_text + "." * filler_dots_count)
54
55 # Show the page number
56 text_gen.move_to(Point(x=page.size.width - border - page_number_width, y=location.y))
57 text_gen.show(page_number_text)
58
59 # Compute the rectangle for the link
60 link_rectangle = Rectangle(
61 left=border,
62 bottom=location.y + font.descent * title_size,
63 right=border + text_width,
64 top=location.y + font.ascent * title_size,
65 )
66
67 # Create a destination to the first page of the current page range and create a link for this destination
68 target_page = page_list[0]
69 destination = LocationZoomDestination.create(out_doc, target_page, 0, target_page.size.height, None)
70 link = InternalLink.create(out_doc, link_rectangle, destination)
71
72 # Add the link to the table of contents page
73 page.links.append(link)
74
75 # Advance the location for the next entry
76 location.y -= 1.8 * title_size
77 page_number += len(page_list)
78
79 # Paint the generated text
80 content_generator.paint_text(text)
81
82 return page
Merge multiple PDFs
1// Create output document
2pOutStream = _tfopen(szOutPath, _T("wb+"));
3GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
4PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
5pOutDoc = PtxPdf_Document_Create(&outDescriptor, NULL, NULL);
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
7 szOutPath, szErrorBuff, Ptx_GetLastError());
8
9// Configure copy options
10pCopyOptions = PtxPdf_PageCopyOptions_New();
11
12// Get output page list
13pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
14GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
15 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
16 szErrorBuff, Ptx_GetLastError());
17
18// Merge input documents
19for (int i = 1; i < argc - 1; i++)
20{
21 // Open input document
22 pInStream = _tfopen(szInPath[i], _T("rb"));
23 GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath[i]);
24 PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
25 pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
26 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
27 szInPath[i], szErrorBuff, Ptx_GetLastError());
28
29 // Configure copy options
30 pCopyOptions = PtxPdf_PageCopyOptions_New();
31
32 // Copy all pages
33 pInPageList = PtxPdf_Document_GetPages(pInDoc);
34 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
35 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
36 szErrorBuff, Ptx_GetLastError());
37 pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
38 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"),
39 szErrorBuff, Ptx_GetLastError());
40
41 // Append copied pages
42 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
43 _T("Failed to add page range. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
44 Ptx_GetLastError());
45
46 Ptx_Release(pInPageList);
47 pInPageList = NULL;
48 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_Close(pInDoc),
49 _T("Failed to close input document. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
50 Ptx_GetLastError());
51 pInDoc = NULL;
52 fclose(pInStream);
53 pInStream = NULL;
54 Ptx_Release(pCopiedPages);
55 pCopiedPages = NULL;
56}
57
1// Create output document
2using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
3using (Document outDoc = Document.Create(outStream, null, null))
4{
5 // Define page copy options
6 PageCopyOptions copyOptions = new PageCopyOptions();
7
8 // Get output pages
9 PageList outPages = outDoc.Pages;
10
11 // Merge input documents
12 for (int i = 0; i < args.Length - 1; i++)
13 {
14 // Open input document
15 using Stream inFs = new FileStream(inPath[i], FileMode.Open, FileAccess.Read);
16 using Document inDoc = Document.Open(inFs, null);
17
18 // Copy all pages and append to output document
19 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
20 outPages.AddRange(copiedPages);
21 }
22}
23
1try (
2 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
3 try (// Create output document
4 Document outDoc = Document.create(outStream, null, null)) {
5
6 // Configure page copy options
7 PageCopyOptions copyOptions = new PageCopyOptions();
8
9 // Get output pages
10 PageList outPages = outDoc.getPages();
11
12 // Merge input document
13 for (int i = 0; i < args.length - 1; i++) {
14 try (// Open input document
15 FileStream inStream = new FileStream(inPath[i], FileStream.Mode.READ_ONLY);
16 Document inDoc = Document.open(inStream, null)) {
17
18 // Copy all pages and append to output document
19 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
20 outPages.addAll(copiedPages);
21 }
22 }
23 }
24}
25
1# Create output document
2with open(output_path, "wb+") as out_stream:
3 with Document.create(out_stream, None, None) as out_doc:
4
5 # Define page copy options
6 page_copy_options = PageCopyOptions()
7
8 # Get output pages
9 out_pages = out_doc.pages
10
11 # Merge input documents
12 for input_path in input_paths:
13 # Open input document
14 with open(input_path, "rb") as in_stream:
15 with Document.open(in_stream, None) as in_doc:
16
17 # Copy all pages and append to output document
18 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
19 out_pages.extend(copied_pages)
20
Merge multiple PDFs with outlines
1// Create output document
2using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
3using (Document outDoc = Document.Create(outStream, null, null))
4{
5 // Define page copy options, skip outline
6 PageCopyOptions pageCopyOptions = new PageCopyOptions
7 {
8 CopyOutlineItems = false
9 };
10
11 // Define outline copy options
12 OutlineCopyOptions outlineCopyOptions = new OutlineCopyOptions();
13
14 // Get output pages
15 PageList outPages = outDoc.Pages;
16
17 // Merge input documents
18 foreach (string inPath in inPaths)
19 {
20 // Open input document
21 using Stream inFs = new FileStream(inPath, FileMode.Open, FileAccess.Read);
22 using Document inDoc = Document.Open(inFs, null);
23
24 // Copy all pages and append to output document
25 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, pageCopyOptions);
26 outPages.AddRange(copiedPages);
27
28 // Create outline item
29 string title = inDoc.Metadata.Title ?? Path.GetFileName(inPath);
30 Page firstCopiedPage = copiedPages[0];
31 Destination destination = LocationZoomDestination.Create(outDoc, firstCopiedPage, 0, firstCopiedPage.Size.Height, null);
32 OutlineItem outlineItem = OutlineItem.Create(outDoc, title, destination);
33 outDoc.Outline.Add(outlineItem);
34
35 // Add outline items from input document as children
36 OutlineItemList children = outlineItem.Children;
37 foreach (OutlineItem inputOutline in inDoc.Outline)
38 children.Add(OutlineItem.Copy(outDoc, inputOutline, outlineCopyOptions));
39 }
40}
41
1try (
2 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
3 try (// Create output document
4 Document outDoc = Document.create(outStream, null, null)) {
5 // Define page copy options, skip outline
6 PageCopyOptions pageCopyOptions = new PageCopyOptions();
7 pageCopyOptions.setCopyOutlineItems(false);
8
9 // Define outline copy options
10 OutlineCopyOptions outlineCopyOptions = new OutlineCopyOptions();
11
12 // Get output pages
13 PageList outPages = outDoc.getPages();
14
15 // Merge input document
16 for (String inPath : inPaths) {
17 try (// Open input document
18 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
19 Document inDoc = Document.open(inStream, null)) {
20
21 // Copy all pages and append to output document
22 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), pageCopyOptions);
23 outPages.addAll(copiedPages);
24
25 // Create outline item
26 String title = inDoc.getMetadata().getTitle();
27 if (title == null)
28 title = Paths.get(inPath).getFileName().toString();
29 Page firstCopiedPage = copiedPages.get(0);
30 Destination destination = LocationZoomDestination.create(outDoc, firstCopiedPage, 0.0,
31 firstCopiedPage.getSize().getHeight(), null);
32 OutlineItem outlineItem = OutlineItem.create(outDoc, title, destination);
33 outDoc.getOutline().add(outlineItem);
34
35 // Add outline items from input document as children
36 OutlineItemList children = outlineItem.getChildren();
37 for (OutlineItem inputOutline : inDoc.getOutline())
38 children.add(OutlineItem.copy(outDoc, inputOutline, outlineCopyOptions));
39 }
40 }
41 }
42}
43
1# Create output document
2with open(output_path, "wb+") as out_stream:
3 with Document.create(out_stream, None, None) as out_doc:
4
5 # Define page copy options
6 page_copy_options = PageCopyOptions()
7 page_copy_options.copy_outline_items = False
8
9 # Define outline copy options
10 outline_copy_options = OutlineCopyOptions()
11
12 # Get output pages
13 out_pages = out_doc.pages
14
15 # Merge input documents
16 for input_path in input_paths:
17 # Open input document
18 with open(input_path, "rb") as in_stream:
19 with Document.open(in_stream, None) as in_doc:
20
21 # Copy all pages and append to output document
22 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
23 out_pages.extend(copied_pages)
24
25 # Create outline item
26 title = in_doc.metadata.title or os.path.basename(input_path)
27 first_copied_page = copied_pages[0]
28 destination = LocationZoomDestination.create(out_doc, first_copied_page, 0, first_copied_page.size.height, None)
29 outline_item = OutlineItem.create(out_doc, title, destination)
30 out_doc.outline.append(outline_item)
31
32 # Add outline items from input document as children
33 children = outline_item.children
34 for in_outline_item in in_doc.outline:
35 children.append(OutlineItem.copy(out_doc, in_outline_item, outline_copy_options))
36
Overlay color of PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Create transparency and set blend mode
13 Transparency transparency = new Transparency(colorAlpha)
14 {
15 BlendMode = BlendMode.Multiply
16 };
17
18 // Create colorspace
19 ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outDoc, colorType);
20
21 // Create a transparent paint for the given color
22 Paint paint = Paint.Create(outDoc, colorSpace, color, transparency);
23 Fill fill = new Fill(paint);
24
25 // Get output pages
26 PageList outPages = outDoc.Pages;
27
28 // Define page copy options
29 PageCopyOptions copyOptions = new PageCopyOptions();
30
31 // Loop through all pages
32 foreach (Page inPage in inDoc.Pages)
33 {
34 // Create a new page
35 Page outPage = Page.Copy(outDoc, inPage, copyOptions);
36 Size size = inPage.Size;
37
38 // Create a content generator
39 using (ContentGenerator generator = new ContentGenerator(outPage.Content, false))
40 {
41 // Make a rectangular path the same size as the page
42 PdfTools.Toolbox.Pdf.Content.Path path = new PdfTools.Toolbox.Pdf.Content.Path();
43 using (PathGenerator pathGenerator = new PathGenerator(path))
44 {
45 // Compute Rectangle
46 Rectangle pathRect = new Rectangle
47 {
48 Left = 0,
49 Bottom = 0,
50 Right = size.Width,
51 Top = size.Height
52 };
53 pathGenerator.AddRectangle(pathRect);
54 }
55 // Paint the path with the transparent paint
56 generator.PaintPath(path, fill, null);
57 }
58 // Add pages to output document
59 outPages.Add(outPage);
60 }
61}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Create transparency and set blend mode
12 Transparency transparency = new Transparency(colorAlpha);
13 transparency.setBlendMode(BlendMode.MULTIPLY);
14
15 // Create colorspace
16 ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outDoc, colorType);
17
18 // Create a transparent paint for the given color
19 Paint paint = Paint.create(outDoc, colorSpace, color, transparency);
20 Fill fill = new Fill(paint);
21
22 // Set copy options
23 PageCopyOptions copyOptions = new PageCopyOptions();
24
25 // Loop through all pages
26 for (Page inPage : inDoc.getPages()) {
27 // Create a new page
28 Size size = inPage.getSize();
29 Page outPage = Page.copy(outDoc, inPage, copyOptions);
30
31 try (// Create a content generator
32 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
33 // Calculate rectangle
34 Rectangle rect = new Rectangle(0, 0, size.width, size.height);
35
36 // Make a rectangular path the same size as the page
37 Path path = new Path();
38 try (
39 PathGenerator pathGenerator = new PathGenerator(path)) {
40 pathGenerator.addRectangle(rect);
41 }
42
43 // Paint the path with the transparent paint
44 generator.paintPath(path, fill, null);
45 }
46
47 // Add pages to output document
48 outDoc.getPages().add(outPage);
49 }
50 }
51}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def parse_options(options: str) -> tuple:
2 """
3 Parse the options string to extract color, color type, and alpha.
4 """
5 # Default values
6 color_type = COLOR_TYPE
7 color = COLOR
8 alpha = COLOR_ALPHA
9
10 if options is None:
11 return color, color_type, alpha
12
13 # Split options into tokens
14 tokens = options.split()
15 if not tokens:
16 return color, color_type, alpha
17
18 # Parse options
19 i = 0
20 while i < len(tokens):
21 arg = tokens[i]
22 if arg.startswith("-"):
23 if len(arg) != 2:
24 raise ValueError(f"Invalid option: {arg}")
25
26 flag = arg[1]
27 i += 1 # Move to the next token
28
29 if flag == "k": # Grayscale
30 if len(tokens) - i != 2:
31 raise ValueError("Invalid arguments for -k. Requires (k) (a).")
32 color_type = ProcessColorSpaceType.GRAY
33 color = [float(tokens[i])]
34 alpha = float(tokens[i + 1])
35 i += 2
36 elif flag == "c": # CMYK
37 if len(tokens) - i != 5:
38 raise ValueError("Invalid arguments for -c. Requires (c) (m) (y) (k) (a).")
39 color_type = ProcessColorSpaceType.CMYK
40 color = [float(tokens[i]), float(tokens[i + 1]), float(tokens[i + 2]), float(tokens[i + 3])]
41 alpha = float(tokens[i + 4])
42 i += 5
43 elif flag == "r": # RGB
44 if len(tokens) - i != 4:
45 raise ValueError("Invalid arguments for -r. Requires (r) (g) (b) (a).")
46 color_type = ProcessColorSpaceType.RGB
47 color = [float(tokens[i]), float(tokens[i + 1]), float(tokens[i + 2])]
48 alpha = float(tokens[i + 3])
49 i += 4
50 else:
51 raise ValueError(f"Unsupported option: {flag}")
52 else:
53 raise ValueError(f"Unexpected token: {arg}")
54
55 # Validate color and alpha values
56 if not (0 <= alpha <= 1 and all(0 <= c <= 1 for c in color)):
57 raise ValueError("Color and alpha values must be between 0 and 1.")
58
59 return color, color_type, alpha
1def apply_overlay_to_pages(in_doc: Document, out_doc: Document, color: list, color_type: ProcessColorSpaceType, color_alpha: float):
2 """Apply the overlay color to all pages in the document."""
3
4 # Create transparency and set blend mode
5 transparency = Transparency(color_alpha)
6 transparency.blend_mode = BlendMode.MULTIPLY
7
8 # Create color space
9 color_space = ColorSpace.create_process_color_space(out_doc, color_type)
10
11 # Create a transparent paint for the given color
12 paint = Paint.create(out_doc, color_space, color, transparency)
13 fill = Fill(paint)
14
15 # Get output pages
16 out_pages = out_doc.pages
17
18 # Define page copy options
19 copy_options = PageCopyOptions()
20
21 # Loop through all pages
22 for in_page in in_doc.pages:
23 # Create a new page
24 out_page = Page.copy(out_doc, in_page, copy_options)
25
26 in_page_size = in_page.size
27
28 # Create a content generator
29 with ContentGenerator(out_page.content, False) as generator:
30
31 # Make a rectangular path the same size as the page
32 path = Path()
33 with PathGenerator(path) as path_generator:
34 # Compute Rectangle
35 path_rectangle = Rectangle(
36 left=0,
37 bottom=0,
38 right=in_page_size.width,
39 top=in_page_size.height,
40 )
41
42 path_generator.add_rectangle(path_rectangle)
43
44 # Paint the path with the transparent overlay
45 generator.paint_path(path, fill, None)
46
47 out_pages.append(out_page)
Add info entries to PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy all pages and append to output document
16 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
17 outDoc.Pages.AddRange(copiedPages);
18
19 // Set info entry
20 Metadata metadata = Metadata.Copy(outDoc, inDoc.Metadata);
21 if (key == "Title")
22 metadata.Title = value;
23 else if (key == "Author")
24 metadata.Author = value;
25 else if (key == "Subject")
26 metadata.Subject = value;
27 else if (key == "Keywords")
28 metadata.Keywords = value;
29 else if (key == "CreationDate")
30 metadata.CreationDate = DateTimeOffset.Parse(value);
31 else if (key == "ModDate")
32 throw new Exception("ModDate cannot be set.");
33 else if (key == "Creator")
34 metadata.Creator = value;
35 else if (key == "Producer")
36 throw new Exception("Producer is set by means of the license key.");
37 else
38 metadata.CustomEntries[key] = value;
39 outDoc.Metadata = metadata;
40}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data (except metadata)
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Viewer settings
10 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
11
12 // Associated files (for PDF/A-3 and PDF 2.0 only)
13 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
14 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
15 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
16
17 // Plain embedded files
18 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
19 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
20 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
21}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy all pages and append to output document
15 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
16 outDoc.getPages().addAll(copiedPages);
17
18 // Set info entry
19 Metadata metadata = Metadata.copy(outDoc, inDoc.getMetadata());
20 if (key.equals("Title"))
21 metadata.setTitle(value);
22 else if (key.equals("Author"))
23 metadata.setAuthor(value);
24 else if (key.equals("Subject"))
25 metadata.setSubject(value);
26 else if (key.equals("Keywords"))
27 metadata.setKeywords(value);
28 else if (key.equals("CreationDate")) {
29 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd' 'HH:mm:ssZ");
30 OffsetDateTime creationDate = OffsetDateTime.parse(value, formatter);
31 metadata.setCreationDate(creationDate);
32 } else if (key.equals("ModDate"))
33 throw new Exception("ModDate cannot be set.");
34 else if (key.equals("Creator"))
35 metadata.setCreator(value);
36 else if (key.equals("Producer"))
37 throw new Exception("Producer is set by means of the license key.");
38 else
39 metadata.getCustomEntries().put(key, value);
40 outDoc.setMetadata(metadata);
41 }
42}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data (excluding metadata)
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Viewer settings
9 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
10
11 // Associated files (for PDF/A-3 and PDF 2.0 only)
12 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
13 for (FileReference inFileRef : inDoc.getAssociatedFiles())
14 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
15
16 // Plain embedded files
17 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
18 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
19 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
20}
1
2
3# Open input document
4with io.FileIO(input_path, "rb") as in_stream:
5 with Document.open(in_stream, None) as in_doc:
6
7 # Create output document
8 with io.FileIO(output_path, "wb+") as out_stream:
9 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
10
11 # Copy document-wide data
12 copy_document_data(in_doc, out_doc)
13
14 # Define page copy options
15 page_copy_options = PageCopyOptions()
16
17 # Copy all pages and append to output document
18 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
19 out_doc.pages.extend(copied_pages)
20
21 # Set info entry
22 metadata = Metadata.copy(out_doc, in_doc.metadata)
23 if key == "Title":
24 metadata.title = value
25 elif key == "Author":
26 metadata.author = value
27 elif key == "Subject":
28 metadata.subject = value
29 elif key == "Keywords":
30 metadata.keywords = value
31 elif key == "CreationDate":
32 # Use of the ISO 8601 format for the date
33 date_format = "%Y-%m-%dT%H:%M:%S"
34 parsed_date = datetime.strptime(value, date_format)
35
36 metadata.creation_date = parsed_date
37 elif key == "ModDate":
38 raise Exception("ModDate cannot be set.")
39 elif key == "Creator":
40 metadata.creator = value
41 elif key == "Producer":
42 raise Exception("Producer is set by means of the license key.")
43 else:
44 metadata.custom_entries[key] = value
45
46 # Assign modified metadata to the output document
47 out_doc.metadata = metadata
48
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data (excluding metadata)
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Viewer settings
9 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
10
11 # Associated files (for PDF/A-3 and PDF 2.0 only)
12 outAssociatedFiles = out_doc.associated_files
13 for in_file_ref in in_doc.associated_files:
14 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
15
16 # Plain embedded files
17 out_embedded_files = out_doc.plain_embedded_files
18 for in_file_ref in in_doc.plain_embedded_files:
19 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Set the open-destination of a PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 if (destinationPageNumber < 1 || destinationPageNumber > inDoc.Pages.Count)
6 throw new ArgumentOutOfRangeException("Given page number is invalid");
7
8 // Create output document
9 using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
10 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
11
12 // Copy document-wide data
13 CopyDocumentData(inDoc, outDoc);
14
15 // Define page copy options
16 PageCopyOptions copyOptions = new PageCopyOptions();
17
18 // Copy all pages and append to output document
19 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
20 outDoc.Pages.AddRange(copiedPages);
21
22 // Add open destination
23 Page outPage = copiedPages[destinationPageNumber - 1];
24 outDoc.OpenDestination = LocationZoomDestination.Create(outDoc, outPage, 0, outPage.Size.Height, null);
25}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Check given page number
9 if (destinationPageNumber < 1 || destinationPageNumber > inDoc.getPages().size()) {
10 System.out.println("Given pageNumber is invalid.");
11 return;
12 }
13
14 // Copy document-wide data
15 copyDocumentData(inDoc, outDoc);
16
17 // Define page copy options
18 PageCopyOptions copyOptions = new PageCopyOptions();
19
20 // Copy all pages and append to output document
21 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
22 outDoc.getPages().addAll(copiedPages);
23
24 // Add open destination
25 Page outPage = outDoc.getPages().get(destinationPageNumber - 1);
26 LocationZoomDestination destination = LocationZoomDestination.create(outDoc, outPage, 0.0, outPage.getSize().getHeight(), null);
27 outDoc.setOpenDestination(destination);
28 }
29}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1
2
3destination_page_number = int(page_number)
4
5# Open input document
6with io.FileIO(input_path, "rb") as in_stream:
7 with Document.open(in_stream, None) as in_doc:
8
9 if destination_page_number < 1 or destination_page_number > len(in_doc.pages):
10 raise ValueError("Given page number is invalid")
11
12 # Create output document
13 with io.FileIO(output_path, "wb+") as out_stream:
14 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
15
16 # Copy document-wide data
17 copy_document_data(in_doc, out_doc)
18
19 # Define page copy options
20 page_copy_options = PageCopyOptions()
21
22 # Copy all pages and append to output document
23 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
24 out_doc.pages.extend(copied_pages)
25
26 # Add open destination
27 out_page = copied_pages[destination_page_number - 1]
28 out_doc.open_destination = LocationZoomDestination.create(out_doc, out_page, 0, out_page.size.height, None)
29
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Remove pages from PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9pInPageList = PtxPdf_Document_GetPages(pInDoc);
10GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
11 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
12 szErrorBuff, Ptx_GetLastError());
13int nInPages = PtxPdf_PageList_GetCount(pInPageList);
14iStartIndex = MAX(MIN(nInPages - 1, iStartIndex), 0);
15nCount = MIN(nInPages - iStartIndex, nCount);
16GOTO_CLEANUP_IF_FALSE(nCount > 0, _T("lastPage must be greater or equal to firstPage.\n"));
17
18// Create output document
19pOutStream = _tfopen(szOutPath, _T("wb+"));
20GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
21PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
22iConformance = PtxPdf_Document_GetConformance(pInDoc);
23pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
24GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
25 szOutPath, szErrorBuff, Ptx_GetLastError());
26
27// Copy document-wide data
28GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
29 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
30 Ptx_GetLastError());
31
32// Configure copy options
33pCopyOptions = PtxPdf_PageCopyOptions_New();
34
35// Get page range from input pages
36pInPageRange = PtxPdf_PageList_GetRange(pInPageList, iStartIndex, nCount);
37GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange,
38 _T("Failed to get page range from input document. %s (ErrorCode: 0x%08x)\n"),
39 szErrorBuff, Ptx_GetLastError());
40
41// Copy page range to toutput document
42pOutPageRange = PtxPdf_PageList_Copy(pOutDoc, pInPageRange, pCopyOptions);
43GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageRange, _T("Failed to copy page range. %s (ErrorCode: 0x%08x)\n"),
44 szErrorBuff, Ptx_GetLastError());
45
46// Get output pages
47pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
48GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
49 _T("Failed to get the pages of the output document. %s (ErrorCode: 0x%08x)\n"),
50 szErrorBuff, Ptx_GetLastError());
51
52// Appende page range to output pages
53GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pOutPageRange),
54 _T("Failed to append page range. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
55 Ptx_GetLastError());
56
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 startIndex = Math.Max(Math.Min(inDoc.Pages.Count - 1, startIndex), 0);
6 count = Math.Min(inDoc.Pages.Count - startIndex, count);
7 if (count <= 0)
8 {
9 Console.WriteLine("lastPage must be greater or equal to firstPage");
10 return;
11 }
12
13 // Create output document
14 using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
15 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
16
17 // Copy document-wide data
18 CopyDocumentData(inDoc, outDoc);
19
20 // Define page copy options
21 PageCopyOptions copyOptions = new PageCopyOptions();
22
23 // Get page range from input pages
24 PageList inPageRange = inDoc.Pages.GetRange(startIndex, count);
25
26 // Copy page range and append to output document
27 PageList outPageRange = PageList.Copy(outDoc, inPageRange, copyOptions);
28 outDoc.Pages.AddRange(outPageRange);
29}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4 // Get pages from input document
5 PageList inPages = inDoc.getPages();
6
7 // Correct and check page indices
8 startIndex = Math.max(Math.min(inPages.size() - 1, startIndex), 0);
9 endIndex = Math.max(Math.min(inPages.size(), endIndex), 0);
10 if (startIndex >= endIndex) {
11 System.out.println("lastPage must be greater or equal to firstPage");
12 return;
13 }
14 try (
15 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
16 try (// Create output document
17 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
18
19 // Copy document-wide data
20 copyDocumentData(inDoc, outDoc);
21
22 // Define page copy options
23 PageCopyOptions copyOptions = new PageCopyOptions();
24
25 // Get page range from input pages
26 PageList inPageRange = inPages.subList(startIndex, endIndex);
27
28 // Copy page range and append to output document
29 PageList outPageRange = PageList.copy(outDoc, inPageRange, copyOptions);
30 outDoc.getPages().addAll(outPageRange);
31 }
32 }
33}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain mbedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1
2
3start_index = int(args.first_page) - 1
4last_page = int(args.last_page)
5count = int(args.last_page) - start_index
6
7# Open input document
8with io.FileIO(input_path, "rb") as in_stream:
9 with Document.open(in_stream, None) as in_doc:
10
11 # Validate page range
12 start_index = max(min(len(in_doc.pages) - 1, start_index), 0)
13 count = min(len(in_doc.pages) - start_index, count)
14 if count <= 0:
15 print("lastPage must be greater or equal to firstPage")
16 exit(1)
17
18 # Create output document
19 with io.FileIO(output_path, "wb+") as out_stream:
20 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
21
22 # Copy document-wide data
23 copy_document_data(in_doc, out_doc)
24
25 # Define page copy options
26 page_copy_options = PageCopyOptions()
27
28 # Get page range from input pages
29 in_page_range = in_doc.pages[start_index:last_page]
30
31 # Copy page range and append to output document
32 out_page_range = PageList.copy(out_doc, in_page_range, page_copy_options)
33 out_doc.pages.extend(out_page_range)
34
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Split at Outlines
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 // Collect all outline items at the given level
6 List<OutlineItem> outlines = GetOutlines(inDoc.Outline, level);
7
8 // Collect all page ranges corresponding to the given outline items
9 List<Tuple<PageList, OutlineItem>> parts = GetParts(inDoc.Pages, outlines);
10
11 // Iterate over all collected parts
12 foreach (var part in parts)
13 {
14 // Turn the outline item's title into a valid file name
15 string fileName = part.Item2.Title;
16 foreach (char c in System.IO.Path.GetInvalidFileNameChars())
17 {
18 fileName = fileName.Replace(c, '_');
19 }
20 fileName += ".pdf";
21 fileName = System.IO.Path.Combine(outDir, fileName);
22
23 // Create output document
24 using Stream outStream = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
25 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
26
27 // Copy document-wide data
28 CopyDocumentData(inDoc, outDoc);
29
30 // Define page copy options
31 PageCopyOptions pageCopyOptions = new PageCopyOptions();
32 pageCopyOptions.CopyOutlineItems = false;
33
34 // Copy the pages and add to the output document's page list
35 PageList outPages = PageList.Copy(outDoc, part.Item1, pageCopyOptions);
36 outDoc.Pages.AddRange(outPages);
37
38 // Copy child outline items
39 OutlineCopyOptions outlineCopyOptions = new OutlineCopyOptions();
40 foreach (var child in part.Item2.Children)
41 {
42 outDoc.Outline.Add(OutlineItem.Copy(outDoc, child, outlineCopyOptions));
43 }
44 }
45}
1private static List<OutlineItem> GetOutlines(OutlineItemList currentOutlines, int level, int currentLevel = 1)
2{
3 List<OutlineItem> matchingOutlines = new List<OutlineItem>();
4 // If the current level matches the specified level add the given outline items
5 if (level == currentLevel)
6 {
7 matchingOutlines.AddRange(currentOutlines);
8 }
9 else
10 {
11 // Otherwise recurse to next level
12 foreach (var outline in currentOutlines)
13 {
14 matchingOutlines.AddRange(GetOutlines(outline.Children, level, currentLevel + 1));
15 }
16 }
17 return matchingOutlines;
18}
1private static List<Tuple<PageList, OutlineItem>> GetParts(PageList inPages, List<OutlineItem> outlines)
2{
3 // Construct parts according to the given outlines
4 List<Tuple<PageList, OutlineItem>> parts = new List<Tuple<PageList, OutlineItem>>();
5
6 // No parts to be constructed if no outlines are found
7 if (outlines.Count == 0)
8 return parts;
9
10 // Keep both the last and the next outline items while iterating
11 OutlineItem lastOutline = null;
12 var outlineEnumerator = outlines.GetEnumerator();
13 outlineEnumerator.MoveNext();
14 OutlineItem nextOutline = outlineEnumerator.Current;
15
16 // Keep both, the last and the current page index while iterating
17 int lastPageIndex = 0;
18 for (int pageIndex = 0; pageIndex < inPages.Count; pageIndex++)
19 {
20 // Check if this page is the destination's page of the next outline
21 if (inPages[pageIndex].Equals(nextOutline.Destination.Target.Page))
22 {
23 // Create a new part if the last outline item is defined and if the page index has increased at least by 1
24 if (lastOutline != null && pageIndex - lastPageIndex > 0)
25 parts.Add(new Tuple<PageList, OutlineItem>(inPages.GetRange(lastPageIndex, pageIndex - lastPageIndex), lastOutline));
26
27 // Keep the current page index as the last page index used
28 lastPageIndex = pageIndex;
29
30 // Keep the current outline as the last outline used
31 lastOutline = nextOutline;
32
33 // Iterate to the next outline item and stop if none left
34 if (outlineEnumerator.MoveNext())
35 nextOutline = outlineEnumerator.Current;
36 else
37 break;
38 }
39 }
40 // Add the last part which is assumed to contain all the pages until the end of the document
41 parts.Add(new Tuple<PageList, OutlineItem>(inPages.GetRange(lastPageIndex, inPages.Count - lastPageIndex), lastOutline));
42 return parts;
43}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def get_outlines(current_outlines: OutlineItemList, level: int, current_level: int = 1) -> list:
2 """Recursively collect outline items at the specified level."""
3 matching_outlines = []
4 # If the current level matches the specified level add the given outline items
5 if level == current_level:
6 matching_outlines.extend(current_outlines)
7 else:
8 # Otherwise recurse to next level
9 for outline in current_outlines:
10 matching_outlines.extend(get_outlines(outline.children, level, current_level + 1))
11
12 return matching_outlines
1def get_parts(in_pages: PageList, outlines: list) -> list:
2 """Collect page ranges corresponding to the outlines."""
3 # Construct parts according to the given outlines
4 parts = []
5
6 # No parts to be constructed if no outlines are found
7 if not outlines or len(outlines) == 0:
8 return parts
9
10 # Keep both the last and the next outline items while iterating
11 last_outline = None
12 last_page_index = 0
13
14 for page_index, page in enumerate(in_pages):
15 # Check if this page is the destination's page of the next outline
16 if outlines and page == outlines[0].destination.target.page:
17 # Create a new part if the last outline item is defined and if the page index has increased at least by 1
18 if last_outline and page_index - last_page_index > 0:
19 parts.append((in_pages[last_page_index:page_index], last_outline))
20 last_outline = outlines.pop(0)
21
22 # Keep the current page index as the last page index used
23 last_page_index = page_index
24
25 # Add the last part which is assumed to contain all the pages until the end of the document
26 if last_outline:
27 parts.append((in_pages[last_page_index:], last_outline))
28
29 return parts
Imposition
Create a booklet from PDF
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 // Objects that need releasing or closing
4 TPtxPdfContent_IccBasedColorSpace* pInOutputIntent = NULL;
5 TPtxPdfContent_IccBasedColorSpace* pOutOutputIntent = NULL;
6 TPtxPdf_Metadata* pInMetadata = NULL;
7 TPtxPdf_Metadata* pOutMetadata = NULL;
8 TPtxPdfNav_ViewerSettings* pInViewerSettings = NULL;
9 TPtxPdfNav_ViewerSettings* pOutViewerSettings = NULL;
10 TPtxPdf_FileReferenceList* pInFileRefList = NULL;
11 TPtxPdf_FileReferenceList* pOutFileRefList = NULL;
12 TPtxPdf_FileReference* pInFileRef = NULL;
13 TPtxPdf_FileReference* pOutFileRef = NULL;
14
15 iReturnValue = 0;
16
17 // Output intent
18 pInOutputIntent = PtxPdf_Document_GetOutputIntent(pInDoc);
19 if (pInOutputIntent != NULL)
20 {
21 pOutOutputIntent = PtxPdfContent_IccBasedColorSpace_Copy(pOutDoc, pInOutputIntent);
22 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutOutputIntent,
23 _T("Failed to copy ICC-based color space. %s (ErrorCode: 0x%08x)\n"),
24 szErrorBuff, Ptx_GetLastError());
25 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetOutputIntent(pOutDoc, pOutOutputIntent),
26 _T("Failed to set output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
27 Ptx_GetLastError());
28 }
29 else
30 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get output intent. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
31 Ptx_GetLastError());
32
33 // Metadata
34 pInMetadata = PtxPdf_Document_GetMetadata(pInDoc);
35 if (pInMetadata != NULL)
36 {
37 pOutMetadata = PtxPdf_Metadata_Copy(pOutDoc, pInMetadata);
38 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutMetadata, _T("Failed to copy metadata. %s (ErrorCode: 0x%08x)\n"),
39 szErrorBuff, Ptx_GetLastError());
40 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetMetadata(pOutDoc, pOutMetadata),
41 _T("Failed to set metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
42 Ptx_GetLastError());
43 }
44 else
45 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get metadata. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
46 Ptx_GetLastError());
47
48 // Viewer settings
49 pInViewerSettings = PtxPdf_Document_GetViewerSettings(pInDoc);
50 if (pInViewerSettings != NULL)
51 {
52 pOutViewerSettings = PtxPdfNav_ViewerSettings_Copy(pOutDoc, pInViewerSettings);
53 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutViewerSettings,
54 _T("Failed to copy viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
55 Ptx_GetLastError());
56 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Document_SetViewerSettings(pOutDoc, pOutViewerSettings),
57 _T("Failed to set viewer settings. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
58 Ptx_GetLastError());
59 }
60 else
61 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get viewer settings. %s (ErrorCode: 0x%08x)"), szErrorBuff,
62 Ptx_GetLastError());
63
64 // Associated files (for PDF/A-3 and PDF 2.0 only)
65 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
66 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of input document. %s (ErrorCode: 0x%08x)\n"),
67 szErrorBuff, Ptx_GetLastError());
68 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
69 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get associated files of output document. %s (ErrorCode: 0x%08x)\n"),
70 szErrorBuff, Ptx_GetLastError());
71 int nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
72 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of associated files. %s (ErrorCode: 0x%08x)\n"),
73 szErrorBuff, Ptx_GetLastError());
74 for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
75 {
76 pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
77 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
78 szErrorBuff, Ptx_GetLastError());
79 pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
80 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
81 szErrorBuff, Ptx_GetLastError());
82 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
83 _T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
84 Ptx_GetLastError());
85 Ptx_Release(pInFileRef);
86 pInFileRef = NULL;
87 Ptx_Release(pOutFileRef);
88 pOutFileRef = NULL;
89 }
90 Ptx_Release(pInFileRefList);
91 pInFileRefList = NULL;
92 Ptx_Release(pOutFileRefList);
93 pOutFileRefList = NULL;
94
95 // Plain embedded files
96 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
97 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
98 pInFileRefList, _T("Failed to get plain embedded files of input document %s (ErrorCode: 0x%08x)\n"),
99 szErrorBuff, Ptx_GetLastError());
100 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
101 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
102 pInFileRefList, _T("Failed to get plain embedded files of output document %s (ErrorCode: 0x%08x)\n"),
103 szErrorBuff, Ptx_GetLastError());
104 nFileRefs = PtxPdf_FileReferenceList_GetCount(pInFileRefList);
105 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get count of plain embedded files. %s (ErrorCode: 0x%08x)\n"),
106 szErrorBuff, Ptx_GetLastError());
107 for (int iFileRef = 0; iFileRef < nFileRefs; iFileRef++)
108 {
109 pInFileRef = PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef);
110 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInFileRef, _T("Failed to get file reference. %s (ErrorCode: 0x%08x)\n"),
111 szErrorBuff, Ptx_GetLastError());
112 pOutFileRef = PtxPdf_FileReference_Copy(pOutDoc, pInFileRef);
113 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutFileRef, _T("Failed to copy file reference. %s (ErrorCode: 0x%08x)\n"),
114 szErrorBuff, Ptx_GetLastError());
115 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_FileReferenceList_Add(pOutFileRefList, pOutFileRef),
116 _T("Failed to add file reference. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
117 Ptx_GetLastError());
118 Ptx_Release(pInFileRef);
119 pInFileRef = NULL;
120 Ptx_Release(pOutFileRef);
121 pOutFileRef = NULL;
122 }
123
124cleanup:
125 if (pInOutputIntent != NULL)
126 Ptx_Release(pInOutputIntent);
127 if (pOutOutputIntent != NULL)
128 Ptx_Release(pOutOutputIntent);
129 if (pInMetadata != NULL)
130 Ptx_Release(pInMetadata);
131 if (pOutMetadata != NULL)
132 Ptx_Release(pOutMetadata);
133 if (pInViewerSettings != NULL)
134 Ptx_Release(pInViewerSettings);
135 if (pOutViewerSettings != NULL)
136 Ptx_Release(pOutViewerSettings);
137 if (pInFileRefList != NULL)
138 Ptx_Release(pInFileRefList);
139 if (pOutFileRefList != NULL)
140 Ptx_Release(pOutFileRefList);
141 if (pInFileRef != NULL)
142 Ptx_Release(pInFileRef);
143 if (pOutFileRef != NULL)
144 Ptx_Release(pOutFileRef);
145 return iReturnValue;
146}
1int StampPageNumber(TPtxPdf_Document* pDocument, TPtxPdfContent_Font* pFont,
2 TPtxPdfContent_ContentGenerator* pGenerator, int nPageNo, BOOL bIsLeftPage)
3{
4 // Objects that need releasing or closing
5 TPtxPdfContent_Text* pText = NULL;
6 TPtxPdfContent_TextGenerator* pTextGenerator = NULL;
7
8 // Create text object
9 pText = PtxPdfContent_Text_Create(pDocument);
10 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pText, _T("Failed to create text object. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
11 Ptx_GetLastError());
12
13 // Create text generator
14 pTextGenerator = PtxPdfContent_TextGenerator_New(pText, pFont, 8.0, NULL);
15 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pTextGenerator, _T("Failed to create text generator. %s (ErrorCode: 0x%08x)\n"),
16 szErrorBuff, Ptx_GetLastError());
17
18 TCHAR szStampText[50];
19 _stprintf(szStampText, _T("Page %d"), nPageNo);
20
21 // Get width of stamp text
22 double dStampWidth = PtxPdfContent_TextGenerator_GetWidth(pTextGenerator, szStampText);
23 if (dStampWidth == 0.0)
24 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get text width. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
25 Ptx_GetLastError());
26
27 // Compute position
28 TPtxGeomReal_Point point = {
29 .dX = bIsLeftPage ? dBorder + 0.5 * dCellWidth - dStampWidth / 2
30 : 2 * dBorder + 1.5 * dCellWidth - dStampWidth / 2,
31 .dY = dBorder,
32 };
33
34 // Move to position
35 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_MoveTo(pTextGenerator, &point),
36 _T("Failed to move to position. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
37 Ptx_GetLastError());
38 // Add page number
39 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_TextGenerator_Show(pTextGenerator, szStampText),
40 _T("Failed to show text. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
41 Ptx_GetLastError());
42
43 BOOL bClose = PtxPdfContent_TextGenerator_Close(pTextGenerator);
44 pTextGenerator = NULL;
45 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(bClose, _T("Failed to close text generator. %s (ErrorCode: 0x%08x)\n"),
46 szErrorBuff, Ptx_GetLastError());
47
48 // Paint the positioned text
49 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintText(pGenerator, pText),
50 _T("Failed to paint text. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
51 Ptx_GetLastError());
52
53cleanup:
54 if (pText != NULL)
55 Ptx_Release(pText);
56 if (pTextGenerator != NULL)
57 PtxPdfContent_TextGenerator_Close(pTextGenerator);
58 return iReturnValue;
59}
1void ComputeTargetRect(TPtxGeomReal_Rectangle* pRectangle, const TPtxGeomReal_Size* pBBox, BOOL bIsLeftPage)
2{
3 // Compute factor for fitting page into rectangle
4 double dScale = MIN(dCellWidth / pBBox->dWidth, dCellHeight / pBBox->dHeight);
5 double dGroupWidth = pBBox->dWidth * dScale;
6 double dGroupHeight = pBBox->dHeight * dScale;
7
8 // Compute x-value
9 double dGroupXPos =
10 bIsLeftPage ? dCellLeft + (dCellWidth - dGroupWidth) / 2 : dCellRight + (dCellWidth - dGroupWidth) / 2;
11
12 // Compute y-value
13 double dGroupYPos = dCellYPos + (dCellHeight - dGroupHeight) / 2;
14
15 // Set rectangle
16 pRectangle->dLeft = dGroupXPos;
17 pRectangle->dBottom = dGroupYPos;
18 pRectangle->dRight = dGroupXPos + dGroupWidth;
19 pRectangle->dTop = dGroupYPos + dGroupHeight;
20}
1int CreateBooklet(TPtxPdf_PageList* pInDocList, TPtxPdf_Document* pOutDoc, TPtxPdf_PageList* pOutDocList,
2 int nLeftPageIndex, int nRightPageIndex, TPtxPdfContent_Font* pFont)
3{
4 // Objects that need releasing or closing
5 TPtxPdf_PageCopyOptions* pCopyOptions = NULL;
6 TPtxPdf_Page* pOutPage = NULL;
7 TPtxPdfContent_Content* pContent = NULL;
8 TPtxPdfContent_ContentGenerator* pGenerator = NULL;
9 TPtxPdf_Page* pInPage = NULL;
10 TPtxPdfContent_Group* pGroup = NULL;
11
12 // Configure copy options
13 pCopyOptions = PtxPdf_PageCopyOptions_New();
14
15 // Create page object
16 pOutPage = PtxPdf_Page_Create(pOutDoc, &pageSize);
17 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create page object. %s (ErrorCode: 0x%08x)\n"),
18 szErrorBuff, Ptx_GetLastError());
19
20 // Create content generator
21 pContent = PtxPdf_Page_GetContent(pOutPage);
22 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
23 Ptx_GetLastError());
24 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
25 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator, _T("Failed to create content generator. %s (ErrorCode: 0x%08x)\n"),
26 szErrorBuff, Ptx_GetLastError());
27
28 int nPageCount = PtxPdf_PageList_GetCount(pInDocList);
29 GOTO_CLEANUP_IF_ERROR_PRINT_ERROR(_T("Failed to get page list count. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
30 Ptx_GetLastError());
31
32 // Left page
33 if (nLeftPageIndex < nPageCount)
34 {
35 // Get the input page
36 pInPage = PtxPdf_PageList_Get(pInDocList, nLeftPageIndex);
37 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
38 Ptx_GetLastError());
39
40 // Copy page from input to output
41 pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
42 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x)\n"),
43 szErrorBuff, Ptx_GetLastError());
44
45 // Compute group location
46 TPtxGeomReal_Size groupSize;
47 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
48 _T("Failed to get group size. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
49 Ptx_GetLastError());
50 TPtxGeomReal_Rectangle targetRect;
51 ComputeTargetRect(&targetRect, &groupSize, TRUE);
52
53 // Paint group at location
54 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
55 PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
56 _T("Failed to paint group. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
57
58 // Add page number to page
59 if (StampPageNumber(pOutDoc, pFont, pGenerator, nLeftPageIndex + 1, TRUE) != 0)
60 goto cleanup;
61
62 Ptx_Release(pInPage);
63 pInPage = NULL;
64 Ptx_Release(pGroup);
65 pGroup = NULL;
66 }
67
68 // Right page
69 if (nRightPageIndex < nPageCount)
70 {
71 // Get the input Page
72 pInPage = PtxPdf_PageList_Get(pInDocList, nRightPageIndex);
73 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("Failed to get page. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
74 Ptx_GetLastError());
75
76 // Copy page from input to output
77 pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
78 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x)\n"),
79 szErrorBuff, Ptx_GetLastError());
80
81 // Compute group location
82 TPtxGeomReal_Size groupSize;
83 PtxPdfContent_Group_GetSize(pGroup, &groupSize);
84 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
85 _T("Failed to get group size. %s (ErrorCode: 0x%08x)\n"), szErrorBuff,
86 Ptx_GetLastError());
87 TPtxGeomReal_Rectangle targetRect;
88 ComputeTargetRect(&targetRect, &groupSize, FALSE);
89
90 // Paint group on the Computed rectangle
91 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
92 PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
93 _T("Failed to paint group. %s (ErrorCode: 0x%08x)\n"), szErrorBuff, Ptx_GetLastError());
94
95 // Add page number to page
96 if (StampPageNumber(pOutDoc, pFont, pGenerator, nRightPageIndex + 1, FALSE) != 0)
97 goto cleanup;
98 }
99
100 BOOL bClose = PtxPdfContent_ContentGenerator_Close(pGenerator);
101 pGenerator = NULL;
102 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(bClose, _T("Failed to close content generator. %s (ErrorCode: 0x%08x)\n"),
103 szErrorBuff, Ptx_GetLastError());
104
105 // Add page to output document
106 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutDocList, pOutPage),
107 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x)\n"),
108 szErrorBuff, Ptx_GetLastError());
109
110cleanup:
111 if (pGenerator != NULL)
112 PtxPdfContent_ContentGenerator_Close(pGenerator);
113 if (pCopyOptions != NULL)
114 Ptx_Release(pCopyOptions);
115 if (pOutPage != NULL)
116 Ptx_Release(pOutPage);
117 if (pContent != NULL)
118 Ptx_Release(pContent);
119 if (pInPage != NULL)
120 Ptx_Release(pInPage);
121 if (pGroup != NULL)
122 Ptx_Release(pGroup);
123 return iReturnValue;
124}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Create a font
13 Font font = Font.CreateFromSystem(outDoc, "Arial", "Italic", true);
14
15 // Copy pages
16 PageList inPages = inDoc.Pages;
17 PageList outPages = outDoc.Pages;
18 int numberOfSheets = (inPages.Count + 3) / 4;
19
20 for (int sheetNumber = 0; sheetNumber < numberOfSheets; ++sheetNumber)
21 {
22
23 // Add on front side
24 CreateBooklet(inPages, outDoc, outPages, 4 * numberOfSheets - 2 * sheetNumber - 1,
25 2 * sheetNumber, font);
26
27 // Add on back side
28 CreateBooklet(inPages, outDoc, outPages, 2 * sheetNumber + 1,
29 4 * numberOfSheets - 2 * sheetNumber - 2, font);
30 }
31}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void CreateBooklet(PageList inPages, Document outDoc, PageList outPages, int leftPageIndex,
2 int rightPageIndex, Font font)
3{
4 // Define page copy options
5 PageCopyOptions copyOptions = new PageCopyOptions();
6
7 // Create page object
8 Page outpage = Page.Create(outDoc, PageSize);
9
10 // Create content generator
11 using (ContentGenerator generator = new ContentGenerator(outpage.Content, false))
12 {
13 // Left page
14 if (leftPageIndex < inPages.Count)
15 {
16 // Copy page from input to output
17 Page leftPage = inPages[leftPageIndex];
18 Group leftGroup = Group.CopyFromPage(outDoc, leftPage, copyOptions);
19
20 // Paint group on the calculated rectangle
21 generator.PaintGroup(leftGroup, ComputTargetRect(leftGroup.Size, true), null);
22
23 // Add page number to page
24 StampPageNumber(outDoc, font, generator, leftPageIndex + 1, true);
25 }
26
27 // Right page
28 if (rightPageIndex < inPages.Count)
29 {
30 // Copy page from input to output
31 Page rigthPage = inPages[rightPageIndex];
32 Group rightGroup = Group.CopyFromPage(outDoc, rigthPage, copyOptions);
33
34 // Paint group on the calculated rectangle
35 generator.PaintGroup(rightGroup, ComputTargetRect(rightGroup.Size, false), null);
36
37 // Add page number to page
38 StampPageNumber(outDoc, font, generator, rightPageIndex + 1, false);
39 }
40 }
41 // Add page to output document
42 outPages.Add(outpage);
43}
1private static Rectangle ComputTargetRect(Size bbox, bool isLeftPage)
2{
3 // Calculate factor for fitting page into rectangle
4 double scale = Math.Min(CellWidth / bbox.Width, CellHeight / bbox.Height);
5 double groupWidth = bbox.Width * scale;
6 double groupHeight = bbox.Height * scale;
7
8 // Calculate x-value
9 double groupXPos = isLeftPage ? CellLeft + (CellWidth - groupWidth) / 2 :
10 CellRight + (CellWidth - groupWidth) / 2;
11
12 // Calculate y-value
13 double groupYPos = CellYPos + (CellHeight - groupHeight) / 2;
14
15 // Calculate rectangle
16 return new Rectangle
17 {
18 Left = groupXPos,
19 Bottom = groupYPos,
20 Right = groupXPos + groupWidth,
21 Top = groupYPos + groupHeight
22 };
23}
1private static void StampPageNumber(Document document, Font font, ContentGenerator generator,
2 int PageNo, bool isLeftPage)
3{
4 // Create text object
5 Text text = Text.Create(document);
6
7 // Create text generator
8 using (TextGenerator textgenerator = new TextGenerator(text, font, 8, null))
9 {
10 string stampText = string.Format("Page {0}", PageNo);
11
12 // Get width of stamp text
13 double width = textgenerator.GetWidth(stampText);
14
15 // Calculate position
16 double x = isLeftPage ? Border + 0.5 * CellWidth - width / 2 :
17 2 * Border + 1.5 * CellWidth - width / 2;
18 double y = Border;
19
20 // Move to position
21 textgenerator.MoveTo(new Point { X = x, Y = y});
22
23 // Add page number
24 textgenerator.Show(stampText);
25 }
26 // Paint the positioned text
27 generator.PaintText(text);
28}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7 Font font = Font.createFromSystem(outDoc, "Arial", "Italic", true);
8
9 // Copy document-wide data
10 copyDocumentData(inDoc, outDoc);
11
12 // Copy pages
13 PageList inPages = inDoc.getPages();
14 PageList outPages = outDoc.getPages();
15 int numberOfSheets = (inPages.size() + 3) / 4;
16
17 for (int sheetNumber = 0; sheetNumber < numberOfSheets; ++sheetNumber) {
18 // Add on front side
19 createBooklet(inPages, outDoc, outPages, 4 * numberOfSheets - 2 * sheetNumber - 1,
20 2 * sheetNumber, font);
21
22 // Add on back side
23 createBooklet(inPages, outDoc, outPages, 2 * sheetNumber + 1,
24 4 * numberOfSheets - 2 * sheetNumber - 2, font);
25 }
26 }
27}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1private static void createBooklet(PageList inPages, Document outDoc, PageList outPages, int leftPageIndex,
2 int rightPageIndex, Font font) throws ToolboxException, IOException {
3 // Define page copy options
4 PageCopyOptions copyOptions = new PageCopyOptions();
5
6 // Create page object
7 Page outPage = Page.create(outDoc, new Size(PageWidth, PageHeight));
8
9 try (// Create content generator
10 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
11
12 // Left page
13 if (leftPageIndex < inPages.size()) {
14 Page leftPage = inPages.get(leftPageIndex);
15
16 // Copy page from input to output
17 Group leftGroup = Group.copyFromPage(outDoc, leftPage, copyOptions);
18
19 // Paint group on the calculated rectangle
20 generator.paintGroup(leftGroup, computeTargetRect(leftGroup.getSize(), true), null);
21
22 // Add page number to page
23 StampPageNumber(outDoc, font, generator, leftPageIndex + 1, true);
24 }
25
26 // Right page
27 if (rightPageIndex < inPages.size()) {
28 Page rightPage = inPages.get(rightPageIndex);
29
30 // Copy page from input to output
31 Group rightGroup = Group.copyFromPage(outDoc, rightPage, copyOptions);
32
33 // Paint group on the calculated rectangle
34 generator.paintGroup(rightGroup, computeTargetRect(rightGroup.getSize(), false), null);
35
36 // Add page number to page
37 StampPageNumber(outDoc, font, generator, rightPageIndex + 1, false);
38 }
39 }
40 // Add page to output document
41 outPages.add(outPage);
42}
1private static Rectangle computeTargetRect(Size bbox, Boolean isLeftPage) {
2 // Calculate factor for fitting page into rectangle
3 double scale = Math.min(CellWidth / bbox.width, CellHeight / bbox.height);
4 double groupWidth = bbox.width * scale;
5 double groupHeight = bbox.height * scale;
6
7 // Calculate x-value
8 double groupXPos = isLeftPage ? CellLeft + (CellWidth - groupWidth) / 2 :
9 CellRight + (CellWidth - groupWidth) / 2;
10
11 // Calculate y-value
12 double groupYPos = CellYPos + (CellHeight - groupHeight) / 2;
13
14 // Calculate rectangle
15 return new Rectangle(groupXPos, groupYPos, groupXPos + groupWidth, groupYPos + groupHeight);
16}
1private static void StampPageNumber(Document document, Font font, ContentGenerator generator, int pageNo,
2 boolean isLeftPage) throws ToolboxException, IOException {
3 // Create text object
4 Text text = Text.create(document);
5
6 try (// Create text generator
7 TextGenerator textgenerator = new TextGenerator(text, font, 8, null)) {
8 String stampText = String.format("Page %d", pageNo);
9
10 // Get width of stamp text
11 double width = textgenerator.getWidth(stampText);
12
13 // Calculate position
14 double x = isLeftPage ? Border + 0.5 * CellWidth - width / 2 :
15 2 * Border + 1.5 * CellWidth - width / 2;
16 double y = Border;
17
18 // Move to position
19 textgenerator.moveTo(new Point(x, y));
20
21 // Add page number
22 textgenerator.show(stampText);
23 }
24
25 // Paint the positioned text
26 generator.paintText(text);
27}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def compute_target_rect(bbox: Size, is_left_page: bool) -> Rectangle:
2 # Calculate factor for fitting page into rectangle
3 scale = min(cell_width / bbox.width, cell_height / bbox.height)
4 group_width = bbox.width * scale
5 group_height = bbox.height * scale
6
7 # Calculate x-value
8 group_x_pos = cell_left + (cell_width - group_width) / 2 if is_left_page else cell_right + (cell_width - group_width) / 2
9
10 # Calculate y-value
11 group_y_pos = cell_y_pos + (cell_height - group_height) / 2
12
13 # Calculate rectangle
14 return Rectangle(
15 left=group_x_pos,
16 bottom=group_y_pos,
17 right=group_x_pos + group_width,
18 top=group_y_pos + group_height,
19 )
1def stamp_page_number(document: Document, font: Font, generator: ContentGenerator, page_no: int, is_left_page: bool):
2 # Create text object
3 text = Text.create(document)
4
5 # Create text generator
6 with TextGenerator(text, font, 8.0, None) as text_generator:
7 stamp_text = f"Page {page_no}"
8
9 # Get width of stamp text
10 width = text_generator.get_width(stamp_text)
11
12 # Calculate position
13 x = border + 0.5 * cell_width - width / 2 if is_left_page else 2 * border + 1.5 * cell_width - width / 2
14 y = border
15
16 # Move to position
17 text_generator.move_to(Point(x=x, y=y))
18
19 # Add page number
20 text_generator.show(stamp_text)
21
22 # Paint the positioned text
23 generator.paint_text(text)
1def create_booklet(in_pages: PageList, out_doc: Document, out_pages: PageList, left_page_index: int, right_page_index: int, font: Font):
2 # Define page copy options
3 copy_options = PageCopyOptions()
4
5 # Create page object
6 out_page = Page.create(out_doc, page_size)
7
8 # Create content generator
9 with ContentGenerator(out_page.content, False) as generator:
10 # Left page
11 if left_page_index < len(in_pages):
12 # Copy page from input to output
13 left_page = in_pages[left_page_index]
14 left_group = Group.copy_from_page(out_doc, left_page, copy_options)
15
16 # Paint group into target rectangle
17 generator.paint_group(left_group, compute_target_rect(left_group.size, True), None)
18
19 # Add page number to page
20 stamp_page_number(out_doc, font, generator, left_page_index + 1, True)
21
22 # Right page
23 if right_page_index < len(in_pages):
24 # Copy page from input to output
25 right_page = in_pages[right_page_index]
26 right_group = Group.copy_from_page(out_doc, right_page, copy_options)
27
28 # Paint group on the calculated rectangle
29 generator.paint_group(right_group, compute_target_rect(right_group.size, False), None)
30
31 # Add page number to page
32 stamp_page_number(out_doc, font, generator, right_page_index + 1, False)
33
34 # Add page to output document
35 out_pages.append(out_page)
Fit pages to specific page format
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Copy all pages
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
33 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
34 szErrorBuff, Ptx_GetLastError());
35for (int iPage = 0; iPage < PtxPdf_PageList_GetCount(pInPageList); iPage++)
36{
37 TPtxGeomReal_Size pageSize;
38 TPtxGeomReal_Size rotatedSize;
39 BOOL bRotate;
40
41 pInPage = PtxPdf_PageList_Get(pInPageList, iPage);
42 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPage, _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
43
44 pOutPage = NULL;
45 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_GetSize(pInPage, &pageSize), _T("%s (ErrorCode: 0x%08x).\n"),
46 szErrorBuff, Ptx_GetLastError());
47
48 bRotate = bAllowRotate && (pageSize.dHeight >= pageSize.dWidth) != (targetSize.dHeight >= targetSize.dWidth);
49 if (bRotate)
50 {
51 rotatedSize.dWidth = pageSize.dHeight;
52 rotatedSize.dHeight = pageSize.dHeight;
53 }
54 else
55 {
56 rotatedSize = pageSize;
57 }
58
59 if (rotatedSize.dWidth == targetSize.dWidth && rotatedSize.dHeight == targetSize.dWidth)
60 {
61 // If size is correct, copy page only
62 pOutPage = PtxPdf_Page_Copy(pOutDoc, pInPage, pCopyOptions);
63 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
64 _T("Failed to copy pages from input to output. %s (ErrorCode: 0x%08x).\n"),
65 szErrorBuff, Ptx_GetLastError());
66
67 if (bRotate)
68 {
69 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_Rotate(pOutPage, ePtxGeom_Rotation_Clockwise),
70 _T("Failed to rotate page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
71 Ptx_GetLastError());
72 }
73 }
74 else
75 {
76 TPtxPdfContent_Group* pGroup = NULL;
77 TPtxPdfContent_Content* pContent = NULL;
78 TPtxGeomReal_AffineTransform transform;
79 TPtxGeomReal_Point position;
80 TPtxGeomReal_Point point;
81
82 // Create a new page of correct size and fit existing page onto it
83 pOutPage = PtxPdf_Page_Create(pOutDoc, &targetSize);
84 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to create a new page. %s (ErrorCode: 0x%08x).\n"),
85 szErrorBuff, Ptx_GetLastError());
86
87 // Copy page as group
88 pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
89 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGroup, _T("Failed to copy page as group. %s (ErrorCode: 0x%08x).\n"),
90 szErrorBuff, Ptx_GetLastError());
91
92 // Calculate scaling and position of group
93 double scale = MIN(targetSize.dWidth / rotatedSize.dWidth, targetSize.dHeight / rotatedSize.dHeight);
94
95 // Calculate position
96 position.dX = (targetSize.dWidth - pageSize.dWidth * scale) / 2;
97 position.dY = (targetSize.dHeight - pageSize.dHeight * scale) / 2;
98
99 pContent = PtxPdf_Page_GetContent(pOutPage);
100
101 // Create content generator
102 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
103 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator,
104 _T("Failed to create a content generator. %s (ErrorCode: 0x%08x).\n"),
105 szErrorBuff, Ptx_GetLastError());
106
107 // Calculate and apply transformation
108 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxGeomReal_AffineTransform_GetIdentity(&transform),
109 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
110 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
111 PtxGeomReal_AffineTransform_Translate(&transform, position.dX, position.dY),
112 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
113 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxGeomReal_AffineTransform_Scale(&transform, scale, scale),
114 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
115
116 point.dX = pageSize.dWidth / 2.0;
117 point.dY = pageSize.dHeight / 2.0;
118
119 // Rotate input file
120 if (bRotate)
121 {
122 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxGeomReal_AffineTransform_Rotate(&transform, 90, &point),
123 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
124 }
125 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_Transform(pGenerator, &transform),
126 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
127
128 // Paint form
129 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, NULL, NULL),
130 _T("Failed to paint the group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
131 Ptx_GetLastError());
132
133 PtxPdfContent_ContentGenerator_Close(pGenerator);
134 pGenerator = NULL;
135
136 if (pGenerator != NULL)
137 Ptx_Release(pGenerator);
138 if (pGroup != NULL)
139 Ptx_Release(pGroup);
140 }
141
142 // Add page to output document
143 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
144 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
145 szErrorBuff, Ptx_GetLastError());
146
147 if (pOutPage != NULL)
148 {
149 Ptx_Release(pOutPage);
150 pOutPage = NULL;
151 }
152
153 if (pInPage != NULL)
154 {
155 Ptx_Release(pInPage);
156 pInPage = NULL;
157 }
158}
159
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy pages
16 foreach (Page inPage in inDoc.Pages)
17 {
18 Page outPage = null;
19 Size pageSize = inPage.Size;
20
21 bool rotate = AllowRotate &&
22 (pageSize.Height >= pageSize.Width) != (TargetSize.Height >= TargetSize.Width);
23 Size rotatedSize = pageSize;
24
25 if (rotate)
26 rotatedSize = new Size { Width = pageSize.Height, Height = pageSize.Width };
27
28 if (rotatedSize.Width == TargetSize.Width && rotatedSize.Height == TargetSize.Width)
29 {
30 // If size is correct, copy page only
31 outPage = Page.Copy(outDoc, inPage, copyOptions);
32
33 if (rotate)
34 outPage.Rotate(Rotation.Clockwise);
35 }
36 else
37 {
38 // Create new page of correct size and fit existing page onto it
39 outPage = Page.Create(outDoc, TargetSize);
40
41 // Copy page as group
42 Group group = Group.CopyFromPage(outDoc, inPage, copyOptions);
43 // Calculate scaling and position of group
44 double scale = Math.Min(TargetSize.Width / rotatedSize.Width,
45 TargetSize.Height / rotatedSize.Height);
46
47 // Calculate position
48 Point position = new Point
49 {
50 X = (TargetSize.Width - pageSize.Width * scale) / 2,
51 Y = (TargetSize.Height - pageSize.Height * scale) / 2
52 };
53
54 // Create content generator
55 using ContentGenerator generator = new ContentGenerator(outPage.Content, false);
56
57 // Calculate and apply transformation
58 AffineTransform transform = AffineTransform.Identity;
59 transform.Translate(position.X, position.Y);
60 transform.Scale(scale, scale);
61
62 Point point = new Point()
63 {
64 X = pageSize.Width / 2.0,
65 Y = pageSize.Height / 2.0
66 };
67
68 // Rotate input file
69 if (rotate)
70 transform.Rotate(90, point);
71 generator.Transform(transform);
72
73 // Paint group
74 generator.PaintGroup(group, null, null);
75 }
76 // Add page to output document
77 outDoc.Pages.Add(outPage);
78 }
79}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Define page copy options
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy pages
15 for (Page inPage : inDoc.getPages()) {
16 Page outPage = null;
17 Size pageSize = inPage.getSize();
18
19 boolean rotate = AllowRotate &&
20 (pageSize.height >= pageSize.width) != (TargetHeight >= TargetWidth);
21 Size rotatedSize = pageSize;
22
23 if (rotate)
24 rotatedSize = new Size(pageSize.height, pageSize.width);
25
26 if (rotatedSize.width == TargetWidth && rotatedSize.height == TargetWidth) {
27 // If size is correct, copy page only
28 outPage = Page.copy(outDoc, inPage, copyOptions);
29
30 if (rotate)
31 outPage.rotate(Rotation.CLOCKWISE);
32 } else {
33 // Create new page of correct size and fit existing page onto it
34 outPage = Page.create(outDoc, new Size(TargetWidth, TargetHeight));
35
36 // Copy page as group
37 Group group = Group.copyFromPage(outDoc, inPage, copyOptions);
38 // Calculate scaling and position of group
39 double scale = Math.min(TargetWidth / rotatedSize.width,
40 TargetHeight / rotatedSize.height);
41
42 // Calculate position
43 Point position = new Point(
44 (TargetWidth - pageSize.width * scale) / 2,
45 (TargetHeight - pageSize.height * scale) / 2);
46
47 try(// Create content generator
48 ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
49 // Calculate and apply transformation
50 AffineTransform transform = AffineTransform.getIdentity();
51 transform.translate(position.x, position.y);
52 transform.scale(scale, scale);
53
54 Point point = new Point(pageSize.width / 2.0, pageSize.height / 2.0);
55
56 // Rotate input file
57 if (rotate)
58 transform.rotate(90, point);
59 generator.transform(transform);
60
61 // Paint group
62 generator.paintGroup(group, null, null);
63 }
64 }
65 // Add page to output document
66 outDoc.getPages().add(outPage);
67 }
68 }
69}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def scale_pages_to_fit(in_doc: Document, out_doc: Document):
2 copy_options = PageCopyOptions()
3
4 # Copy pages
5 for in_page in in_doc.pages:
6 page_size = in_page.size
7 rotate = (
8 ALLOW_ROTATE
9 and (page_size.height >= page_size.width) != (TARGET_SIZE.height >= TARGET_SIZE.width)
10 )
11
12 rotated_size = Size(
13 width=page_size.height, height=page_size.width
14 ) if rotate else page_size
15
16 if rotated_size.width == TARGET_SIZE.width and rotated_size.height == TARGET_SIZE.height:
17 # If size is correct, copy page only
18 out_page = Page.copy(out_doc, in_page, copy_options)
19
20 if rotate:
21 out_page.rotate(90) # Clockwise rotation
22 else:
23 # Create new page of correct size and fit existing page onto it
24 out_page = Page.create(out_doc, TARGET_SIZE)
25
26 # Copy page as group
27 group = Group.copy_from_page(out_doc, in_page, copy_options)
28 # Calculate scaling and position of group
29 scale = min(TARGET_SIZE.width / rotated_size.width, TARGET_SIZE.height / rotated_size.height)
30
31 # Calculate position
32 position = Point(
33 x=(TARGET_SIZE.width - page_size.width * scale) / 2,
34 y=(TARGET_SIZE.height - page_size.height * scale) / 2,
35 )
36
37 # Create content generator
38 with ContentGenerator(out_page.content, False) as generator:
39
40 # Calculate and apply transformation
41 transform = AffineTransform.get_identity()
42 transform.translate(position.x, position.y)
43 transform.scale(scale, scale)
44
45 # Rotate input file
46 if rotate:
47 center_point = Point(x=page_size.width / 2, y=page_size.height / 2)
48 transform.rotate(90, center_point)
49
50 # Paint group
51 generator.transform(transform)
52 generator.paint_group(group, None, None)
53
54 # Add the page to the output document
55 out_doc.pages.append(out_page)
Place multiple pages on one page
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Copy all pages
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPageList,
33 _T("Failed to get pages of the output document. %s (ErrorCode: 0x%08x).\n"),
34 szErrorBuff, Ptx_GetLastError());
35int nPageCount = 0;
36for (int iPage = 0; iPage < PtxPdf_PageList_GetCount(pInPageList); iPage++)
37{
38 pInPage = PtxPdf_PageList_Get(pInPageList, iPage);
39
40 if (nPageCount == nNx * nNy)
41 {
42 // Add to output document
43 PtxPdfContent_ContentGenerator_Close(pGenerator);
44 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
45 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
46 szErrorBuff, Ptx_GetLastError());
47 Ptx_Release(pOutPage);
48 pOutPage = NULL;
49 nPageCount = 0;
50 }
51 if (pOutPage == NULL)
52 {
53 // Create a new output page
54 pOutPage = PtxPdf_Page_Create(pOutDoc, &PageSize);
55 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage,
56 _T("Failed to create a new output page. %s (ErrorCode: 0x%08x).\n"),
57 szErrorBuff, Ptx_GetLastError());
58 TPtxPdfContent_Content* pContent = PtxPdf_Page_GetContent(pOutPage);
59 pGenerator = PtxPdfContent_ContentGenerator_New(pContent, FALSE);
60 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pGenerator,
61 _T("Failed to create content generator. %s (ErrorCode: 0x%08x).\n"),
62 szErrorBuff, Ptx_GetLastError());
63 }
64
65 // Get area where group has to be
66 int x = nPageCount % nNx;
67 int y = nNy - (nPageCount / nNx) - 1;
68
69 // Calculate cell size
70 TPtxGeomReal_Size cellSize;
71 cellSize.dWidth = (PageSize.dWidth - ((nNx + 1) * dBorder)) / nNx;
72 cellSize.dHeight = (PageSize.dHeight - ((nNy + 1) * dBorder)) / nNy;
73
74 // Calculate cell position
75 TPtxGeomReal_Point cellPosition;
76 cellPosition.dX = dBorder + x * (cellSize.dWidth + dBorder);
77 cellPosition.dY = dBorder + y * (cellSize.dHeight + dBorder);
78
79 // Copy page group from input to output
80 pGroup = PtxPdfContent_Group_CopyFromPage(pOutDoc, pInPage, pCopyOptions);
81 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(
82 pGroup, _T("Failed to copy page group from input to output. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
83 Ptx_GetLastError());
84
85 // Calculate group position
86 TPtxGeomReal_Size groupSize;
87 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdfContent_Group_GetSize(pGroup, &groupSize),
88 _T("%s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
89 double dScale = MIN(cellSize.dWidth / groupSize.dWidth, cellSize.dHeight / groupSize.dHeight);
90
91 // Calculate target size
92 TPtxGeomReal_Size targetSize;
93 targetSize.dWidth = groupSize.dWidth * dScale;
94 targetSize.dHeight = groupSize.dHeight * dScale;
95
96 // Calculate position
97 TPtxGeomReal_Point targetPos;
98 targetPos.dX = cellPosition.dX + ((cellSize.dWidth - targetSize.dWidth) / 2);
99 targetPos.dY = cellPosition.dY + ((cellSize.dHeight - targetSize.dHeight) / 2);
100
101 // Calculate rectangle
102 TPtxGeomReal_Rectangle targetRect;
103 targetRect.dLeft = targetPos.dX;
104 targetRect.dBottom = targetPos.dY;
105 targetRect.dRight = targetPos.dX + targetSize.dWidth;
106 targetRect.dTop = targetPos.dY + targetSize.dHeight;
107
108 // Add group to page
109 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(
110 PtxPdfContent_ContentGenerator_PaintGroup(pGenerator, pGroup, &targetRect, NULL),
111 _T("Failed to paint the group. %s (ErrorCode: 0x%08x).\n"), szErrorBuff, Ptx_GetLastError());
112
113 if (pGroup != NULL)
114 {
115 Ptx_Release(pGroup);
116 pGroup = NULL;
117 }
118 if (pInPage != NULL)
119 {
120 Ptx_Release(pInPage);
121 pInPage = NULL;
122 }
123
124 nPageCount++;
125}
126
127// Add partially filled page
128if (pOutPage != NULL)
129{
130 PtxPdfContent_ContentGenerator_Close(pGenerator);
131 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_Add(pOutPageList, pOutPage),
132 _T("Failed to add page to output document. %s (ErrorCode: 0x%08x).\n"),
133 szErrorBuff, Ptx_GetLastError());
134 Ptx_Release(pOutPage);
135 pOutPage = NULL;
136}
137
138
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 // Create output document
6 using Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite);
7 using Document outDoc = Document.Create(outStream, inDoc.Conformance, null);
8 PageList outPages = outDoc.Pages;
9 int pageCount = 0;
10 ContentGenerator generator = null;
11 Page outPage = null;
12
13 // Copy document-wide data
14 CopyDocumentData(inDoc, outDoc);
15
16 // Copy all pages from input document
17 foreach (Page inPage in inDoc.Pages)
18 {
19 if (pageCount == Nx * Ny)
20 {
21 // Add to output document
22 generator.Dispose();
23 outPages.Add(outPage);
24 outPage = null;
25 pageCount = 0;
26 }
27 if (outPage == null)
28 {
29 // Create a new output page
30 outPage = Page.Create(outDoc, PageSize);
31 generator = new ContentGenerator(outPage.Content, false);
32 }
33
34 // Get area where group has to be
35 int x = pageCount % Nx;
36 int y = Ny - (pageCount / Nx) - 1;
37
38 // Compute cell size
39 Size cellSize = new Size
40 {
41 Width = (PageSize.Width - ((Nx + 1) * Border)) / Nx,
42 Height = (PageSize.Height - ((Ny + 1) * Border)) / Ny
43 };
44
45 // Compute cell position
46 Point cellPosition = new Point
47 {
48 X = Border + x * (cellSize.Width + Border),
49 Y = Border + y * (cellSize.Height + Border)
50 };
51
52 // Define page copy options
53 PageCopyOptions copyOptions = new PageCopyOptions();
54
55 // Copy page as group from input to output
56 Group group = Group.CopyFromPage(outDoc, inPage, copyOptions);
57
58 // Compute group position
59 Size groupSize = group.Size;
60 double scale = Math.Min(cellSize.Width / groupSize.Width,
61 cellSize.Height / groupSize.Height);
62
63 // Compute target size
64 Size targetSize = new Size
65 {
66 Width = groupSize.Width * scale,
67 Height = groupSize.Height * scale
68 };
69
70 // Compute position
71 Point targetPos = new Point
72 {
73 X = cellPosition.X + ((cellSize.Width - targetSize.Width) / 2),
74 Y = cellPosition.Y + ((cellSize.Height - targetSize.Height) / 2)
75 };
76
77 // Compute rectangle
78 Rectangle targetRect = new Rectangle
79 {
80 Left = targetPos.X,
81 Bottom = targetPos.Y,
82 Right = targetPos.X + targetSize.Width,
83 Top = targetPos.Y + targetSize.Height
84 };
85
86 // Add group to page
87 generator.PaintGroup(group, targetRect, null);
88 pageCount++;
89 }
90 // Add page
91 if (outPage != null)
92 {
93 generator.Dispose();
94 outPages.Add(outPage);
95 }
96}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4 try (
5 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
6 try (// Create output document
7 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
8 PageList outPages = outDoc.getPages();
9 int pageCount = 0;
10 ContentGenerator generator = null;
11 Page outPage = null;
12
13 // A4 portrait
14 Size pageSize = new Size(595, 842);
15
16 // Copy document-wide data
17 copyDocumentData(inDoc, outDoc);
18
19 // Copy pages
20 for (Page inPage : inDoc.getPages()) {
21
22 if (pageCount == Nx * Ny) {
23 // Add to output document
24 generator.close();
25 outPages.add(outPage);
26 outPage = null;
27 pageCount = 0;
28 }
29 if (outPage == null) {
30 // Create a new output page
31 outPage = Page.create(outDoc, pageSize);
32 generator = new ContentGenerator(outPage.getContent(), false);
33 }
34
35 // Get area where group has to be
36 int x = pageCount % Nx;
37 int y = Ny - (pageCount / Nx) - 1;
38
39 // Calculate cell size
40 Size cellSize = new Size((pageSize.width - ((Nx + 1) * Border)) / Nx,
41 (pageSize.height - ((Ny + 1) * Border)) / Ny);
42
43 // Calculate cell position
44 Point cellPosition = new Point(Border + x * (cellSize.width + Border),
45 Border + y * (cellSize.height + Border));
46
47 // Set copy option
48 PageCopyOptions copyOptions = new PageCopyOptions();
49
50 // Copy page group from input to output
51 Group group = Group.copyFromPage(outDoc, inPage, copyOptions);
52
53 // Calculate group position
54 Size groupSize = group.getSize();
55 double scale = Math.min(cellSize.width / groupSize.width,
56 cellSize.height / groupSize.height);
57
58 // Calculate target size
59 Size targetSize = new Size(groupSize.width * scale, groupSize.height * scale);
60
61 // Calculate position
62 Point targetPos = new Point(cellPosition.x + ((cellSize.width - targetSize.width) / 2),
63 cellPosition.y + ((cellSize.height - targetSize.height) / 2));
64
65 // Calculate rectangle
66 Rectangle targetRect = new Rectangle(targetPos.x, targetPos.y,
67 targetPos.x + targetSize.width, targetPos.y + targetSize.height);
68
69 // Add group to page
70 generator.paintGroup(group, targetRect, null);
71
72 pageCount++;
73 }
74 // Add page
75 if (outPage != null) {
76 generator.close();
77 outPages.add(outPage);
78 }
79 }
80 }
81}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1
2
3# Open input document
4with io.FileIO(input_file_path, 'rb') as in_stream:
5 with Document.open(in_stream, None) as input_document:
6
7 # Create output document
8 with io.FileIO(output_file_path, 'wb+') as output_stream:
9 with Document.create(output_stream, input_document.conformance, None) as output_document:
10 out_pages = output_document.pages
11 page_count = 0
12 generator = None
13 out_page = None
14
15 # Copy document-wide data
16 copy_document_data(input_document, output_document)
17
18 # Copy all pages from input document
19 for in_page in input_document.pages:
20 if page_count == nx * ny:
21 # Add to output document
22 generator.__exit__(None, None, None)
23 out_pages.append(out_page)
24 out_page = None
25 page_count = 0
26 if out_page is None:
27 # Create a new output page
28 out_page = Page.create(output_document, page_size)
29 generator = ContentGenerator(out_page.content, False)
30
31 # Get area where group has to be (// calculates the floor of the division)
32 x = int(page_count % nx)
33 y = int(ny - (page_count // nx) - 1)
34
35 # Compute cell size
36 cell_width = (page_size.width - ((nx + 1) * border)) / nx
37 cell_height = (page_size.height - ((ny + 1) * border)) / ny
38
39 # Compute cell position
40 cell_x = border + x * (cell_width + border)
41 cell_y = border + y * (cell_height + border)
42
43 # Define page copy options
44 copy_options = PageCopyOptions()
45
46 # Copy page as group from input to output
47 group = Group.copy_from_page(output_document, in_page, copy_options)
48
49 # Compute group position
50 group_size = group.size
51 scale = min(cell_width / group_size.width, cell_height / group_size.height)
52
53 # Compute target size
54 target_width = group_size.width * scale
55 target_height = group_size.height * scale
56
57 # Compute position
58 target_x = cell_x + ((cell_width - target_width) / 2)
59 target_y = cell_y + ((cell_height - target_height) / 2)
60
61 # Compute rectangle
62 target_rect = Rectangle()
63 target_rect.left = target_x
64 target_rect.bottom = target_y
65 target_rect.right = target_x + target_width
66 target_rect.top = target_y + target_height
67
68 # Add group to page
69 generator.paint_group(group, target_rect, None)
70 page_count += 1
71
72 # Add page
73 if out_page:
74 generator.__exit__(None, None, None)
75 out_pages.append(out_page)
76
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Set page orientation
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Create output document
10pOutStream = _tfopen(szOutPath, _T("wb+"));
11GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
12PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
13iConformance = PtxPdf_Document_GetConformance(pInDoc);
14pOutDoc = PtxPdf_Document_Create(&outDescriptor, &iConformance, NULL);
15GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutDoc, _T("Output file \"%s\" cannot be created. %s (ErrorCode: 0x%08x).\n"),
16 szOutPath, szErrorBuff, Ptx_GetLastError());
17
18// Copy document-wide data
19GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(copyDocumentData(pInDoc, pOutDoc),
20 _T("Failed to copy document-wide data. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
21 Ptx_GetLastError());
22
23// Configure copy options
24pCopyOptions = PtxPdf_PageCopyOptions_New();
25
26// Copy all pages
27pInPageList = PtxPdf_Document_GetPages(pInDoc);
28GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
29 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
30 szErrorBuff, Ptx_GetLastError());
31pCopiedPages = PtxPdf_PageList_Copy(pOutDoc, pInPageList, pCopyOptions);
32GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCopiedPages, _T("Failed to copy pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
33 Ptx_GetLastError());
34
35// Rotate given pages by 90 degrees
36for (int i = 0; i < ARRAY_SIZE(aPageNumbers); i++)
37{
38 pOutPage = PtxPdf_PageList_Get(pCopiedPages, aPageNumbers[i] - 1);
39 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pOutPage, _T("Failed to get copied page. %s (ErrorCode: 0x%08x).\n"),
40 szErrorBuff, Ptx_GetLastError());
41 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_Page_Rotate(pOutPage, ePtxGeom_Rotation_Clockwise),
42 _T("Failed to rotate page. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
43 Ptx_GetLastError());
44}
45
46// Add pages to output document
47pOutPageList = PtxPdf_Document_GetPages(pOutDoc);
48GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(PtxPdf_PageList_AddRange(pOutPageList, pCopiedPages),
49 _T("Failed to add copied pages. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
50 Ptx_GetLastError());
51
1int copyDocumentData(TPtxPdf_Document* pInDoc, TPtxPdf_Document* pOutDoc)
2{
3 TPtxPdf_FileReferenceList* pInFileRefList;
4 TPtxPdf_FileReferenceList* pOutFileRefList;
5
6 // Output intent
7 if (PtxPdf_Document_GetOutputIntent(pInDoc) != NULL)
8 if (PtxPdf_Document_SetOutputIntent(pOutDoc, PtxPdfContent_IccBasedColorSpace_Copy(
9 pOutDoc, PtxPdf_Document_GetOutputIntent(pInDoc))) == FALSE)
10 return FALSE;
11
12 // Metadata
13 if (PtxPdf_Document_SetMetadata(pOutDoc, PtxPdf_Metadata_Copy(pOutDoc, PtxPdf_Document_GetMetadata(pInDoc))) ==
14 FALSE)
15 return FALSE;
16
17 // Viewer settings
18 if (PtxPdf_Document_SetViewerSettings(
19 pOutDoc, PtxPdfNav_ViewerSettings_Copy(pOutDoc, PtxPdf_Document_GetViewerSettings(pInDoc))) == FALSE)
20 return FALSE;
21
22 // Associated files (for PDF/A-3 and PDF 2.0 only)
23 pInFileRefList = PtxPdf_Document_GetAssociatedFiles(pInDoc);
24 pOutFileRefList = PtxPdf_Document_GetAssociatedFiles(pOutDoc);
25 if (pInFileRefList == NULL || pOutFileRefList == NULL)
26 return FALSE;
27 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
28 if (PtxPdf_FileReferenceList_Add(
29 pOutFileRefList,
30 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
31 return FALSE;
32
33 // Plain embedded files
34 pInFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pInDoc);
35 pOutFileRefList = PtxPdf_Document_GetPlainEmbeddedFiles(pOutDoc);
36 if (pInFileRefList == NULL || pOutFileRefList == NULL)
37 return FALSE;
38 for (int iFileRef = 0; iFileRef < PtxPdf_FileReferenceList_GetCount(pInFileRefList); iFileRef++)
39 if (PtxPdf_FileReferenceList_Add(
40 pOutFileRefList,
41 PtxPdf_FileReference_Copy(pOutDoc, PtxPdf_FileReferenceList_Get(pInFileRefList, iFileRef))) == FALSE)
42 return FALSE;
43
44 return TRUE;
45}
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4
5// Create output document
6using (Stream outFs = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
7using (Document outDoc = Document.Create(outFs, inDoc.Conformance, null))
8{
9 // Copy document-wide data
10 CopyDocumentData(inDoc, outDoc);
11
12 // Define page copy options
13 PageCopyOptions copyOptions = new PageCopyOptions();
14
15 // Copy all pages
16 PageList copiedPages = PageList.Copy(outDoc, inDoc.Pages, copyOptions);
17
18 // Rotate selected pages by 90 degrees
19 foreach (var pageNumber in pageNumbers)
20 {
21 copiedPages[pageNumber - 1].Rotate(Rotation.Clockwise);
22 }
23
24 // Add pages to output document
25 outDoc.Pages.AddRange(copiedPages);
26}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW)) {
5 try (// Create output document
6 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
7
8 // Copy document-wide data
9 copyDocumentData(inDoc, outDoc);
10
11 // Set copy options and flatten annotations, form fields and signatures
12 PageCopyOptions copyOptions = new PageCopyOptions();
13
14 // Copy all pages
15 PageList copiedPages = PageList.copy(outDoc, inDoc.getPages(), copyOptions);
16
17 // Rotate selected pages by 90 degrees
18 for (int pageNumber : pageNumbers) {
19 copiedPages.get(pageNumber - 1).rotate(Rotation.CLOCKWISE);
20 }
21
22 // Add pages to output document
23 outDoc.getPages().addAll(copiedPages);
24 }
25}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Metadata
9 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
10
11 // Viewer settings
12 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
13
14 // Associated files (for PDF/A-3 and PDF 2.0 only)
15 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
16 for (FileReference inFileRef : inDoc.getAssociatedFiles())
17 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
18
19 // Plain embedded files
20 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
21 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
22 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
23}
1
2
3# Open input document
4with io.FileIO(input_path, "rb") as in_stream:
5 with Document.open(in_stream, None) as in_doc:
6
7 # Create output document
8 with io.FileIO(output_path, "wb+") as out_stream:
9 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
10
11 # Copy document-wide data
12 copy_document_data(in_doc, out_doc)
13
14 # Define page copy options
15 page_copy_options = PageCopyOptions()
16
17 # Copy all pages
18 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
19
20 # Rotate selected pages by 90 degrees
21 for page_number in page_numbers:
22 copied_pages[int(page_number) - 1].rotate(Rotation.CLOCKWISE)
23
24 # Add pages to output document
25 out_doc.pages.extend(copied_pages)
26
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
Information Extraction
Embed files into a PDF
1
2// Open input document
3using (FileStream inStream = new FileStream(input, FileMode.Open, FileAccess.Read))
4using (Document inDoc = Document.Open(inStream, null))
5
6// Create output document
7using (FileStream outStream = new FileStream(output, FileMode.Create, FileAccess.ReadWrite))
8using (Document outDoc = Document.Create(outStream, inDoc.Conformance, null))
9{
10 // Copy document-wide data
11 CopyDocumentData(inDoc, outDoc);
12
13 // Define page copy options
14 PageCopyOptions copyOptions = new PageCopyOptions();
15
16 // Copy all pages
17 PageList inPageRange = inDoc.Pages.GetRange(0, inDoc.Pages.Count);
18 PageList copiedPages = PageList.Copy(outDoc, inPageRange, copyOptions);
19 outDoc.Pages.AddRange(copiedPages);
20
21 EmbedFile(outDoc, new FileInfo(fileToEmbed), page);
22}
1private static void CopyDocumentData(Document inDoc, Document outDoc)
2{
3 // Copy document-wide data
4
5 // Output intent
6 if (inDoc.OutputIntent != null)
7 outDoc.OutputIntent = IccBasedColorSpace.Copy(outDoc, inDoc.OutputIntent);
8
9 // Metadata
10 outDoc.Metadata = Metadata.Copy(outDoc, inDoc.Metadata);
11
12 // Viewer settings
13 outDoc.ViewerSettings = ViewerSettings.Copy(outDoc, inDoc.ViewerSettings);
14
15 // Associated files (for PDF/A-3 and PDF 2.0 only)
16 FileReferenceList outAssociatedFiles = outDoc.AssociatedFiles;
17 foreach (FileReference inFileRef in inDoc.AssociatedFiles)
18 outAssociatedFiles.Add(FileReference.Copy(outDoc, inFileRef));
19
20 // Plain embedded files
21 FileReferenceList outEmbeddedFiles = outDoc.PlainEmbeddedFiles;
22 foreach (FileReference inFileRef in inDoc.PlainEmbeddedFiles)
23 outEmbeddedFiles.Add(FileReference.Copy(outDoc, inFileRef));
24}
1private static void EmbedFile(Document outputDoc, FileSystemInfo fileToEmbed, int pageNumber)
2{
3 // create file stream to read the file to embed
4 using (FileStream fileStream = new FileStream(fileToEmbed.FullName, FileMode.Open, FileAccess.Read))
5 {
6 // create a file type depending on the file ending (e.g. "application/pdf")
7 string fileEnding = fileToEmbed.Name.Substring(fileToEmbed.Name.LastIndexOf("."));
8 string type = "application/" + fileEnding;
9
10 // get the modified date from the file
11 DateTime dateTime = fileToEmbed.LastWriteTime;
12
13 // create a new FileReference
14 FileReference fr = FileReference.Create(outputDoc, fileStream, fileToEmbed.Name, type, "", dateTime);
15
16 // if a page is set, add a FileAttachment annotation to that page
17 // otherwise, attach the file to the document
18 if (pageNumber > 0 && pageNumber <= outputDoc.Pages.Count)
19 {
20 // get the page to create the annotation on
21 Page page = outputDoc.Pages[pageNumber - 1];
22
23 // Get the color space
24 ColorSpace colorSpace = ColorSpace.CreateProcessColorSpace(outputDoc, ProcessColorSpaceType.Rgb);
25
26 // Choose the RGB color value
27 double[] color = { 1.0, 0.0, 0.0 };
28 Transparency transparency = new Transparency(1);
29
30 // Create paint object
31 Paint paint = Paint.Create(outputDoc, colorSpace, color, transparency);
32
33 // put the annotation in the center of the page
34 Point point = new Point
35 {
36 X= page.Size.Width / 2,
37 Y= page.Size.Height / 2
38 };
39
40 // create a FileReference annotation and attach it to a page so the FireReference is visible on that page
41 FileAttachment fa = FileAttachment.Create(outputDoc, point, fr, paint);
42
43 // add FileAttachment annotation to page
44 page.Annotations.Add(fa);
45 }
46 else
47 {
48 // attach it to the document
49 outputDoc.PlainEmbeddedFiles.Add(fr);
50 }
51 }
52}
1try (// Open input document
2 FileStream inStream = new FileStream(input, Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4
5 // Create output document
6 FileStream outStream = new FileStream(output, Mode.READ_WRITE_NEW);
7 Document outDoc = Document.create(outStream, inDoc.getConformance(), null);
8 )
9{
10 // Copy document-wide data
11 copyDocumentData(inDoc, outDoc);
12
13 // Define page copy options
14 PageCopyOptions copyOptions = new PageCopyOptions();
15
16 // Copy all pages
17 PageList inPageRange = inDoc.getPages().subList(0, inDoc.getPages().size());
18 PageList copiedPages = PageList.copy(outDoc, inPageRange, copyOptions);
19 outDoc.getPages().addAll(copiedPages);
20
21 embedFile(outDoc, new File(fileToEmbed), page);
22}
1private static void copyDocumentData(Document inDoc, Document outDoc) throws ToolboxException, IOException {
2 // Copy document-wide data (excluding metadata)
3
4 // Output intent
5 if (inDoc.getOutputIntent() != null)
6 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
7
8 // Viewer settings
9 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
10
11 // Associated files (for PDF/A-3 and PDF 2.0 only)
12 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
13 for (FileReference inFileRef : inDoc.getAssociatedFiles())
14 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
15
16 // Plain embedded files
17 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
18 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles())
19 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
20}
1private static void embedFile(Document outputDoc, File fileToEmbed, int pageNumber) throws Exception
2{
3 try(
4 // create file stream to read the file to embed
5 FileStream fileStream = new FileStream(fileToEmbed, Mode.READ_ONLY);
6 )
7 {
8 // create a file type depending on the file ending (e.g. "application/pdf")
9 String fileEnding = fileToEmbed.getName().substring(fileToEmbed.getName().lastIndexOf("."));
10 String type = "application/" + fileEnding;
11
12 // get the modified date from the file
13 Instant instant = Instant.ofEpochMilli(fileToEmbed.lastModified());
14 ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, ZoneId.systemDefault());
15 OffsetDateTime dateTime = OffsetDateTime.from(zonedDateTime);
16
17 // create a new FileReference
18 FileReference fr = FileReference.create(outputDoc, fileStream, fileToEmbed.getName(), type, "", dateTime);
19
20 // if a page is set, add a FileAttachment annotation to that page
21 // otherwise, attach the file to the document
22 if(pageNumber > 0 && pageNumber <= outputDoc.getPages().size())
23 {
24 // get the page to create the annotation on
25 Page page = outputDoc.getPages().get(pageNumber - 1);
26
27 // Get the color space
28 ColorSpace colorSpace = ColorSpace.createProcessColorSpace(outputDoc, ProcessColorSpaceType.RGB);
29
30 // Choose the RGB color value
31 double[] color = { 1.0, 0.0, 0.0 };
32 Transparency transparency = new Transparency(1);
33
34 // Create paint object
35 Paint paint = Paint.create(outputDoc, colorSpace, color, transparency);
36
37 // put the annotation in the center of the page
38 Point point = new Point(page.getSize().getWidth() / 2, page.getSize().getHeight() / 2);
39
40 // create a FileReference annotation and attach it to a page so the FireReference is visible on that page
41 FileAttachment fa = FileAttachment.create(outputDoc, point, fr, paint);
42
43 // add FileAttachment annotation to the page
44 page.getAnnotations().add(fa);
45 }
46 else
47 {
48 // attach it to the document
49 outputDoc.getPlainEmbeddedFiles().add(fr);
50 }
51 }
52}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 # Copy document-wide data
3
4 # Output intent
5 if in_doc.output_intent is not None:
6 in_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
7
8 # Metadata
9 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
10
11 # Viewer settings
12 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
13
14 # Associated files (for PDF/A-3 and PDF 2.0 only)
15 outAssociatedFiles = out_doc.associated_files
16 for in_file_ref in in_doc.associated_files:
17 outAssociatedFiles.append(FileReference.copy(out_doc, in_file_ref))
18
19 # Plain embedded files
20 out_embedded_files = out_doc.plain_embedded_files
21 for in_file_ref in in_doc.plain_embedded_files:
22 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def embed_file(output_doc: Document, file_to_embed: str, page_number: int | None):
2 # Create file stream to read the file to embed
3 with open(file_to_embed, "rb") as file_stream:
4 # Create a file type depending on the file ending (e.g. "application/pdf")
5 file_to_embed_name = os.path.basename(file_to_embed)
6 file_type = "application/" + file_to_embed_name.split(".")[-1]
7
8 # Get the modified date from the file
9 last_modified = datetime.fromtimestamp(os.path.getmtime(file_to_embed))
10
11 # Create a new FileReference
12 file_ref = FileReference.create(output_doc, file_stream, file_to_embed_name, file_type, "", last_modified)
13
14 # If a page is set, add a FileAttachment annotation to that page
15 # otherwise, attach the file to the document
16 if page_number is not None and page_number > 0 and page_number <= len(output_doc.pages):
17 # Get the page to create the annotation on
18 page = output_doc.pages[page_number - 1]
19
20 # Get the color space
21 color_space = ColorSpace.create_process_color_space(output_doc, ProcessColorSpaceType.RGB)
22
23 # Choose the RGB color value
24 color = [1.0, 0.0, 0.0] # Red color
25 transparency = Transparency(1)
26
27 # Create paint object
28 paint = Paint.create(output_doc, color_space, color, transparency)
29
30 # Put the annotation in the center of the page
31 point = Point(x = page.size.width/2, y = page.size.height/2)
32
33 # Create a FileReference annotation and attach it to a page so the FireReference is visible on that page
34 annotation = FileAttachment.create(output_doc, point, file_ref, paint)
35
36 # Add the annotation to the page
37 page.annotations.append(annotation)
38 else:
39 # Attach the file to the document
40 output_doc.plain_embedded_files.append(file_ref)
Extract files embedded from a PDF
1
2// Open input document
3using (FileStream inStream = new FileStream(inputFile, FileMode.Open, FileAccess.Read))
4using (Document inDoc = Document.Open(inStream, null))
5{
6 FileReferenceList frList = inDoc.AllEmbeddedFiles;
7
8 foreach(FileReference fr in frList)
9 {
10 ExtractFile(fr, outputDir);
11 }
12}
1private static void ExtractFile(FileReference fr, String outputDir)
2{
3 using (FileStream outStream = new FileStream(outputDir + "/" + fr.Name, FileMode.Create, FileAccess.ReadWrite))
4 {
5 fr.Data.CopyTo(outStream);
6 }
7}
1try (// Open input document
2 FileStream inStream = new FileStream(inputFile, Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null);
4 )
5{
6 FileReferenceList frList = inDoc.getAllEmbeddedFiles();
7
8 for(FileReference fr: frList)
9 {
10 extractFile(fr, outputDir);
11 }
12}
1private static void extractFile(FileReference fr, String outputDir) throws Exception
2{
3 try(
4 FileStream outStream = new FileStream(outputDir + "/" + fr.getName(), Mode.READ_WRITE_NEW);
5 )
6 {
7 outStream.copy(fr.getData());
8 }
9}
1def copy_to_stream(data: io.IOBase, out_stream: io.IOBase, chunk_size: int = 4096):
2 """Copy data from an IO stream to another."""
3 while chunk := data.read(chunk_size):
4 out_stream.write(chunk)
1def extract_file(file_reference: FileReference, output_dir: str):
2 # Remove null characters
3 clean_file_name = file_reference.name.replace("\x00", "")
4 output_path = os.path.join(output_dir, clean_file_name)
5
6 if file_reference.data is None:
7 raise ValueError("The file_reference.data stream is None.")
8 if not file_reference.data.readable():
9 raise ValueError("The file_reference.data stream is not readable.")
10
11 # Ensure the output directory exists
12 os.makedirs(output_dir, exist_ok=True)
13
14 with io.FileIO(output_path, "wb") as out_file:
15 copy_to_stream(file_reference.data, out_file)
Extract all images and image masks from a PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Loop over all pages and extract images
10pInPageList = PtxPdf_Document_GetPages(pInDoc);
11GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInPageList,
12 _T("Failed to get the pages of the input document. %s (ErrorCode: 0x%08x).\n"),
13 szErrorBuff, Ptx_GetLastError());
14
15for (int iPageNo = 0; iPageNo < PtxPdf_PageList_GetCount(pInPageList); iPageNo++)
16{
17 pPage = PtxPdf_PageList_Get(pInPageList, iPageNo);
18 pContent = PtxPdf_Page_GetContent(pPage);
19 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pContent, _T("Failed to get content from page %d. %s (ErrorCode: 0x%08x).\n"),
20 iPageNo + 1, szErrorBuff, Ptx_GetLastError());
21
22 pExtractor = PtxPdfContent_ContentExtractor_New(pContent);
23 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pExtractor,
24 _T("Failed to create content extractor. %s (ErrorCode: 0x%08x).\n"),
25 szErrorBuff, Ptx_GetLastError());
26
27 GOTO_CLEANUP_IF_FALSE_PRINT_ERROR(extractImages(pExtractor, iPageNo + 1, szOutputDir),
28 _T("Error occurred while extracting images. %s (ErrorCode: 0x%08x).\n"),
29 szErrorBuff, Ptx_GetLastError());
30
31 if (pPage != NULL)
32 {
33 Ptx_Release(pPage);
34 pPage = NULL;
35 }
36 if (pContent != NULL)
37 {
38 Ptx_Release(pContent);
39 pContent = NULL;
40 }
41}
42
43
1int extractImages(TPtxPdfContent_ContentExtractor* pExtractor, int iPageNo, const TCHAR* szOutputDir)
2{
3 int iImgCount = 0;
4 int iImgMaskCount = 0;
5 TPtxPdfContent_ContentExtractorIterator* pIterator = NULL;
6 TPtxPdfContent_ContentElement* pContentElement = NULL;
7 TPtxPdfContent_Image* pImage = NULL;
8 TPtxPdfContent_ImageMask* pImageMask = NULL;
9 TCHAR* szExtension = NULL;
10 FILE* pOutStream = NULL;
11
12 pIterator = PtxPdfContent_ContentExtractor_GetIterator(pExtractor);
13 GOTO_CLEANUP_IF_NULL(pIterator, _T("Failed to get iterator.\n"));
14 PtxPdfContent_ContentExtractorIterator_MoveNext(pIterator);
15 while (pContentElement = PtxPdfContent_ContentExtractorIterator_GetValue(pIterator))
16 {
17 TPtxPdfContent_ContentElementType iType = PtxPdfContent_ContentElement_GetType(pContentElement);
18 if (iType == ePtxPdfContent_ContentElementType_ImageElement)
19 {
20 iImgCount++;
21 pImage = PtxPdfContent_ImageElement_GetImage((TPtxPdfContent_ImageElement*)pContentElement);
22 GOTO_CLEANUP_IF_NULL(pImage, _T("Failed to get image.\n"));
23
24 const TPtxPdfContent_ImageType iImageType = PtxPdfContent_Image_GetDefaultImageType(pImage);
25 if (iImageType == ePtxPdfContent_ImageType_Jpeg)
26 szExtension = _T(".jpg");
27 else
28 szExtension = _T(".tiff");
29
30 TCHAR szOutPath[256] = {'\0'};
31 _stprintf(szOutPath, _T("%s/image_page%d_%d%s"), szOutputDir, iPageNo, iImgCount, szExtension);
32
33 pOutStream = _tfopen(szOutPath, _T("wb+"));
34 GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
35
36 TPtxSys_StreamDescriptor outDescriptor;
37 PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
38 if (PtxPdfContent_Image_Extract(pImage, &outDescriptor, NULL) == FALSE)
39 {
40 if (Ptx_GetLastError() == ePtx_Error_Generic)
41 {
42 nBufSize = Ptx_GetLastErrorMessage(NULL, 0);
43 Ptx_GetLastErrorMessage(szErrorBuff, MIN(ARRAY_SIZE(szErrorBuff), nBufSize));
44 _tprintf(szErrorBuff);
45 }
46 else
47 return FALSE;
48 }
49
50 if (pImage != NULL)
51 {
52 Ptx_Release(pImage);
53 pImage = NULL;
54 }
55 if (pOutStream != NULL)
56 {
57 fclose(pOutStream);
58 pOutStream = NULL;
59 }
60 }
61 else if (iType == ePtxPdfContent_ContentElementType_ImageMaskElement)
62 {
63 iImgMaskCount++;
64 pImageMask = PtxPdfContent_ImageMaskElement_GetImageMask((TPtxPdfContent_ImageMaskElement*)pContentElement);
65 GOTO_CLEANUP_IF_NULL(pImageMask, _T("Failed to get image.\n"));
66
67 szExtension = _T(".tiff");
68
69 TCHAR szOutPath[256] = {'\0'};
70 _stprintf(szOutPath, _T("%s/image_mask_page%d_%d%s"), szOutputDir, iPageNo, iImgMaskCount, szExtension);
71
72 pOutStream = _tfopen(szOutPath, _T("wb+"));
73 GOTO_CLEANUP_IF_NULL(pOutStream, _T("Failed to open output file \"%s\".\n"), szOutPath);
74
75 TPtxSys_StreamDescriptor outDescriptor;
76 PtxSysCreateFILEStreamDescriptor(&outDescriptor, pOutStream, 0);
77 if (PtxPdfContent_ImageMask_Extract(pImageMask, &outDescriptor, NULL) == FALSE)
78 {
79 if (Ptx_GetLastError() == ePtx_Error_Generic)
80 {
81 nBufSize = Ptx_GetLastErrorMessage(NULL, 0);
82 Ptx_GetLastErrorMessage(szErrorBuff, MIN(ARRAY_SIZE(szErrorBuff), nBufSize));
83 _tprintf(szErrorBuff);
84 }
85 else
86 return FALSE;
87 }
88
89 if (pImageMask != NULL)
90 {
91 Ptx_Release(pImageMask);
92 pImageMask = NULL;
93 }
94 if (pOutStream != NULL)
95 {
96 fclose(pOutStream);
97 pOutStream = NULL;
98 }
99 }
100 if (pContentElement != NULL)
101 {
102 Ptx_Release(pContentElement);
103 pContentElement = NULL;
104 }
105 PtxPdfContent_ContentExtractorIterator_MoveNext(pIterator);
106 }
107
108cleanup:
109 if (pImage != NULL)
110 Ptx_Release(pImage);
111 if (pImageMask != NULL)
112 Ptx_Release(pImageMask);
113 if (pContentElement != NULL)
114 Ptx_Release(pContentElement);
115 if (pIterator != NULL)
116 Ptx_Release(pIterator);
117 if (pOutStream != NULL)
118 fclose(pOutStream);
119
120 return iReturnValue == 1 ? FALSE : TRUE;
121}
1// Open input document
2using (Stream stream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document doc = Document.Open(stream, null))
4{
5 // Loop over all pages and extract images
6 for (int i = 0; i < doc.Pages.Count; i++)
7 {
8 ContentExtractor extractor = new ContentExtractor(doc.Pages[i].Content);
9 ExtractImages(extractor, i + 1, outputDir);
10 }
11}
1private static void ExtractImages(ContentExtractor extractor, int pageNo, string outputDir)
2{
3 int imgCount = 0;
4 int imgMaskCount = 0;
5 foreach (ContentElement contentElement in extractor)
6 {
7 if (contentElement is ImageElement element)
8 {
9 imgCount++;
10 string extension = ".tiff";
11 switch (element.Image.DefaultImageType)
12 {
13 case ImageType.Jpeg:
14 extension = ".jpg";
15 break;
16 case ImageType.Tiff:
17 extension = ".tiff";
18 break;
19 default:
20 break;
21 }
22 string outputPath = System.IO.Path.Combine(outputDir, $"image_page{pageNo}_{imgCount}{extension}");
23
24 try
25 {
26 using (Stream imageStream = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
27 {
28 element.Image.Extract(imageStream);
29 }
30 }
31 catch (GenericException ex)
32 {
33 Console.WriteLine(ex.ToString());
34 }
35 }
36 else if (contentElement is ImageMaskElement maskElement)
37 {
38 imgMaskCount++;
39 string extension = ".tiff";
40 string outputPath = System.IO.Path.Combine(outputDir, $"image_mask_page{pageNo}_{imgMaskCount}{extension}");
41 try
42 {
43 using (Stream imageStream = new FileStream(outputPath, FileMode.Create, FileAccess.ReadWrite))
44 {
45 maskElement.ImageMask.Extract(imageStream);
46 }
47 }
48 catch (GenericException ex)
49 {
50 Console.WriteLine(ex.ToString());
51 }
52 }
53 }
54}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4
5 // Loop over all pages and extract images
6 for (int i = 0; i < inDoc.getPages().size(); i++) {
7 ContentExtractor extractor = new ContentExtractor(inDoc.getPages().get(i).getContent());
8 extractImages(extractor, i + 1, outputDir);
9 }
10}
1private static void extractImages(ContentExtractor extractor, int pageNo, String outputDir) throws IOException {
2 int imgCount = 0;
3 int imgMaskCount = 0;
4 for (Object elementObj : extractor) {
5 if (elementObj instanceof ImageElement) {
6 ImageElement element = (ImageElement) elementObj;
7 imgCount++;
8 String extension = ".tiff";
9 switch (element.getImage().getDefaultImageType()) {
10 case JPEG:
11 extension = ".jpg";
12 break;
13 case TIFF:
14 extension = ".tiff";
15 break;
16 default:
17 break;
18 }
19 String outputPath = Paths.get(outputDir, "image_page" + pageNo + "_" + imgCount + extension).toString();
20 try (FileStream imageStream = new FileStream(outputPath, FileStream.Mode.READ_WRITE_NEW)) {
21 element.getImage().extract(imageStream);
22 } catch (GenericException ex) {
23 System.out.println(ex.toString());
24 }
25 }
26 else if (elementObj instanceof ImageMaskElement) {
27 ImageMaskElement element = (ImageMaskElement) elementObj;
28 imgMaskCount++;
29 String extension = ".tiff";
30 String outputPath = Paths.get(outputDir, "image_mask_page" + pageNo + "_" + imgMaskCount + extension).toString();
31 try (FileStream imageStream = new FileStream(outputPath, FileStream.Mode.READ_WRITE_NEW)) {
32 element.getImageMask().extract(imageStream);
33 } catch (GenericException ex) {
34 System.out.println(ex.toString());
35 }
36 }
37 }
38}
1def extract_image(image_element: ImageElement, output_path: str):
2 with open(output_path, "wb+") as out_stream:
3 image_element.image.extract(out_stream)
1def extract_image_mask(image_mask_element: ImageMaskElement, output_path: str):
2 with open(output_path, "wb+") as out_stream:
3 image_mask_element.image_mask.extract(out_stream)
1def process_page_content(page: Page, page_number: int, output_dir: str):
2 extractor = ContentExtractor(page.content)
3 img_count = 0
4 mask_count = 0
5
6 for content_element in extractor:
7 # Extract image elements
8 if isinstance(content_element, ImageElement):
9 img_count += 1
10 image_type = content_element.image.default_image_type
11
12 extension = ".jpg" if image_type == ImageType.JPEG else ".tiff"
13
14 output_path = os.path.join(output_dir, f"image_page{page_number}_{img_count}{extension}")
15
16 extract_image(content_element, output_path)
17
18 print(f"Extracted image: {output_path}")
19
20 # Extract image masks
21 elif isinstance(content_element, ImageMaskElement):
22 mask_count += 1
23 output_path = os.path.join(output_dir, f"image_mask_page{page_number}_{mask_count}.tiff")
24 extract_image_mask(content_element, output_path)
25 print(f"Extracted image mask: {output_path}")
List bounds of page content
1// Open input document
2using (Stream stream = new FileStream(path, FileMode.Open, FileAccess.Read))
3using (Document doc = Document.Open(stream, null))
4{
5 // Iterate over all pages
6 int pageNumber = 1;
7 foreach (Page page in doc.Pages)
8 {
9 // Print page size
10 Console.WriteLine("Page {0}", pageNumber++);
11 Size size = page.Size;
12 Console.WriteLine(" Size:");
13 Console.WriteLine(" Width: {0}", size.Width);
14 Console.WriteLine(" Height: {0}", size.Height);
15
16 // Compute rectangular bounding box of all content on page
17 Rectangle contentBox = new Rectangle()
18 {
19 Left = double.MaxValue,
20 Bottom = double.MaxValue,
21 Right = double.MinValue,
22 Top = double.MinValue,
23 };
24 ContentExtractor extractor = new ContentExtractor(page.Content);
25 foreach (ContentElement element in extractor)
26 {
27 // Enlarge the content box for each content element
28 AffineTransform tr = element.Transform;
29 Rectangle box = element.BoundingBox;
30
31 // The location on the page is given by the transformed points
32 Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Left, Y = box.Bottom, }));
33 Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Right, Y = box.Bottom, }));
34 Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Right, Y = box.Top, }));
35 Enlarge(ref contentBox, tr.TransformPoint(new Point { X = box.Left, Y = box.Top, }));
36 }
37 Console.WriteLine(" Content bounding box:");
38 Console.WriteLine(" Left: {0}", contentBox.Left);
39 Console.WriteLine(" Bottom: {0}", contentBox.Bottom);
40 Console.WriteLine(" Right: {0}", contentBox.Right);
41 Console.WriteLine(" Top: {0}", contentBox.Top);
42 }
43}
1static void Enlarge(ref Rectangle box, Point point)
2{
3 // Enlarge box if point lies outside of box
4 if (point.X < box.Left)
5 box.Left = point.X;
6 else if (point.X > box.Right)
7 box.Right = point.X;
8 if (point.Y < box.Bottom)
9 box.Bottom = point.Y;
10 else if (point.Y > box.Top)
11 box.Top = point.Y;
12}
1try (// Open input document
2 FileStream stream = new FileStream(path, FileStream.Mode.READ_ONLY);
3 Document doc = Document.open(stream, null)) {
4 // Iterate over all pages
5 int pageNumber = 1;
6 for (Page page : doc.getPages()) {
7 // Print page size
8 System.out.format("Page %d\n", pageNumber++);
9 Size size = page.getSize();
10 System.out.println(" Size:");
11 System.out.format(" Width: %f\n", size.getWidth());
12 System.out.format(" Height: %f\n", size.getHeight());
13
14 // Compute rectangular bounding box of all content on page
15 Rectangle contentBox = new Rectangle(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE, Double.MIN_VALUE);
16 ContentExtractor extractor = new ContentExtractor(page.getContent());
17 for (ContentElement element : extractor) {
18 // Enlarge the content box for each content element
19 AffineTransform tr = element.getTransform();
20 Rectangle box = element.getBoundingBox();
21
22 // The location on the page is given by the transformed points
23 contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getLeft(), box.getBottom())));
24 contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getRight(), box.getBottom())));
25 contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getRight(), box.getTop())));
26 contentBox = enlarge(contentBox, tr.transformPoint(new Point(box.getLeft(), box.getTop())));
27 }
28 System.out.println(" Content bounding box:");
29 System.out.format(" Left: %f\n", contentBox.getLeft());
30 System.out.format(" Bottom: %f\n", contentBox.getBottom());
31 System.out.format(" Right: %f\n", contentBox.getRight());
32 System.out.format(" Top: %f\n", contentBox.getTop());
33 }
34}
1static Rectangle enlarge(Rectangle box, Point point) {
2 // Enlarge box if point lies outside of box
3 if (point.getX() < box.getLeft())
4 box.setLeft(point.getX());
5 else if (point.getX() > box.getRight())
6 box.setRight(point.getX());
7 if (point.getY() < box.getBottom())
8 box.setBottom(point.getY());
9 else if (point.getY() > box.getTop())
10 box.setTop(point.getY());
11 return box;
12}
1def enlarge(content_box: Rectangle, point: Point):
2 """
3 Enlarge the bounding box to include the given point.
4 """
5 content_box.left = min(content_box.left, point.x)
6 content_box.right = max(content_box.right, point.x)
7 content_box.bottom = min(content_box.bottom, point.y)
8 content_box.top = max(content_box.top, point.y)
1def list_content_bounds(input_doc: Document):
2 """
3 Process the input PDF file to list page size and bounding boxes.
4 """
5 # Iterate over all pages
6 for page_number, page in enumerate(input_doc.pages, start=1):
7 print(f"Page {page_number}")
8
9 # Print page size
10 size = page.size
11 print(" Size:")
12 print(f" Width: {size.width}")
13 print(f" Height: {size.height}")
14
15 # Compute rectangular bounding box of all content on page
16 content_box = Rectangle(
17 left=float("inf"),
18 bottom=float("inf"),
19 right=float("-inf"),
20 top=float("-inf"),
21 )
22
23 # Extract content and compute bounding box
24 extractor = ContentExtractor(page.content)
25 for element in extractor:
26 # Enlarge the content box for each content element
27 tr = element.transform
28 box = element.bounding_box
29
30 # The location on the page is given by the transformed points
31 enlarge(content_box, tr.transform_point(Point(x=box.left, y=box.bottom)))
32 enlarge(content_box, tr.transform_point(Point(x=box.right, y=box.bottom)))
33 enlarge(content_box, tr.transform_point(Point(x=box.right, y=box.top)))
34 enlarge(content_box, tr.transform_point(Point(x=box.left, y=box.top)))
35
36 print(" Content bounding box:")
37 print(f" Left: {content_box.left}")
38 print(f" Bottom: {content_box.bottom}")
39 print(f" Right: {content_box.right}")
40 print(f" Top: {content_box.top}")
List document information of PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, szPassword);
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Conformance
10TPtxPdf_Conformance conformance = PtxPdf_Document_GetConformance(pInDoc);
11if (conformance == 0)
12{
13 GOTO_CLEANUP(szErrorBuff, Ptx_GetLastError());
14}
15_tprintf(_T("Conformance: "));
16switch (conformance)
17{
18case ePtxPdf_Conformance_Pdf10:
19 _tprintf(_T("PDF 1.0\n"));
20 break;
21case ePtxPdf_Conformance_Pdf11:
22 _tprintf(_T("PDF 1.1\n"));
23 break;
24case ePtxPdf_Conformance_Pdf12:
25 _tprintf(_T("PDF 1.2\n"));
26 break;
27case ePtxPdf_Conformance_Pdf13:
28 _tprintf(_T("PDF 1.3\n"));
29 break;
30case ePtxPdf_Conformance_Pdf14:
31 _tprintf(_T("PDF 1.4\n"));
32 break;
33case ePtxPdf_Conformance_Pdf15:
34 _tprintf(_T("PDF 1.5\n"));
35 break;
36case ePtxPdf_Conformance_Pdf16:
37 _tprintf(_T("PDF 1.6\n"));
38 break;
39case ePtxPdf_Conformance_Pdf17:
40 _tprintf(_T("PDF 1.7\n"));
41 break;
42case ePtxPdf_Conformance_Pdf20:
43 _tprintf(_T("PDF 2.0\n"));
44 break;
45case ePtxPdf_Conformance_PdfA1B:
46 _tprintf(_T("PDF/A1-b\n"));
47 break;
48case ePtxPdf_Conformance_PdfA1A:
49 _tprintf(_T("PDF/A1-a\n"));
50 break;
51case ePtxPdf_Conformance_PdfA2B:
52 _tprintf(_T("PDF/A2-b\n"));
53 break;
54case ePtxPdf_Conformance_PdfA2U:
55 _tprintf(_T("PDF/A2-u\n"));
56 break;
57case ePtxPdf_Conformance_PdfA2A:
58 _tprintf(_T("PDF/A2-a\n"));
59 break;
60case ePtxPdf_Conformance_PdfA3B:
61 _tprintf(_T("PDF/A3-b\n"));
62 break;
63case ePtxPdf_Conformance_PdfA3U:
64 _tprintf(_T("PDF/A3-u\n"));
65 break;
66case ePtxPdf_Conformance_PdfA3A:
67 _tprintf(_T("PDF/A3-a\n"));
68 break;
69}
70
71// Encryption information
72TPtxPdf_Permission permissions;
73BOOL iRet = PtxPdf_Document_GetPermissions(pInDoc, &permissions);
74if (iRet == FALSE)
75{
76 if (Ptx_GetLastError() != ePtx_Error_Success)
77 GOTO_CLEANUP(szErrorBuff, Ptx_GetLastError());
78 _tprintf(_T("Not encrypted\n"));
79}
80else
81{
82 _tprintf(_T("Encryption:\n"));
83 _tprintf(_T(" - Permissions: "));
84 if (permissions & ePtxPdf_Permission_Print)
85 _tprintf(_T("Print, "));
86 if (permissions & ePtxPdf_Permission_Modify)
87 _tprintf(_T("Modify, "));
88 if (permissions & ePtxPdf_Permission_Copy)
89 _tprintf(_T("Copy, "));
90 if (permissions & ePtxPdf_Permission_Annotate)
91 _tprintf(_T("Annotate, "));
92 if (permissions & ePtxPdf_Permission_FillForms)
93 _tprintf(_T("FillForms, "));
94 if (permissions & ePtxPdf_Permission_SupportDisabilities)
95 _tprintf(_T("SupportDisabilities, "));
96 if (permissions & ePtxPdf_Permission_Assemble)
97 _tprintf(_T("Assemble, "));
98 if (permissions & ePtxPdf_Permission_DigitalPrint)
99 _tprintf(_T("DigitalPrint, "));
100 _tprintf(_T("\n"));
101}
102
103// Get metadata of input PDF
104pMetadata = PtxPdf_Document_GetMetadata(pInDoc);
105GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pMetadata, _T("Failed to get metadata. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
106 Ptx_GetLastError());
107_tprintf(_T("Document information:\n"));
108
109// Get title
110size_t nTitle = PtxPdf_Metadata_GetTitle(pMetadata, NULL, 0);
111if (nTitle != 0)
112{
113 TCHAR* szTitle = (TCHAR*)malloc(nTitle * sizeof(TCHAR));
114 if (szTitle != NULL)
115 {
116 PtxPdf_Metadata_GetTitle(pMetadata, szTitle, nTitle);
117 _tprintf(_T(" - Title: %s\n"), szTitle);
118 free(szTitle);
119 }
120}
121
122// Get author
123size_t nAuthor = PtxPdf_Metadata_GetAuthor(pMetadata, NULL, 0);
124if (nAuthor != 0)
125{
126 TCHAR* szAuthor = (TCHAR*)malloc(nAuthor * sizeof(TCHAR));
127 if (szAuthor != NULL)
128 {
129 PtxPdf_Metadata_GetAuthor(pMetadata, szAuthor, nAuthor);
130 _tprintf(_T(" - Author: %s\n"), szAuthor);
131 free(szAuthor);
132 }
133}
134
135// Get creator
136size_t nCreator = PtxPdf_Metadata_GetCreator(pMetadata, NULL, 0);
137if (nCreator != 0)
138{
139 TCHAR* szCreator = (TCHAR*)malloc(nCreator * sizeof(TCHAR));
140 if (szCreator != NULL)
141 {
142 PtxPdf_Metadata_GetCreator(pMetadata, szCreator, nCreator);
143 _tprintf(_T(" - Creator: %s\n"), szCreator);
144 free(szCreator);
145 }
146}
147
148// Get producer
149size_t nProducer = PtxPdf_Metadata_GetProducer(pMetadata, NULL, 0);
150if (nProducer != 0)
151{
152 TCHAR* szProducer = (TCHAR*)malloc(nProducer * sizeof(TCHAR));
153 if (szProducer != NULL)
154 {
155 PtxPdf_Metadata_GetProducer(pMetadata, szProducer, nProducer);
156 _tprintf(_T(" - Producer: %s\n"), szProducer);
157 free(szProducer);
158 }
159}
160
161// Get subject
162size_t nSubject = PtxPdf_Metadata_GetSubject(pMetadata, NULL, 0);
163if (nSubject != 0)
164{
165 TCHAR* szSubject = (TCHAR*)malloc(nSubject * sizeof(TCHAR));
166 if (szSubject != NULL)
167 {
168 PtxPdf_Metadata_GetSubject(pMetadata, szSubject, nSubject);
169 _tprintf(_T(" - Subject: %s\n"), szSubject);
170 free(szSubject);
171 }
172}
173
174// Get keywords
175size_t nKeywords = PtxPdf_Metadata_GetKeywords(pMetadata, NULL, 0);
176if (nKeywords != 0)
177{
178 TCHAR* szKeywords = (TCHAR*)malloc(nKeywords * sizeof(TCHAR));
179 if (szKeywords != NULL)
180 {
181 PtxPdf_Metadata_GetKeywords(pMetadata, szKeywords, nKeywords);
182 _tprintf(_T(" - Keywords: %s\n"), szKeywords);
183 free(szKeywords);
184 }
185}
186
187// Get creation date
188if (PtxPdf_Metadata_GetCreationDate(pMetadata, &date) == TRUE)
189{
190 _tprintf(_T(" - Creation Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear, date.iMonth, date.iDay,
191 date.iHour, date.iMinute, date.iSecond, date.iTZSign >= 0 ? '+' : '-', date.iTZHour, date.iTZMinute);
192}
193
194// Get modification date
195if (PtxPdf_Metadata_GetModificationDate(pMetadata, &date) == TRUE)
196{
197 _tprintf(_T(" - Modification Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear, date.iMonth,
198 date.iDay, date.iHour, date.iMinute, date.iSecond, date.iTZSign >= 0 ? '+' : '-', date.iTZHour,
199 date.iTZMinute);
200}
201
202// Get custom entries
203_tprintf(_T("Custom entries:\n"));
204TPtx_StringMap* pCustomEntries = PtxPdf_Metadata_GetCustomEntries(pMetadata);
205GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pCustomEntries, _T("Failed to get custom entries. %s (ErrorCode: 0x%08x).\n"),
206 szErrorBuff, Ptx_GetLastError());
207for (int i = Ptx_StringMap_GetBegin(pCustomEntries), iEnd = Ptx_StringMap_GetEnd(pCustomEntries); i != iEnd;
208 i = Ptx_StringMap_GetNext(pCustomEntries, i))
209{
210 size_t nKeySize = Ptx_StringMap_GetKey(pCustomEntries, i, NULL, 0);
211 TCHAR* szKey = (TCHAR*)malloc(nKeySize * sizeof(TCHAR));
212 nKeySize = Ptx_StringMap_GetKey(pCustomEntries, i, szKey, nKeySize);
213
214 size_t nValueSize = Ptx_StringMap_GetValue(pCustomEntries, i, NULL, 0);
215 TCHAR* szValue = (TCHAR*)malloc(nValueSize * sizeof(TCHAR));
216 nValueSize = Ptx_StringMap_GetValue(pCustomEntries, i, szValue, nValueSize);
217
218 if (szKey && nKeySize && szValue && nValueSize)
219 _tprintf(_T(" - %s: %s\n"), szKey, szValue);
220
221 free(szKey);
222 free(szValue);
223}
224
225
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, password))
4{
5 // Conformance
6 Console.WriteLine("Conformance: {0}", inDoc.Conformance.ToString());
7
8 // Encryption information
9 Permission? permissions = inDoc.Permissions;
10 if (!permissions.HasValue)
11 {
12 Console.WriteLine("Not encrypted");
13 }
14 else
15 {
16 Console.WriteLine("Encryption:");
17 Console.Write(" - Permissions: ");
18 foreach (Enum flag in Enum.GetValues(typeof(Permission)))
19 if (permissions.Value.HasFlag(flag))
20 Console.Write("{0}, ", flag.ToString());
21 Console.WriteLine();
22 }
23
24 // Get metadata
25 Metadata metadata = inDoc.Metadata;
26 Console.WriteLine("Document information:");
27
28 // Get title
29 string title = metadata.Title;
30 if (title != null)
31 Console.WriteLine(" - Title: {0}", title);
32
33 // Get author
34 string author = metadata.Author;
35 if (author != null)
36 Console.WriteLine(" - Author: {0}", author);
37
38 // Get subject
39 string subject = metadata.Subject;
40 if (subject != null)
41 Console.WriteLine(" - Subject: {0}", subject);
42
43 // Get keywords
44 string keywords = metadata.Keywords;
45 if (keywords != null)
46 Console.WriteLine(" - Keywords: {0}", keywords);
47
48 // Get creation date
49 DateTimeOffset? creationDate = metadata.CreationDate;
50 if (creationDate != null)
51 Console.WriteLine(" - Creation Date: {0}", creationDate);
52
53 // Get modification date
54 DateTimeOffset? modificationDate = metadata.ModificationDate;
55 if (modificationDate != null)
56 Console.WriteLine(" - Modification Date: {0}", modificationDate);
57
58 // Get creator
59 string creator = metadata.Creator;
60 if (creator != null)
61 Console.WriteLine(" - Creator: {0}", creator);
62
63 // Get producer
64 string producer = metadata.Producer;
65 if (producer != null)
66 Console.WriteLine(" - Producer: {0}", producer);
67
68 // Custom entries
69 Console.WriteLine("Custom entries:");
70 foreach (var entry in metadata.CustomEntries)
71 Console.WriteLine(" - {0}: {1}", entry.Key, entry.Value);
72}
73
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4 // Conformance
5 System.out.format("Conformance: %s\n", inDoc.getConformance().toString());
6
7 // Encryption information
8 EnumSet<Permission> permissions = inDoc.getPermissions();
9 if (permissions == null) {
10 System.out.println("Not encrypted");
11 } else {
12 System.out.println("Encryption:");
13 System.out.print(" - Permissions: ");
14 for (Permission permission : permissions) {
15 System.out.format("%s, ", permission.toString());
16 }
17 System.out.println();
18 }
19
20 // Get metadata of input PDF
21 Metadata metadata = inDoc.getMetadata();
22 System.out.format("Document information:\n");
23
24 // Get title
25 String title = metadata.getTitle();
26 if (title != null)
27 System.out.format(" - Title: %s\n", title);
28
29 // Get author
30 String author = metadata.getAuthor();
31 if (author != null)
32 System.out.format(" - Author: %s\n", author);
33
34 // Get subject
35 String subject = metadata.getSubject();
36 if (subject != null)
37 System.out.format(" - Subject: %s\n", subject);
38
39 // Get keywords
40 String keywords = metadata.getKeywords();
41 if (keywords != null)
42 System.out.format(" - Keywords: %s\n", keywords);
43
44 // Get creation date
45 OffsetDateTime creationDate = metadata.getCreationDate();
46 if (creationDate != null)
47 System.out.format(" - Creation Date: %s\n", creationDate.toString());
48
49 // Get modification date
50 OffsetDateTime modificationDate = metadata.getModificationDate();
51 if (modificationDate != null)
52 System.out.format(" - Modification Date: %s\n", modificationDate.toString());
53
54 // Get creator
55 String creator = metadata.getCreator();
56 if (creator != null)
57 System.out.format(" - Creator: %s\n", creator);
58
59 // Get producer
60 String producer = metadata.getProducer();
61 if (producer != null)
62 System.out.format(" - Producer: %s\n", producer);
63
64 // Custom entries
65 System.out.format("Custom entries:\n");
66 for (Map.Entry<String, String> entry : metadata.getCustomEntries().entrySet())
67 System.out.format(" - %s: %s\n", entry.getKey(), entry.getValue());
68}
69
1def display_permissions(permissions: int):
2 """Display encryption permissions in a readable format."""
3 # Display active permission names
4 active_permissions = [perm.name for perm in Permission if permissions & perm]
5 for perm in active_permissions:
6 print(f" - {perm}")
1def list_pdf_info(input_doc: Document):
2 """
3 List document information and metadata of the given PDF.
4 """
5 # Conformance
6 print(f"Conformance: {input_doc.conformance.name}")
7
8 # Encryption information
9 permissions = input_doc.permissions
10 if permissions is None:
11 print("Not encrypted")
12 else:
13 display_permissions(permissions)
14
15 # Get metadata
16 metadata = input_doc.metadata
17 print("Document information:")
18
19 # Display standard metadata
20 if metadata.title:
21 print(f" - Title: {metadata.title}")
22 if metadata.author:
23 print(f" - Author: {metadata.author}")
24 if metadata.subject:
25 print(f" - Subject: {metadata.subject}")
26 if metadata.keywords:
27 print(f" - Keywords: {metadata.keywords}")
28 if metadata.creation_date:
29 print(f" - Creation Date: {metadata.creation_date}")
30 if metadata.modification_date:
31 print(f" - Modification Date: {metadata.modification_date}")
32 if metadata.creator:
33 print(f" - Creator: {metadata.creator}")
34 if metadata.producer:
35 print(f" - Producer: {metadata.producer}")
36
37 # Display custom entries
38 print("Custom entries:")
39 for key, value in metadata.custom_entries.items():
40 print(f" - {key}: {value}")
List Signatures in PDF
1// Open input document
2pInStream = _tfopen(szInPath, _T("rb"));
3GOTO_CLEANUP_IF_NULL(pInStream, _T("Failed to open input file \"%s\".\n"), szInPath);
4PtxSysCreateFILEStreamDescriptor(&descriptor, pInStream, 0);
5pInDoc = PtxPdf_Document_Open(&descriptor, _T(""));
6GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pInDoc, _T("Input file \"%s\" cannot be opened. %s (ErrorCode: 0x%08x).\n"),
7 szInPath, szErrorBuff, Ptx_GetLastError());
8
9// Get signatures of input PDF
10pSignatureFields = PtxPdf_Document_GetSignatureFields(pInDoc);
11GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pSignatureFields,
12 _T("Failed to get signatures of input PDF. %s (ErrorCode: 0x%08x).\n"),
13 szErrorBuff, Ptx_GetLastError());
14_tprintf(_T("Number of signature fields: %d\n"), PtxPdfForms_SignatureFieldList_GetCount(pSignatureFields));
15
16for (int i = 0; i < PtxPdfForms_SignatureFieldList_GetCount(pSignatureFields); i++)
17{
18 pSig = PtxPdfForms_SignatureFieldList_Get(pSignatureFields, i);
19 GOTO_CLEANUP_IF_NULL_PRINT_ERROR(pSig, _T("Failed to get signature. %s (ErrorCode: 0x%08x).\n"), szErrorBuff,
20 Ptx_GetLastError());
21
22 TPtxPdfForms_SignatureFieldType iFieldType = PtxPdfForms_SignatureField_GetType(pSig);
23 if (iFieldType == ePtxPdfForms_SignatureFieldType_Signature ||
24 iFieldType == ePtxPdfForms_SignatureFieldType_DocMdpSignature ||
25 iFieldType == ePtxPdfForms_SignatureFieldType_DocumentSignature)
26 {
27 // List name
28 size_t nName = PtxPdfForms_SignedSignatureField_GetName(pSig, NULL, 0);
29 _tprintf(_T("- %s fields"), PtxPdfForms_SignatureField_IsVisible(pSig) ? _T("Visible") : _T("Invisible"));
30 if (nName != 0)
31 {
32 TCHAR* szName = (TCHAR*)malloc(nName * sizeof(TCHAR));
33 if (szName != NULL)
34 {
35 PtxPdfForms_SignedSignatureField_GetName(pSig, szName, nName);
36 _tprintf(_T(", signed by: %s"), szName);
37 free(szName);
38 }
39 }
40 _tprintf(_T("\n"));
41
42 // List location
43 size_t nLocation = PtxPdfForms_Signature_GetLocation(pSig, NULL, 0);
44 if (nLocation != 0)
45 {
46 TCHAR* szLocation = (TCHAR*)malloc(nLocation * sizeof(TCHAR));
47 if (szLocation != NULL)
48 {
49 PtxPdfForms_Signature_GetLocation(pSig, szLocation, nLocation);
50 _tprintf(_T(" - Location: %s\n"), szLocation);
51 free(szLocation);
52 }
53 }
54
55 // List reason
56 size_t nReason = PtxPdfForms_Signature_GetReason(pSig, NULL, 0);
57 if (nReason != 0)
58 {
59 TCHAR* szReason = (TCHAR*)malloc(nReason * sizeof(TCHAR));
60 if (szReason != NULL)
61 {
62 PtxPdfForms_Signature_GetReason(pSig, szReason, nReason);
63 _tprintf(_T(" - Reason: %s\n"), szReason);
64 free(szReason);
65 }
66 }
67
68 // List contact info
69 size_t nContactInfo = PtxPdfForms_Signature_GetContactInfo(pSig, NULL, 0);
70 if (nContactInfo != 0)
71 {
72 TCHAR* szContactInfo = (TCHAR*)malloc(nContactInfo * sizeof(TCHAR));
73 if (szContactInfo != NULL)
74 {
75 PtxPdfForms_Signature_GetContactInfo(pSig, szContactInfo, nContactInfo);
76 _tprintf(_T(" - Contact info: %s\n"), szContactInfo);
77 free(szContactInfo);
78 }
79 }
80
81 // List date
82 if (PtxPdfForms_SignedSignatureField_GetDate(pSig, &date) == TRUE)
83 {
84 _tprintf(_T(" - Date: %02d-%02d-%d %02d:%02d:%02d%c%02d:%02d\n"), date.iYear, date.iMonth, date.iDay,
85 date.iHour, date.iMinute, date.iSecond, date.iTZSign >= 0 ? '+' : '-', date.iTZHour,
86 date.iTZMinute);
87 }
88 }
89 else
90 {
91 _tprintf(_T("- %s field, not signed\n"),
92 PtxPdfForms_SignatureField_IsVisible(pSig) ? _T("Visible") : _T("Invisible"));
93 }
94}
95
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 SignatureFieldList signatureFields = inDoc.SignatureFields;
6 Console.WriteLine("Number of signature fields: {0}", signatureFields.Count);
7 foreach (SignatureField field in signatureFields)
8 {
9 if (field is Signature sig)
10 {
11 // List name
12 string name = sig.Name;
13 Console.WriteLine("- {0} fields, signed by: {1}",
14 sig.IsVisible ? "Visible" : "Invisible", name ?? "(Unknown name)");
15
16 // List location
17 string location = sig.Location;
18 if (location != null)
19 Console.WriteLine(" - Location: {0}", location);
20
21 // List reason
22 string reason = sig.Reason;
23 if (reason != null)
24 Console.WriteLine(" - Reason: {0}", reason);
25
26 // List contact info
27 string contactInfo = sig.ContactInfo;
28 if (contactInfo != null)
29 Console.WriteLine(" - Contact info: {0}", contactInfo);
30
31 // List date
32 DateTimeOffset? date = sig.Date;
33 if (date != null)
34 Console.WriteLine(" - Date: {0}", date.Value);
35 }
36 else
37 Console.WriteLine("- {0} field, not signed", field.IsVisible ? "Visible" : "Invisible");
38 }
39}
40
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4 SignatureFieldList signatureFields = inDoc.getSignatureFields();
5 System.out.format("Number of signature fields: %d\n", signatureFields.size());
6
7 for (SignatureField field : signatureFields) {
8 if (field instanceof Signature) {
9 Signature sig = (Signature)field;
10 // List name
11 String name = sig.getName();
12 System.out.format("- %s field, signed by: %s\n", sig.getIsVisible() ? "Visible" : "Invisible",
13 name != null ? name : "(Unknown name)");
14
15 // List location
16 String location = sig.getLocation();
17 if (location != null)
18 System.out.format(" - Location: %s\n", location);
19
20 // List reason
21 String reason = sig.getReason();
22 if (reason != null)
23 System.out.format(" - Reason: %s\n", reason);
24
25 // List contact info
26 String contactInfo = sig.getContactInfo();
27 if (contactInfo != null)
28 System.out.format(" - Contact info: %s\n", contactInfo);
29
30 // List date
31 OffsetDateTime date = sig.getDate();
32 if (date != null)
33 System.out.format(" - Date: %s\n", date.toString());
34 } else {
35 System.out.format("- %s field, not signed\n", field.getIsVisible() ? "Visible" : "Invisible");
36 }
37 }
38}
39
1
2
3# Open input document
4with io.FileIO(input_file_path, "rb") as in_stream:
5 with Document.open(in_stream, None) as in_doc:
6 # List all signatures of the PDF document
7 list_signatures(in_doc)
8
1def list_signatures(in_doc: Document):
2 # Retrieve the list of signature fields
3 signature_fields = in_doc.signature_fields
4 print(f"Number of signature fields: {len(signature_fields)}")
5
6 for field in signature_fields:
7 if isinstance(field, Signature):
8 # List name
9 name = field.name or "(Unknown name)"
10 print(f"- {'Visible' if field.is_visible else 'Invisible'} field, signed by: {name}")
11
12 # List location
13 if field.location:
14 print(f" - Location: {field.location}")
15
16 # List reason
17 if field.reason:
18 print(f" - Reason: {field.reason}")
19
20 # List contact info
21 if field.contact_info:
22 print(f" - Contact info: {field.contact_info}")
23
24 # List date
25 if field.date:
26 print(f" - Date: {field.date}")
27 else:
28 print(f"- {'Visible' if field.is_visible else 'Invisible'} field, not signed")
Print a table of content
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 PrintOutlineItems(inDoc.Outline, "", inDoc);
6}
1static void PrintOutlineItem(OutlineItem item, string indentation, Document document)
2{
3 string title = item.Title;
4 Console.Out.Write("{0}{1}", indentation, title);
5 Destination dest = item.Destination;
6 if (dest != null)
7 {
8 int pageNumber = document.Pages.IndexOf(dest.Target.Page) + 1;
9 string dots = new string('.', 78 - indentation.Length - title.Length - pageNumber.ToString().Length);
10 Console.Out.Write(" {0} {1}", dots, pageNumber);
11 }
12 Console.Out.WriteLine();
13 PrintOutlineItems(item.Children, indentation + " ", document);
14}
1static void PrintOutlineItems(OutlineItemList outlineItems, string indentation, Document document)
2{
3 foreach (var item in outlineItems)
4 PrintOutlineItem(item, indentation, document);
5}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4 printOutlineItems(inDoc.getOutline(), "", inDoc);
5}
1static void printOutlineItem(OutlineItem item, String indentation, Document document) throws ToolboxException {
2 String title = item.getTitle();
3 System.out.format("%s%s", indentation, title);
4 Destination dest = item.getDestination();
5 if (dest != null) {
6 int pageNumber = document.getPages().indexOf(dest.getTarget().getPage()) + 1;
7 char[] dots = new char[78 - indentation.length() - title.length() - Integer.toString(pageNumber).length()];
8 Arrays.fill(dots, '.');
9 System.out.format(" %s %d", new String(dots), pageNumber);
10 }
11 System.out.println();
12 printOutlineItems(item.getChildren(), indentation + " ", document);
13}
14
1static void printOutlineItems(OutlineItemList outlineItems, String indentation, Document document)
2 throws ToolboxException {
3 for (OutlineItem item : outlineItems)
4 printOutlineItem(item, indentation, document);
5}
1def print_outline_item(item: OutlineItem, indentation: str, in_doc: Document):
2 title = item.title
3 print(f"{indentation}{title}", end="")
4
5 dest = item.destination
6 if dest and dest.target:
7 page_number = in_doc.pages.index(dest.target.page) + 1
8 dots_length = max(0, 78 - len(indentation) - len(title) - len(str(page_number)))
9 dots = "." * dots_length
10 print(f" {dots} {page_number}", end="")
11
12 print() # End the current line
13 print_outline_items(item.children, indentation + " ", in_doc)
1def print_outline_items(items: OutlineItemList, indentation: str, in_doc: Document):
2 for outline_item in items:
3 print_outline_item(outline_item, indentation, in_doc);
Extract all text from PDF
1// Open input document
2using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
3using (Document inDoc = Document.Open(inStream, null))
4{
5 int pageNumber = 1;
6
7 // Process each page
8 foreach (var inPage in inDoc.Pages)
9 {
10 Console.WriteLine("==========");
11 Console.WriteLine($"Page: {pageNumber++}");
12 Console.WriteLine("==========");
13
14 ContentExtractor extractor = new ContentExtractor(inPage.Content);
15 extractor.Ungrouping = UngroupingSelection.All;
16
17 // Iterate over all content elements and only process text elements
18 foreach (ContentElement element in extractor)
19 if (element is TextElement textElement)
20 WriteText(textElement.Text);
21 }
22}
1private static void WriteText(Text text)
2{
3 string textPart = "";
4
5 // Write all text fragments
6 // Determine heuristically if there is a space between two text fragments
7 for (int iFragment = 0; iFragment < text.Count; iFragment++)
8 {
9
10 TextFragment currFragment = text[iFragment];
11 if (iFragment == 0)
12 textPart += currFragment.Text;
13 else
14 {
15 TextFragment lastFragment = text[iFragment - 1];
16 if (currFragment.CharacterSpacing != lastFragment.CharacterSpacing ||
17 currFragment.FontSize != lastFragment.FontSize ||
18 currFragment.HorizontalScaling != lastFragment.HorizontalScaling ||
19 currFragment.Rise != lastFragment.Rise ||
20 currFragment.WordSpacing != lastFragment.WordSpacing)
21 textPart += $" {currFragment.Text}";
22 else
23 {
24 Point currentBotLeft = currFragment.Transform.TransformRectangle(currFragment.BoundingBox).BottomLeft;
25 Point beforeBotRight = lastFragment.Transform.TransformRectangle(lastFragment.BoundingBox).BottomRight;
26
27 if (beforeBotRight.X < currentBotLeft.X - 0.7 * currFragment.FontSize ||
28 beforeBotRight.Y < currentBotLeft.Y - 0.1 * currFragment.FontSize ||
29 currentBotLeft.Y < beforeBotRight.Y - 0.1 * currFragment.FontSize)
30 textPart += $" {currFragment.Text}";
31 else
32 textPart += currFragment.Text;
33 }
34 }
35 }
36 Console.WriteLine(textPart);
37}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4 int pageNumber = 1;
5
6 // Process each page
7 for (Page inPage : inDoc.getPages()) {
8 System.out.println("==========");
9 System.out.println("Page: " + pageNumber++);
10 System.out.println("==========");
11
12 ContentExtractor extractor = new ContentExtractor(inPage.getContent());
13 extractor.setUngrouping(UngroupingSelection.ALL);
14
15 // Iterate over all content elements and only process text elements
16 for (ContentElement element : extractor) {
17 if (element instanceof TextElement)
18 writeText(((TextElement) element).getText());
19 }
20 }
21}
1private static void writeText(Text text) {
2 String textPart = "";
3
4 // Write all text fragments
5 // Determine heuristically if there is a space between two text fragments
6 for (int iFragment = 0; iFragment < text.size(); iFragment++) {
7 TextFragment currFragment = text.get(iFragment);
8 if (iFragment == 0)
9 textPart += currFragment.getText();
10 else {
11 TextFragment lastFragment = text.get(iFragment - 1);
12 if (currFragment.getCharacterSpacing() != lastFragment.getCharacterSpacing() ||
13 currFragment.getFontSize() != lastFragment.getFontSize() ||
14 currFragment.getHorizontalScaling() != lastFragment.getHorizontalScaling() ||
15 currFragment.getRise() != lastFragment.getRise() ||
16 currFragment.getWordSpacing() != lastFragment.getWordSpacing()) {
17 textPart += " ";
18 textPart += currFragment.getText();
19 }
20 else {
21 Point currentBotLeft = currFragment.getTransform().transformRectangle(currFragment.getBoundingBox()).getBottomLeft();
22 Point beforeBotRight = lastFragment.getTransform().transformRectangle(lastFragment.getBoundingBox()).getBottomRight();
23
24 if (beforeBotRight.getX() < currentBotLeft.getX() - 0.7 * currFragment.getFontSize() ||
25 beforeBotRight.getY() < currentBotLeft.getY() - 0.1 * currFragment.getFontSize() ||
26 currentBotLeft.getY() < beforeBotRight.getY() - 0.1 * currFragment.getFontSize()) {
27 textPart += " ";
28 textPart += currFragment.getText();
29 }
30 else
31 textPart += currFragment.getText();
32 }
33 }
34 }
35 System.out.println(textPart);
36}
1
2
3# Open input document
4with open(input_path, "rb") as in_stream:
5 with Document.open(in_stream, None) as in_doc:
6 page_number = 1
7
8 # Process each page
9 for in_page in in_doc.pages:
10 print(f"==========\nPage: {page_number}\n==========")
11
12 extractor = ContentExtractor(in_page.content)
13 extractor.ungrouping = UngroupingSelection.ALL
14
15 # Iterate over all content elements and only process text elements
16 for element in extractor:
17 if isinstance(element, TextElement):
18 write_text(element.text)
19
1def write_text(text: Text):
2 """Reconstruct text heuristically from text fragments."""
3 text_part = []
4
5 # Write all text fragments
6 # Determine heuristically if there is a space between two text fragments
7 for i_fragment, curr_fragment in enumerate(text):
8 if i_fragment == 0:
9 text_part.append(curr_fragment.text)
10 else:
11 last_fragment = text[i_fragment - 1]
12
13 # Determine if there's a space between fragments
14 if (curr_fragment.character_spacing != last_fragment.character_spacing or
15 curr_fragment.font_size != last_fragment.font_size or
16 curr_fragment.horizontal_scaling != last_fragment.horizontal_scaling or
17 curr_fragment.rise != last_fragment.rise or
18 curr_fragment.word_spacing != last_fragment.word_spacing):
19 text_part.append(f" {curr_fragment.text}")
20 else:
21 current_bot_left = curr_fragment.transform.transform_rectangle(curr_fragment.bounding_box).bottom_left
22 before_bot_right = last_fragment.transform.transform_rectangle(last_fragment.bounding_box).bottom_right
23
24 if (before_bot_right.x < current_bot_left.x - 0.7 * curr_fragment.font_size or
25 before_bot_right.y < current_bot_left.y - 0.1 * curr_fragment.font_size or
26 current_bot_left.y < before_bot_right.y - 0.1 * curr_fragment.font_size):
27 text_part.append(f" {curr_fragment.text}")
28 else:
29 text_part.append(curr_fragment.text)
30
31 print("".join(text_part))