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
1# Open input document
2with io.FileIO(input_file_path, 'rb') as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4 # Create output document
5 with io.FileIO(output_file_path, 'wb+') as output_stream:
6 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
7 # Copy document-wide data
8 copy_document_data(in_doc, out_doc)
9
10 # Define page copy options
11 copy_options = PageCopyOptions()
12
13 # Copy first page and add annotations
14 out_page = copy_and_add_annotations(out_doc, in_doc.pages[0], copy_options)
15
16 # Add the page to the output document's page list
17 out_doc.pages.append(out_page)
18
19 # Copy the remaining pages and add to the output document's page list
20 in_pages = in_doc.pages[1:]
21 out_pages = PageList.copy(out_doc, in_pages, copy_options)
22 out_doc.pages.extend(out_pages)
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)
1# Open input PDF and FDF files
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with io.FileIO(input_fdf_path, "rb") as in_fdf_stream:
4 with Document.open_with_fdf(in_stream, in_fdf_stream, None) as in_doc:
5 # Create output PDF and FDF files
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with io.FileIO(output_fdf_path, "wb+") as out_fdf_stream:
8 with Document.create_with_fdf(out_stream, out_fdf_stream, in_doc.conformance, None) as out_doc:
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Filter and process annotations
13 filter_annotations(in_doc, out_doc)
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))
1# Open input document
2with io.FileIO(input_file_path, 'rb') as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, 'wb+') as output_stream:
7 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Copy all form fields
13 in_form_fields = in_doc.form_fields
14 out_form_fields = out_doc.form_fields
15 for in_pair_key, in_pair_node in in_form_fields.items():
16 out_form_field_node = FieldNode.copy(out_doc, in_pair_node)
17 out_form_fields[in_pair_key] = out_form_field_node
18
19 # Define page copy options
20 copy_options = PageCopyOptions()
21 copy_options.form_fields = FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS
22 copy_options.unsigned_signatures = CopyStrategy.REMOVE
23
24 # Copy first page
25 out_page = Page.copy(out_doc, in_doc.pages[0], copy_options)
26
27 # Add different types of form fields to the output page
28 add_check_box(out_doc, "Check Box ID", True, out_page, Rectangle(left=50.0, bottom=300.0, right=70.0, top=320.0))
29 add_combo_box(out_doc, "Combo Box ID", ["item 1", "item 2"], "item 1", out_page, Rectangle(left=50.0, bottom=260.0, right=210.0, top=280.0))
30 add_list_box(out_doc, "List Box ID", ["item 1", "item 2", "item 3"], ["item 1", "item 3"], out_page, Rectangle(left=50.0, bottom=160.0, right=210.0, top=240.0))
31 add_radio_button_group(out_doc, "Radio Button ID", ["A", "B", "C"], 0, out_page, Rectangle(left=50.0, bottom=120.0, right=210.0, top=140.0))
32 add_general_text_field(out_doc, "Text ID", "Text", out_page, Rectangle(left=50.0, bottom=80.0, right=210.0, top=100.0))
33
34 # Add page to output document
35 out_doc.pages.append(out_page)
36
37 # Copy remaining pages and append to output document
38 in_page_range = in_doc.pages[1:]
39 copied_pages = PageList.copy(out_doc, in_page_range, copy_options)
40 out_doc.pages.extend(copied_pages)
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
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Copy form fields
13 in_fields = in_doc.form_fields
14 out_fields = out_doc.form_fields
15 for key, in_field_node in in_fields.items():
16 out_fields[key] = FieldNode.copy(out_doc, in_field_node)
17
18 # Find the form field and update its value
19 selected_field = out_fields.lookup(field_identifier)
20 if selected_field:
21 fill_form_field(selected_field, field_value)
22
23 # Configure page copy options
24 copy_options = PageCopyOptions()
25 copy_options.form_fields = FormFieldCopyStrategy.COPY_AND_UPDATE_WIDGETS
26 copy_options.unsigned_signatures = CopyStrategy.REMOVE
27
28 # Copy all pages
29 copied_pages = PageList.copy(out_doc, in_doc.pages, copy_options)
30 out_doc.pages.extend(copied_pages)
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)
1# Define border
2border = 20
3
4# Open input document
5with io.FileIO(input_file_path, 'rb') as in_stream:
6 with Document.open(in_stream, None) as in_doc:
7
8 # Create font stream
9 with io.FileIO(font_path, 'rb') as font_stream:
10
11 # Create output document
12 with io.FileIO(output_file_path, 'wb+') as output_stream:
13 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
14
15 # Copy document-wide data
16 copy_document_data(in_doc, out_doc)
17
18 # Create embedded font in output document
19 font = Font.create(out_doc, font_stream, True)
20
21 # Define page copy options
22 copy_options = PageCopyOptions()
23
24 # Copy first page, add barcode, and append to output document
25 out_page = Page.copy(out_doc, in_doc.pages[0], copy_options)
26 add_barcode(out_doc, out_page, barcode, font, 50.0)
27 out_doc.pages.append(out_page)
28
29 # Copy remaining pages and append to output document
30 in_page_range = in_doc.pages[1:]
31 copied_pages = PageList.copy(out_doc, in_page_range, copy_options)
32 out_doc.pages.extend(copied_pages)
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(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(left=border, bottom=page.size.height - (data_matrix_size + border), right=data_matrix_size + border, top=page.size.height - border)
16
17 # Paint the positioned barcode text
18 generator.paint_image(data_matrix, rect)
1# Define border
2border = 40
3
4# Open input document
5with io.FileIO(input_file_path, 'rb') as in_stream:
6 with Document.open(in_stream, None) as in_doc:
7
8 # Create output document
9 with io.FileIO(output_file_path, 'wb+') as output_stream:
10 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
11
12 # Copy document-wide data
13 copy_document_data(in_doc, out_doc)
14
15 # Define page copy options
16 copy_options = PageCopyOptions()
17
18 # Copy first page, add datamatrix image, and append to output document
19 out_page = Page.copy(out_doc, in_doc.pages[0], copy_options)
20 add_data_matrix(out_doc, out_page, data_matrix_path)
21 out_doc.pages.append(out_page)
22
23 # Copy remaining pages and append to output document
24 in_page_range = in_doc.pages[1:]
25 copied_pages = PageList.copy(out_doc, in_page_range, copy_options)
26 out_doc.pages.extend(copied_pages)
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)
1# Open input document
2with io.FileIO(input_file_path, 'rb') as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, 'wb+') as output_stream:
7 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Define page copy options
13 copy_options = PageCopyOptions()
14
15 # Copy pages preceding selected page and append to output document
16 if page_number > 1:
17 in_page_range = in_doc.pages[:page_number - 1]
18 copied_pages = PageList.copy(out_doc, in_page_range, copy_options)
19 out_doc.pages.extend(copied_pages)
20
21 # Copy selected page, add image, and append to output document
22 out_page = Page.copy(out_doc, in_doc.pages[page_number - 1], copy_options)
23 add_image(out_doc, out_page, image_path, 150, 150)
24 out_doc.pages.append(out_page)
25
26 # Copy remaining pages and append to output document
27 in_page_range = in_doc.pages[page_number:]
28 copied_pages = PageList.copy(out_doc, in_page_range, copy_options)
29 out_doc.pages.extend(copied_pages)
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)
1# Open input document
2with io.FileIO(input_file_path, 'rb') as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, 'wb+') as output_stream:
7 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Get the device color space
13 color_space = ColorSpace.create_process_color_space(out_doc, ProcessColorSpaceType.RGB)
14
15 # Create paint object
16 paint = Paint.create(out_doc, color_space, [1.0, 0.0, 0.0], None)
17
18 # Define page copy options
19 copy_options = PageCopyOptions()
20
21 # Copy first page, add image mask, and append to output document
22 out_page = Page.copy(out_doc, in_doc.pages[0], copy_options)
23 add_image_mask(out_doc, out_page, image_mask_path, 250, 150)
24 out_doc.pages.append(out_page)
25
26 # Copy remaining pages and append to output document
27 in_page_range = in_doc.pages[1:]
28 copied_pages = PageList.copy(out_doc, in_page_range, copy_options)
29 out_doc.pages.extend(copied_pages)
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))
1class TolerantSortedSet:
2 def add(self, value: float):
3 for existing in self.data:
4 if abs(existing - value) < self.tolerance:
5 return # Do not add duplicate-like value
6
7 self.data.append(value)
8 self.data.sort(reverse=self.sort_reverse)
9
10 def iterator(self):
11 return iter(self.data)
12
13 def display(self):
14 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 global line_number
3
4 # Add line numbers to all text found in the input page to the output page
5
6 # The input and output page
7 in_page, out_page = pair
8
9 # Extract all text fragments
10 extractor = ContentExtractor(in_page.content)
11 extractor.ungrouping = UngroupingSelection.ALL
12
13 # The left-most horizontal position of all text fragments
14 left_x = in_page.size.width
15
16 # A comparison for doubles that considers distances smaller than the font size as equal
17 def comparison(a, b):
18 d = b - a
19 if abs(d) < font_size:
20 return 0
21 return (d > 0) - (d < 0) # return 1 if d > 0, -1 if d < 0, 0 otherwise
22
23 # A sorted set to hold the vertical positions of all text fragments
24 # Keep the data sorted in reverse order as the coordinates are reverse in a PDF
25 line_y_positions = create_tolerant_sorted_set(tolerance=font_size, sort_reverse=True)
26
27 # Iterate over all content elements of the input page
28 for element in extractor:
29 # Process only text elements
30 if isinstance(element, TextElement):
31 # Iterate over all text fragments
32 for fragment in element.text:
33 # Get the fragment's baseline starting point
34 point = fragment.transform.transform_point(
35 Point(fragment.bounding_box.left, 0)
36 )
37
38 # Update the left-most position
39 left_x = min(left_x, point.x)
40
41 # Add the vertical position
42 line_y_positions.add(point.y)
43
44 # If at least one text fragment was found, add line numbers
45 if line_y_positions:
46 # Create a text object and use a text generator
47 text = Text.create(out_doc)
48 with TextGenerator(text, line_number_font, font_size, None) as text_generator:
49 # Iterate over all vertical positions found in the input
50 for y in line_y_positions.iterator():
51 # The line number string
52 line_number += 1
53 line_number_string = str(line_number)
54
55 # The width of the line number string when shown on the page
56 width = text_generator.get_width(line_number_string)
57
58 # Position line numbers right-aligned
59 # with a given distance to the right-most horizontal position
60 # and at the vertical position of the current text fragment
61 text_generator.move_to(Point(left_x - width - distance, y))
62
63 # Show the line number string
64 text_generator.show(line_number_string)
65
66 # Use a content generator to paint the text onto the page
67 with ContentGenerator(out_page.content, False) as content_generator:
68 content_generator.paint_text(text)
1# Define global variables
2distance = 10
3font_size = 8.0
4line_number = 0
5
6# Open input document
7with io.FileIO(input_file_path, 'rb') as in_stream:
8 with Document.open(in_stream, None) as in_doc:
9
10 # Create output document
11 with io.FileIO(output_file_path, 'wb+') as output_stream:
12 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
13
14 # Copy document-wide data
15 copy_document_data(in_doc, out_doc)
16
17 # Create a font for the line numbers
18 lineNumberFont = Font.create_from_system(out_doc, "Arial", None, True)
19
20 # Define page copy options
21 copy_options = PageCopyOptions()
22
23 # Copy all pages from input to output document
24 in_pages = in_doc.pages
25 out_pages = PageList.copy(out_doc, in_pages, copy_options)
26
27 # Iterate over all input-output page pairs
28 pages = zip(in_pages, out_pages)
29 for pair in pages:
30 add_line_numbers(out_doc, lineNumberFont, pair)
31
32 out_doc.pages.extend(out_pages)
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)
1# Define global variables
2font_size = 50.0
3
4# Open input document
5with io.FileIO(input_file_path, 'rb') as in_stream:
6 with Document.open(in_stream, None) as in_doc:
7
8 # Create output document
9 with io.FileIO(output_file_path, 'wb+') as output_stream:
10 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
11
12 # Copy document-wide data
13 copy_document_data(in_doc, out_doc)
14
15 # Create font
16 font = Font.create_from_system(out_doc, "Arial", "Italic", True)
17
18 # Get the color space
19 color_space = ColorSpace.create_process_color_space(out_doc, ProcessColorSpaceType.RGB)
20
21 # Choose the RGB color value and transparency
22 color = [1.0, 0.0, 0.0]
23 transparency = Transparency(alpha)
24
25 # Create paint object with the chosen RGB color
26 paint = Paint.create(out_doc, color_space, color, transparency)
27
28 # Define copy options
29 copy_options = PageCopyOptions()
30
31 # Copy all pages from input document
32 for in_page in in_doc.pages:
33 # Copy page from input to output
34 out_page = Page.copy(out_doc, in_page, copy_options)
35
36 # Add text to page
37 add_stamp(out_doc, out_page, stamp_string)
38
39 # Add page to document
40 out_doc.pages.append(out_page)
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)
1# Define global variables
2border = 40.0
3font_size = 15.0
4
5# Open input document
6with io.FileIO(input_file_path, 'rb') as in_stream:
7 with Document.open(in_stream, None) as input_document:
8
9 # Create output document
10 with io.FileIO(output_file_path, 'wb+') as output_stream:
11 with Document.create(output_stream, input_document.conformance, None) as output_document:
12
13 # Copy document-wide data
14 copy_document_data(input_document, output_document)
15
16 # Create a font
17 font = Font.create_from_system(output_document, "Arial", "Italic", True)
18
19 # Define page copy options
20 copy_options = PageCopyOptions()
21
22 # Copy first page, add text, and append to output document
23 out_page = Page.copy(output_document, input_document.pages[0], copy_options)
24 add_text(output_document, out_page, text_string)
25 output_document.pages.append(out_page)
26
27 # Copy remaining pages and append to output document
28 inPageRange = input_document.pages[1:]
29 copied_pages = PageList.copy(output_document, inPageRange, copy_options)
30 output_document.pages.extend(copied_pages)
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)
1# Open input document
2with io.FileIO(input_file_path, 'rb') as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, 'wb+') as output_stream:
7 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Define page copy options
13 copy_options = PageCopyOptions()
14
15 # Copy all pages from input document
16 for in_page in in_doc.pages:
17 out_page = Page.copy(out_doc, in_page, copy_options)
18
19 # Add a line
20 add_line(out_doc, out_page)
21
22 # Add page to output document
23 out_doc.pages.append(out_page)
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}
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) if word_count > 1 else 0
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)
1# Define global variables
2BORDER = 50
3PAGE_SIZE = Size(width=595, height=842) # A4 page size in points
4
5# Create output document
6with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, None, None) as out_doc:
8
9 font = Font.create_from_system(out_doc, "Arial", "Italic", True)
10
11 # Create page
12 out_page = Page.create(out_doc, PAGE_SIZE)
13
14 # Add text as justified text
15 layout_text(out_doc, out_page, input_text_path, font, font_size=20)
16
17 # Add page to document
18 out_doc.pages.append(out_page)
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)
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Define page copy options
13 page_copy_options = PageCopyOptions()
14
15 # Create embedded font in the output document
16 font = Font.create_from_system(out_doc, "Arial", None, True)
17
18 # Copy all pages from input document
19 for page_number, in_page in enumerate(in_doc.pages, start=1):
20 # Copy page from input to output
21 out_page = Page.copy(out_doc, in_page, page_copy_options)
22
23 # Stamp page number on current page of output document
24 add_page_number(out_doc, out_page, font, page_number)
25
26 # Add page to output document
27 out_doc.pages.append(out_page)
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)
1# Open input and create output documents
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Process each page
13 for in_page in in_doc.pages:
14 # Create empty output page
15 out_page = Page.create(out_doc, in_page.size)
16 # Copy page content from input to output and remove glyphs
17 copy_content_and_remove_glyphs(in_page.content, out_page.content, out_doc)
18 # Add the new page to the output document's page list
19 out_doc.pages.append(out_page)
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)
1# Open input and create output documents
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Process each page
13 for in_page in in_doc.pages:
14 # Create empty output page
15 out_page = Page.create(out_doc, in_page.size)
16 # Copy page content from input to output and remove white text
17 copy_content_and_remove_white_text(in_page.content, out_page.content, out_doc)
18 # Add the new page to the output document's page list
19 out_doc.pages.append(out_page)
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)
1# Define global variables
2overall_transform = AffineTransform.get_identity()
3fragment = None
4search_string = "Muster Company AG"
5replacement_string = "Replacement String"
6
7# Open input document
8with io.FileIO(input_file_path, "rb") as in_stream:
9 with Document.open(in_stream, None) as in_doc:
10
11 # Create output document
12 with io.FileIO(output_file_path, "wb+") as out_stream:
13 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
14
15 # Copy document-wide data
16 copy_document_data(in_doc, out_doc)
17
18 # Process each page
19 for in_page in in_doc.pages:
20 # Create empty output page
21 out_page = Page.create(out_doc, in_page.size)
22 # Copy page content from input to output and search for string
23 copy_content_and_remove_text(in_page.content, out_page.content, out_doc, search_string)
24 # If the text was found and deleted, add the replacement text
25 if fragment:
26 add_text(out_doc, out_page, replacement_string)
27 # Add the new page to the output document's page list
28 out_doc.pages.append(out_page)
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 with open(self.input_path, "rb") as in_stream:
6 with Document.open(in_stream, self.pdf_password) as in_doc:
7 is_valid &= self.validate_conformance(in_doc.conformance)
8 is_valid &= self.validate_encryption(in_doc.permissions)
9 is_valid &= self.validate_pages_size(in_doc)
10 is_valid &= self.validate_fonts(in_doc)
11
12 return is_valid
13
14 def validate_file_size(self) -> bool:
15 file_size_in_mb = os.path.getsize(self.input_path) / (1024 * 1024)
16
17 if self.ini_file_size:
18 ini_file_size_in_mb = float(self.ini_file_size)
19 if file_size_in_mb > ini_file_size_in_mb:
20 print("The PDF file size exceeds the specified custom limit.")
21 return False
22 else:
23 print("The PDF file size does not exceed the specified custom limit.")
24 return True
25 return True
26
27 def validate_conformance(self, current_conformance: Conformance) -> bool:
28 if self.ini_max_pdf_version_str:
29 if ConformanceValidator.validate_conformance(self.ini_max_pdf_version_str, current_conformance):
30 print("The PDF version does not exceed the specified custom maximum version.")
31 return True
32 else:
33 print("The PDF version exceeds the specified custom maximum version.")
34 return False
35 return True
36
37 def validate_encryption(self, permissions: Permission) -> bool:
38 if self.ini_encryption:
39 encryption_required = self.ini_encryption.lower() == "true"
40 if encryption_required and not permissions:
41 print("Encryption not conform: the PDF file is not encrypted. The custom encryption value specifies that the PDF file should be encrypted.")
42 return False
43 elif not encryption_required and permissions:
44 print("Encryption not conform: the PDF file is encrypted. The custom encryption value specifies that the PDF file should not be encrypted.")
45 return False
46 else:
47 print("The PDF encryption is conform to the specified custom value.")
48 return True
49 return True
50
51 def validate_pages_size(self, in_doc: Document) -> bool:
52 is_valid = True
53
54 if self.ini_max_page_size is not None:
55 page_number = 0
56 for page in in_doc.pages:
57 page_number += 1
58 size_with_int = Size(
59 width=int(page.size.width), height=int(page.size.height)
60 )
61 is_valid &= self.validate_page_size(page_number, size_with_int)
62
63 return is_valid
64
65 def validate_page_size(self, page_number: int, page_size: Size) -> bool:
66 if self.ini_max_page_size is not None:
67 validator = create_page_size_validator(self.ini_max_page_size, self.size_tolerance)
68 if validator.validate_page_size(page_size):
69 print(
70 f"The size of page {page_number} is within the specified custom maximum page size value."
71 )
72 return True
73 else:
74 print(
75 f"The size of page {page_number} exceeds the specified custom maximum page size value."
76 )
77 return False
78
79 return True
80
81 def validate_fonts(self, in_doc: Document) -> bool:
82 is_valid = True
83
84 if self.ini_embedding:
85 embedding_required = self.ini_embedding.lower() == "true"
86
87 for page_number in range(len(in_doc.pages)):
88 page_number += 1
89 page = in_doc.pages[page_number-1]
90
91 extractor = ContentExtractor(page.content)
92 extractor.ungrouping = UngroupingSelection.ALL
93
94 for element in extractor:
95 if isinstance(element, TextElement):
96 for fragment in element.text:
97 font_name = fragment.font.base_font
98 is_embedded = fragment.font.is_embedded
99
100 # Check if the font is in the exception list
101 is_current_font_an_exception = any(
102 re.match(exc.replace("*", ".*"), font_name, re.IGNORECASE)
103 for exc in self.embedding_exception_fonts
104 )
105
106 # Validate based on the embedding setting
107 if (embedding_required and not is_embedded and not is_current_font_an_exception) or (
108 not embedding_required and is_embedded and not is_current_font_an_exception
109 ):
110 is_valid = False
111 status_text = "be embedded" if embedding_required else "not be embedded"
112 print(
113 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."
114 )
115 else:
116 status_text = (
117 "in the exception list" if embedding_required != is_embedded
118 else "embedded" if is_embedded
119 else "not be embedded"
120 )
121 print(
122 f"The font '{font_name}' on page {page_number} is conform to the 'Embedding' property as it is {status_text}."
123 )
124 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 document_validator.size_tolerance = ini_file.get_value("Pages", "SizeTolerance", "3.0")
10 document_validator.ini_max_page_size = ini_file.get_value("Pages", "MaxPageSize")
11 document_validator.ini_max_pdf_version_str = ini_file.get_value("File", "MaxPdfVersion")
12 document_validator.ini_encryption = ini_file.get_value("File", "Encryption")
13 document_validator.ini_file_size = ini_file.get_value("File", "FileSize")
14 document_validator.ini_embedding = ini_file.get_value("Fonts", "Embedding")
15 document_validator.embedding_exception_fonts = ini_file.get_keys_matching_pattern("Fonts", r"EmbeddingExcFont\d+")
16
17 return document_validator
1class PageSizeValidator:
2 named_page_sizes = {
3 "Letter": Size(width=612, height=792),
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),
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),
16 }
17
18 def parse_page_size(self, max_page_size: str) -> Size:
19 named_size = self.named_page_sizes.get(max_page_size)
20 if named_size:
21 return named_size
22
23 match = re.match(
24 r"(\d+(\.\d+)?)\s*x\s*(\d+(\.\d+)?)(\s*(pt|in|cm|mm))?", max_page_size, re.IGNORECASE
25 )
26 if not match:
27 raise ValueError(f"Invalid MaxPageSize format: {max_page_size}")
28
29 width = float(match.group(1))
30 height = float(match.group(3))
31 unit = match.group(6).lower() if match.group(6) else "pt"
32
33 if unit == "in":
34 return Size(width=int(width * 72), height=int(height * 72))
35 elif unit == "cm":
36 return Size(width=int(width * 28.3465), height=int(height * 28.3465))
37 elif unit == "mm":
38 return Size(width=int(width * 2.83465), height=int(height * 2.83465))
39 elif unit in ["pt", ""]:
40 return Size(width=int(width), height=int(height))
41 else:
42 raise ValueError(f"Unsupported unit: {unit}")
43
44 def parse_size_tolerance(self, size_tolerance_str: str) -> float:
45 if not size_tolerance_str:
46 return 3.0
47
48 match = re.match(r"(\d+(\.\d+)?)\s*(%)?", size_tolerance_str, re.IGNORECASE)
49 if not match:
50 raise ValueError(f"Invalid SizeTolerance format: {size_tolerance_str}")
51
52 value = float(match.group(1))
53 return value / 100.0 if match.group(3) else value
54
55 def validate_page_size(self, page_size: Size) -> bool:
56 is_valid = (
57 (page_size.width <= self.max_size.width + self.size_tolerance
58 and page_size.height <= self.max_size.height + self.size_tolerance
59 ) or
60 (page_size.height <= self.max_size.width + self.size_tolerance
61 and page_size.width <= self.max_size.height + self.size_tolerance)
62 )
63 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 version_parts = version.split(".")
17 if len(version_parts) == 2:
18 major_minor_version = f"{version_parts[0]}.{version_parts[1]}"
19 conformance = ConformanceValidator.version_map.get(major_minor_version)
20 if conformance:
21 return conformance
22 raise ValueError(f"Unsupported version or conformance level: {version}")
23
24 @staticmethod
25 def validate_conformance(max_pdf_version_str: str, current_conformance: Conformance) -> bool:
26 max_pdf_conformance = ConformanceValidator.parse_version_string(max_pdf_version_str)
27 current_conformance_version = ConformanceValidator.get_version_from_conformance(current_conformance)
28 return current_conformance_version.value <= max_pdf_conformance.value
29
30 @staticmethod
31 def get_version_from_conformance(conformance: Conformance) -> Conformance:
32 if conformance in ConformanceValidator.version_map.values():
33 return conformance
34 if conformance in {Conformance.PDF_A1_A, Conformance.PDF_A1_B}:
35 return Conformance.PDF14
36 if conformance in {
37 Conformance.PDF_A2_A,
38 Conformance.PDF_A2_B,
39 Conformance.PDF_A2_U,
40 Conformance.PDF_A3_A,
41 Conformance.PDF_A3_B,
42 Conformance.PDF_A3_U,
43 }:
44 return Conformance.PDF17
45 raise ValueError(f"Unsupported conformance level: {conformance}")
1ini_file = open_ini_file(ini_path)
2document_validator = create_document_validator(ini_file, input_file_path, pdf_password)
3if document_validator.validate_document():
4 print("\nThe document does conform the specified properties.")
5else:
6 print("\nThe document does not conform the specified properties.")
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}
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))
1# Open input document
2with io.FileIO(input_file_path, 'rb') as content_pdf_stream:
3 with Document.open(content_pdf_stream, None) as content_pdf_document:
4
5 # Create output document
6 with io.FileIO(output_file_path, 'wb+') as output_stream:
7 with Document.create(output_stream, content_pdf_document.conformance, None) as output_document:
8 # Copy document-wide data
9 copy_document_data(content_pdf_document, output_document)
10
11 # Set Metadata
12 if metadata_file_path is not None:
13 with io.FileIO(metadata_file_path, 'rb') as metadata_stream:
14 if metadata_file_path.endswith(".pdf"):
15 # Use the metadata of another PDF file
16 with Document.open(metadata_stream, "") as meta_doc:
17 mdata = Metadata.copy(output_document, meta_doc.metadata)
18 else:
19 # Use the content of an XMP metadata file
20 mdata = Metadata.create(output_document, metadata_stream)
21 else:
22 mdata = output_document.metadata
23 mdata.author = "Your Author"
24 mdata.title = "Your Title"
25 mdata.subject = "Your Subject"
26 mdata.creator = "Your Creator"
27
28 output_document.metadata = mdata
29
30 # Define page copy options
31 copy_options = PageCopyOptions()
32
33 # Copy all pages and append to output document
34 copied_pages = PageList.copy(output_document, content_pdf_document.pages, copy_options)
35 output_document.pages.extend(copied_pages)
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}
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# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create encryption parameters
6 encryption_params = Encryption(
7 user_pwd,
8 owner_pwd,
9 Permission.PRINT | Permission.DIGITAL_PRINT,
10 )
11
12 # Create output document and set a user and owner password
13 with io.FileIO(output_file_path, "wb+") as out_stream:
14 with Document.create(out_stream, in_doc.conformance, encryption_params) as out_doc:
15
16 # Copy document-wide data
17 copy_document_data(in_doc, out_doc)
18
19 # Define page copy options
20 copy_options = PageCopyOptions()
21
22 # Copy all pages and append to output document
23 copied_pages = PageList.copy(out_doc, in_doc.pages, copy_options)
24 out_doc.pages.extend(copied_pages)
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}
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# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Set form field flattening options
13 copy_options = PageCopyOptions()
14 copy_options.form_fields = FormFieldCopyStrategy.FLATTEN
15
16 # Copy all pages with flattening options
17 copied_pages = PageList.copy(out_doc, in_doc.pages, copy_options)
18 out_doc.pages.extend(copied_pages)
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
1# Create output document
2with open(output_file_path, "wb+") as out_stream:
3 with Document.create(out_stream, None, None) as out_doc:
4 # Create embedded font in output document
5 font = Font.create_from_system(out_doc, "Arial", None, True)
6
7 # Define page copy options
8 page_copy_options = PageCopyOptions()
9
10 # List of copied pages that will be added to the table of contents
11 toc_entries = []
12
13 # A page number counter
14 page_number = 2
15
16 # Copy all input documents pages
17 for input_path in input_paths:
18 # Open input document
19 with open(input_path, "rb") as in_stream:
20 with Document.open(in_stream, None) as in_doc:
21
22 # Copy all pages and append to output document
23 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
24
25 for copied_page in copied_pages:
26 add_page_number(out_doc, copied_page, font, page_number)
27 page_number += 1
28
29 # Create outline item
30 title = in_doc.metadata.title or os.path.splitext(os.path.basename(input_path))[0]
31 toc_entries.append((title, copied_pages))
32
33 # Create table of contents page
34 contents_page = create_table_of_contents(out_doc, toc_entries, font)
35 add_page_number(out_doc, contents_page, font, 1)
36
37 # Add pages to the output document
38 out_doc.pages.append(contents_page)
39 for _, pages in toc_entries:
40 out_doc.pages.extend(pages)
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_file_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)
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_file_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))
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 = ProcessColorSpaceType.GRAY
7 color = [0.9]
8 alpha = 1.0
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)
1# Parse the color options
2color, color_type, color_alpha = parse_options(options)
3
4# Open the input and create the output document
5with open(input_file_path, "rb") as in_stream:
6 with Document.open(in_stream, None) as in_doc:
7
8 # Create output document
9 with open(output_file_path, "wb+") as out_stream:
10 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
11
12 # Copy document-wide data
13 copy_document_data(in_doc, out_doc)
14
15 # Apply the overlay
16 apply_overlay_to_pages(in_doc, out_doc, color, color_type, color_alpha)
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}
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))
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Define page copy options
13 page_copy_options = PageCopyOptions()
14
15 # Copy all pages and append to output document
16 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
17 out_doc.pages.extend(copied_pages)
18
19 # Set info entry
20 metadata = Metadata.copy(out_doc, in_doc.metadata)
21 if key == "Title":
22 metadata.title = value
23 elif key == "Author":
24 metadata.author = value
25 elif key == "Subject":
26 metadata.subject = value
27 elif key == "Keywords":
28 metadata.keywords = value
29 elif key == "CreationDate":
30 # Use of the ISO 8601 format for the date
31 date_format = "%Y-%m-%dT%H:%M:%S"
32 parsed_date = datetime.strptime(value, date_format)
33 metadata.creation_date = parsed_date
34 elif key == "ModDate":
35 raise Exception("ModDate cannot be set.")
36 elif key == "Creator":
37 metadata.creator = value
38 elif key == "Producer":
39 raise Exception("Producer is set by means of the license key.")
40 else:
41 metadata.custom_entries[key] = value
42
43 # Assign modified metadata to the output document
44 out_doc.metadata = metadata
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}
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))
1destination_page_number = int(page_number)
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 if destination_page_number < 1 or destination_page_number > len(in_doc.pages):
8 raise ValueError("Given page number is invalid")
9
10 # Create output document
11 with io.FileIO(output_file_path, "wb+") as out_stream:
12 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
13
14 # Copy document-wide data
15 copy_document_data(in_doc, out_doc)
16
17 # Define page copy options
18 page_copy_options = PageCopyOptions()
19
20 # Copy all pages and append to output document
21 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
22 out_doc.pages.extend(copied_pages)
23
24 # Add open destination
25 out_page = copied_pages[destination_page_number - 1]
26 out_doc.open_destination = LocationZoomDestination.create(out_doc, out_page, 0, out_page.size.height, None)
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}
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))
1start_index = int(first_page) - 1
2last_page = int(last_page)
3count = last_page - start_index
4
5# Open input document
6with io.FileIO(input_file_path, "rb") as in_stream:
7 with Document.open(in_stream, None) as in_doc:
8
9 # Validate page range
10 start_index = max(min(len(in_doc.pages) - 1, start_index), 0)
11 count = min(len(in_doc.pages) - start_index, count)
12 if count <= 0:
13 raise ValueError("lastPage must be greater or equal to firstPage")
14
15 # Create output document
16 with io.FileIO(output_file_path, "wb+") as out_stream:
17 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
18
19 # Copy document-wide data
20 copy_document_data(in_doc, out_doc)
21
22 # Define page copy options
23 page_copy_options = PageCopyOptions()
24
25 # Get page range from input pages
26 in_page_range = in_doc.pages[start_index:last_page]
27
28 # Copy page range and append to output document
29 out_page_range = PageList.copy(out_doc, in_page_range, page_copy_options)
30 out_doc.pages.extend(out_page_range)
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
1# Get the level from the arguments, default to 1 if not provided
2level = int(level)
3if level < 1:
4 raise ValueError("The level must be greater than zero.")
5
6# Ensure the output directory exists
7os.makedirs(output_dir, exist_ok=True)
8
9# Open input document
10with io.FileIO(input_file_path, "rb") as in_stream:
11 with Document.open(in_stream, None) as in_doc:
12
13 # Collect all outline items at the given level
14 outlines = get_outlines(in_doc.outline, level)
15
16 # Collect all page ranges corresponding to the given outline items
17 parts = get_parts(in_doc.pages, outlines)
18
19 # Iterate over all collected parts
20 for page_list, outline_item in parts:
21 # Turn the outline item's title into a valid file name
22 file_name = "".join([c if c.isalnum() or c in "._-" else "_" for c in outline_item.title.replace("\x00", "")]) + ".pdf"
23 file_path = os.path.join(output_dir, file_name)
24
25 # Create output document
26 with io.FileIO(file_path, "wb+") as out_stream:
27 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
28 # Copy document-wide data
29 copy_document_data(in_doc, out_doc)
30
31 # Define page copy options
32 page_copy_options = PageCopyOptions()
33 page_copy_options.copy_outline_items = False
34
35 # Copy the pages and add to the output document's page list
36 out_pages = PageList.copy(out_doc, page_list, page_copy_options)
37 out_doc.pages.extend(out_pages)
38
39 # Copy child outline items
40 outline_copy_options = OutlineCopyOptions()
41 for child in outline_item.children:
42 out_doc.outline.append(OutlineItem.copy(out_doc, child, outline_copy_options))
Document Structure
Create tagged PDF
1// Create output document
2using (Stream outStream = new FileStream(outPath, FileMode.Create, FileAccess.ReadWrite))
3using (Document outDoc = Document.Create(outStream, Conformance.Pdf17, null))
4{
5 // Create a font
6 Font font = CreateFontWithFallbacks(outDoc, ARIAL_AND_FALLBACKS);
7
8 outDoc.Language = "en";
9 outDoc.SetPdfUaConformant();
10 outDoc.Metadata.Title = "TaggedPDF";
11 outDoc.ViewerSettings.DisplayDocumentTitle = true;
12
13 // Create a page
14 Size pageSize = new Size { Width = ToPoints(21, "cm"), Height = ToPoints(29.7, "cm") }; // DIN A4
15 Page outPage = Page.Create(outDoc, pageSize);
16 CreateAndTagContent(outDoc, outPage, imagePath, font);
17 outDoc.Pages.Add(outPage);
18}
1private static void CreateAndTagContent(Document outputDoc, Page outPage, string imagePath, Font font)
2{
3 using (ContentGenerator gen = new ContentGenerator(outPage.Content, false))
4 {
5 Tree structTree = new Tree(outputDoc);
6 Node docNode = structTree.DocumentNode;
7 Node sectionNode = new Node("Sect", outputDoc, outPage);
8 docNode.Children.Add(sectionNode);
9
10 // Start from the top of the page with margin
11 double currentY = outPage.Size.Height - MARGIN;
12
13 // Create header
14 NodeAndPosition np = CreateAndTagText(
15 outputDoc,
16 outPage,
17 gen,
18 sectionNode,
19 font,
20 currentY,
21 "H1",
22 "This is a properly tagged heading",
23 24.0
24 );
25
26 // Add padding and create paragraph
27 currentY = np.position;
28 currentY -= PADDING;
29 np = CreateAndTagText(
30 outputDoc,
31 outPage,
32 gen,
33 sectionNode,
34 font,
35 currentY,
36 "P",
37 "This is a properly tagged paragraph. Both heading and paragraph belong to a section.",
38 12.0
39 );
40
41 // Add padding and create image
42 currentY = np.position;
43 currentY -= PADDING;
44 CreateAndTagImage(outputDoc, outPage, gen, imagePath, currentY, np.node);
45 }
46}
1/// <summary>
2/// Create and tag a text element (header, paragraph, etc.).
3/// </summary>
4/// <param name="outputDoc">The output document</param>
5/// <param name="outPage">The output page</param>
6/// <param name="gen">The content generator</param>
7/// <param name="sectionNode">The section node to add the text element to</param>
8/// <param name="font">The font to use</param>
9/// <param name="topY">Y coordinate for the top of this element</param>
10/// <param name="tagName">PDF structure tag name (e.g., "H1", "P")</param>
11/// <param name="textContent">The text content to display</param>
12/// <param name="fontSize">Font size in points</param>
13/// <returns>Bottom Y coordinate of this element and created node</returns>
14private static NodeAndPosition CreateAndTagText(
15 Document outputDoc,
16 Page outPage,
17 ContentGenerator gen,
18 Node sectionNode,
19 Font font,
20 double topY,
21 string tagName,
22 string textContent,
23 double fontSize)
24{
25 Node textNode = new Node(tagName, outputDoc, outPage);
26 textNode.ActualText = textContent;
27 textNode.Language = "en";
28 gen.TagAs(textNode);
29 Text text = Text.Create(outputDoc);
30 sectionNode.Children.Add(textNode);
31
32 // Calculate text baseline position
33 double baselineY = topY - fontSize * font.Ascent;
34
35 using (TextGenerator textGen = new TextGenerator(text, font, fontSize, null))
36 {
37 Point position = new Point { X = MARGIN, Y = baselineY };
38 textGen.MoveTo(position);
39 textGen.ShowLine(textNode.ActualText);
40 }
41
42 gen.PaintText(text);
43 gen.StopTagging();
44
45 // Return bottom coordinate (baseline - descent)
46 return new NodeAndPosition(baselineY - fontSize * font.Descent, textNode);
47}
1/// <summary>
2/// Create and tag an image element.
3/// </summary>
4/// <param name="outputDoc">The output document</param>
5/// <param name="outPage">The output page</param>
6/// <param name="gen">The content generator</param>
7/// <param name="imagePath">Path to the image file</param>
8/// <param name="topY">Y coordinate for the top of this element</param>
9/// <param name="parent">Parent node</param>
10/// <returns>Bottom Y coordinate of this element</returns>
11private static double CreateAndTagImage(Document outputDoc, Page outPage, ContentGenerator gen,
12 string imagePath, double topY, Node parent)
13{
14 Node figureNode = new Node("Figure", outputDoc, outPage);
15 figureNode.AlternateText = "PdfTools AG Logo";
16 parent.Children.Add(figureNode);
17
18 figureNode.Language = "en";
19
20 figureNode.SetStringAttribute("O", "Layout");
21
22 gen.TagAs(figureNode);
23
24 Image image;
25 try
26 {
27 using (Stream inImage = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
28 {
29 image = Image.Create(outputDoc, inImage);
30 }
31 }
32 catch (Exception e)
33 {
34 throw new InvalidOperationException(
35 "Failed to create image from file " + imagePath + ": " + e.Message + ". " +
36 "Please ensure the file is a valid image format (PNG, JPEG, etc.).");
37 }
38
39 double x = MARGIN;
40 double width = ToPoints(2.0, "cm");
41 double height = width * image.Size.Height / image.Size.Width; // preserve aspect ratio
42
43 Rectangle rect = new Rectangle
44 {
45 Left = x, // left
46 Bottom = topY - height, // bottom (Rectangle coordinates: bottom is lower than top)
47 Right = x + width, // right
48 Top = topY // top
49 };
50
51 figureNode.BoundingBox = rect;
52
53 gen.PaintImage(image, rect);
54 gen.StopTagging();
55
56 // Return bottom coordinate
57 return topY - height;
58}
1/// <summary>
2/// Try to create a font using common font names that are likely to be available
3/// on Windows, Linux, and Mac systems. Throws an exception if no font can be created.
4/// </summary>
5private static Font CreateFontWithFallbacks(Document document, string[] fontAndFallbacks)
6{
7 foreach (string fontName in fontAndFallbacks)
8 {
9 try
10 {
11 Font font = Font.CreateFromSystem(document, fontName, "", true);
12 if (font != null)
13 {
14 return font;
15 }
16 }
17 catch (Exception)
18 {
19 // Try next font
20 }
21 }
22
23 // If we get here, no font worked
24 throw new InvalidOperationException(
25 "Unable to create font. Tried the following fonts: " + string.Join(", ", fontAndFallbacks) + ". " +
26 "Please ensure you have at least one of these fonts installed on your system.");
27}
1/// <summary>
2/// Convert measurement from inches or centimeters to points.
3/// </summary>
4/// <param name="value">The measurement value</param>
5/// <param name="unit">Unit of measurement ("in" for inches, "cm" for centimeters)</param>
6/// <returns>Value converted to points (1 inch = 72 points, 1 cm ≈ 28.35 points)</returns>
7private static double ToPoints(double value, string unit)
8{
9 if (unit == "in")
10 {
11 return value * 72.0; // 1 inch = 72 points
12 }
13 else if (unit == "cm")
14 {
15 return value * 28.346456693; // 1 cm = 28.346456693 points (72/2.54)
16 }
17 else
18 {
19 throw new ArgumentException(
20 "Unsupported unit " + unit + ". Use 'in' for inches or 'cm' for centimeters.", nameof(unit));
21 }
22}
1// Create a PDF document
2try (FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW);
3 Document outDoc = Document.create(outStream, Conformance.PDF17, null)) {
4
5 // Create a font
6 Font font = createFontWithFallbacks(outDoc, ARIAL_AND_FALLBACKS);
7
8 outDoc.setLanguage("en");
9 outDoc.setPdfUaConformant();
10 outDoc.getMetadata().setTitle("TaggedPDF");
11 outDoc.getViewerSettings().setDisplayDocumentTitle(true);
12
13 // Create a page
14 Size pageSize = new Size(toPoints(21, "cm"), toPoints(29.7, "cm")); // DIN A4
15 Page outPage = Page.create(outDoc, pageSize);
16 createAndTagContent(outDoc, outPage, imagePath, font);
17 outDoc.getPages().add(outPage);
18}
19
20
1private static void createAndTagContent(Document outDoc, Page outPage, String imagePath, Font font) throws Exception {
2 try (ContentGenerator gen = new ContentGenerator(outPage.getContent(), false)) {
3 Tree structTree = new Tree(outDoc);
4 Node docNode = structTree.getDocumentNode();
5 Node sectionNode = new Node("Sect", outDoc, outPage);
6 docNode.getChildren().add(sectionNode);
7
8 // Start from the top of the page with margin
9 double currentY = outPage.getSize().getHeight() - MARGIN;
10
11 // Create header
12 NodeAndPosition np = createAndTagText(
13 outDoc,
14 outPage,
15 gen,
16 sectionNode,
17 font,
18 currentY,
19 "H1",
20 "This is a properly tagged heading",
21 24.0
22 );
23
24 // Add padding and create paragraph
25 currentY = np.position;
26 currentY -= PADDING;
27 np = createAndTagText(
28 outDoc,
29 outPage,
30 gen,
31 sectionNode,
32 font,
33 currentY,
34 "P",
35 "This is a properly tagged paragraph. Both heading and paragraph belong to a section.",
36 12.0
37 );
38
39 // Add padding and create image
40 currentY = np.position;
41 currentY -= PADDING;
42 createAndTagImage(outDoc, outPage, gen, imagePath, currentY, np.node);
43 }
44}
1/**
2 * Create and tag a text element (header, paragraph, etc.).
3 *
4 * @param outDoc The output document
5 * @param outPage The output page
6 * @param gen The content generator
7 * @param sectionNode The section node to add the text element to
8 * @param font The font to use
9 * @param topY Y coordinate for the top of this element
10 * @param tagName PDF structure tag name (e.g., "H1", "P")
11 * @param textContent The text content to display
12 * @param fontSize Font size in points
13 * @return Bottom Y coordinate of this element and created node
14 */
15private static NodeAndPosition createAndTagText(
16 Document outDoc,
17 Page outPage,
18 ContentGenerator gen,
19 Node sectionNode,
20 Font font,
21 double topY,
22 String tagName,
23 String textContent,
24 double fontSize) throws Exception {
25
26 Node textNode = new Node(tagName, outDoc, outPage);
27 textNode.setActualText(textContent);
28 textNode.setLanguage("en");
29 gen.tagAs(textNode);
30 Text text = Text.create(outDoc);
31 sectionNode.getChildren().add(textNode);
32
33 // Calculate text baseline position
34 double baselineY = topY - fontSize * font.getAscent();
35
36 try (TextGenerator textGen = new TextGenerator(text, font, fontSize, null)) {
37 Point position = new Point(MARGIN, baselineY);
38 textGen.moveTo(position);
39 textGen.showLine(textNode.getActualText());
40 }
41 gen.paintText(text);
42 gen.stopTagging();
43
44 // Return bottom coordinate (baseline - descent)
45 return new NodeAndPosition(textNode, baselineY - fontSize * font.getDescent());
46}
1/**
2 * Create and tag an image element.
3 *
4 * @param outDoc The output document
5 * @param outPage The output page
6 * @param gen The content generator
7 * @param imagePath Path to the image file
8 * @param topY Y coordinate for the top of this element
9 * @param parent Parent node
10 * @return Bottom Y coordinate of this element
11 */
12private static double createAndTagImage(
13 Document outDoc,
14 Page outPage,
15 ContentGenerator gen,
16 String imagePath,
17 double topY, Node parent) throws Exception {
18
19 Node figureNode = new Node("Figure", outDoc, outPage);
20 figureNode.setAlternateText("PdfTools AG Logo");
21 gen.tagAs(figureNode);
22
23 figureNode.setLanguage("en");
24 figureNode.setStringAttribute("O", "Layout");
25
26 Image image;
27 try (FileStream inImage = new FileStream(imagePath, FileStream.Mode.READ_ONLY)) {
28 image = Image.create(outDoc, inImage);
29 } catch (Exception e) {
30 throw new RuntimeException(
31 String.format("Failed to create image from file '%s': %s. " +
32 "Please ensure the file is a valid image format (PNG, JPEG, etc.).",
33 imagePath, e.getMessage())
34 );
35 }
36
37 double x = MARGIN;
38 double width = toPoints(2.0, "cm");
39 double height = width * image.getSize().getHeight() / image.getSize().getWidth(); // preserve aspect ratio
40
41 Rectangle rect = new Rectangle(
42 x, // left
43 topY - height, // bottom (Rectangle coordinates: bottom is lower than top)
44 x + width, // right
45 topY // top
46 );
47
48 figureNode.setBoundingBox(rect);
49
50 parent.getChildren().add(figureNode);
51
52 gen.paintImage(image, rect);
53 gen.stopTagging();
54
55 // Return bottom coordinate
56 return topY - height;
57}
1/**
2 * Try to create a font using common font names that are likely to be available
3 * on Windows, Linux, and Mac systems. Throws an exception if no font can be created.
4 */
5private static Font createFontWithFallbacks(Document document, String[] fontAndFallbacks) {
6 for (String fontName : fontAndFallbacks) {
7 try {
8 Font font = Font.createFromSystem(document, fontName, "", true);
9 if (font != null) {
10 return font;
11 }
12 } catch (Exception e) {
13 // Try next font
14 }
15 }
16
17 // If we get here, no font worked
18 throw new RuntimeException(
19 String.format("Unable to create font. Tried the following fonts: %s. " +
20 "Please ensure you have at least one of these fonts installed on your system.",
21 String.join(", ", ARIAL_AND_FALLBACKS))
22 );
23}
1def to_points(value: float, unit: str = "cm") -> float:
2 """
3 Convert measurement from inches or centimeters to points.
4
5 Args:
6 value: The measurement value
7 unit: Unit of measurement ("in" for inches, "cm" for centimeters)
8
9 Returns:
10 Value converted to points (1 inch = 72 points, 1 cm ≈ 28.35 points)
11 """
12 if unit == "in":
13 return value * 72.0 # 1 inch = 72 points
14 elif unit == "cm":
15 return value * 28.346456693 # 1 cm = 28.346456693 points (72/2.54)
16 else:
17 raise ValueError(
18 f"Unsupported unit '{unit}'. Use 'in' for inches or 'cm' for centimeters."
19 )
1# Look & Feel
2MARGIN = to_points(2.5, "cm")
3PADDING = to_points(1, "cm")
4ARIAL_AND_FALLBACKS = [
5 "Arial", # Common on Windows, available on most systems
6 "Liberation Sans", # Common on Linux
7 "DejaVu Sans", # Common on Linux
8 "Helvetica", # Common on macOS
9 "sans-serif", # Generic fallback
10]
1def create_font_with_fallbacks(
2 document: Document, font_and_fallbacks: list[str]
3) -> Font:
4 """
5 Try to create a font using common font names that are likely to be available
6 on Windows, Linux, and Mac systems. Raises an exception if no font can be created.
7 """
8 for font_name in font_and_fallbacks:
9 try:
10 font = Font.create_from_system(document, font_name, "", True)
11 if font is not None:
12 return font
13 except Exception:
14 # Try next font
15 continue
16
17 # If we get here, no font worked
18 raise RuntimeError(
19 f"Unable to create font. Tried the following fonts: {', '.join(font_and_fallbacks)}. "
20 "Please ensure you have at least one of these fonts installed on your system."
21 )
1def create_and_tag_text(
2 out_doc: Document,
3 out_page: Page,
4 gen: ContentGenerator,
5 section_node: Node,
6 font: Font,
7 top_y: float,
8 tag_name: str,
9 text_content: str,
10 font_size: float,
11) -> float:
12 """
13 Create and tag a text element (header, paragraph, etc.).
14
15 Args:
16 top_y: Y coordinate for the top of this element
17 tag_name: PDF structure tag name (e.g., "H1", "P")
18 text_content: The text content to display
19 font_size: Font size in points
20
21 Returns:
22 Bottom Y coordinate of this element
23 """
24 text_node = Node(tag_name, out_doc, out_page)
25 text_node.actual_text = text_content
26 gen.tag_as(text_node)
27 text = Text.create(out_doc)
28 section_node.children.append(text_node)
29
30 text_node.language = "en"
31
32 # Calculate text baseline position
33 baseline_y = top_y - font_size * font.ascent
34
35 with TextGenerator(text, font, font_size, None) as text_gen:
36 position = Point(MARGIN, baseline_y)
37 text_gen.move_to(position)
38 text_gen.show_line(text_node.actual_text)
39 gen.paint_text(text)
40 gen.stop_tagging()
41
42 # Return bottom coordinate (baseline - descent)
43 return text_node, baseline_y - font_size * font.descent
1def create_and_tag_image(
2 out_doc: Document,
3 out_page: Page,
4 gen: ContentGenerator,
5 input_image_path: str,
6 top_y: float,
7 parent: Node
8) -> float:
9 """
10 Create and tag an image element.
11
12 Args:
13 top_y: Y coordinate for the top of this element
14
15 Returns:
16 Bottom Y coordinate of this element
17 """
18
19 figure_node = Node("Figure", out_doc, out_page)
20 figure_node.alternate_text = "PdfTools AG Logo"
21 figure_node.language = "en"
22 figure_node.set_string_attribute("O", "Layout")
23 gen.tag_as(figure_node)
24
25 try:
26 with io.FileIO(input_image_path, "rb") as in_image:
27 image = Image.create(out_doc, in_image)
28 except Exception as e:
29 raise RuntimeError(
30 f"Failed to create image from file '{input_image_path}': {str(e)}. "
31 "Please ensure the file is a valid image format (PNG, JPEG, etc.)."
32 )
33
34 x = MARGIN
35 width = to_points(2.0, "cm")
36 height = width * image.size.height / image.size.width # preserve aspect ratio
37
38 rect = Rectangle(
39 left=x,
40 bottom=top_y - height, # Rectangle coordinates: bottom is lower than top
41 right=x + width,
42 top=top_y,
43 )
44 gen.paint_image(image, rect)
45 gen.stop_tagging()
46
47 figure_node.bounding_box = rect
48
49 parent.children.append(figure_node)
50
51 # Return bottom coordinate
52 return top_y - height
1def create_and_tag_content(
2 out_doc: Document,
3 out_page: Page,
4 input_image_path: str,
5 font: Font,
6):
7 with ContentGenerator(out_page.content, False) as gen:
8 struct_tree = Tree(out_doc)
9 doc_node = struct_tree.document_node
10 section_node = Node("Sect", out_doc, out_page)
11 doc_node.children.append(section_node)
12
13 # Start from the top of the page with margin
14 current_y = out_page.size.height - MARGIN
15
16 # Create header
17 node, current_y = create_and_tag_text(
18 out_doc,
19 out_page,
20 gen,
21 section_node,
22 font,
23 current_y,
24 "H1",
25 "This is a properly tagged heading",
26 24.0,
27 )
28
29 # Add padding and create paragraph
30 current_y -= PADDING
31 node, current_y = create_and_tag_text(
32 out_doc,
33 out_page,
34 gen,
35 section_node,
36 font,
37 current_y,
38 "P",
39 "This is a properly tagged paragraph. Both heading and paragraph belong to a section.",
40 12.0,
41 )
42
43 # Add padding and create image
44 current_y -= PADDING
45 create_and_tag_image(out_doc, out_page, gen, input_image_path, current_y, node)
1# Check if image file exists
2if not os.path.isfile(input_image_path):
3 raise FileNotFoundError(
4 f"Image file not found: '{input_image_path}'. "
5 "Please ensure the image file exists and the path is correct."
6 )
7# Create a PDF document
8with io.FileIO(output_file_path, "wb+") as out_stream:
9 with Document.create(out_stream, Conformance.PDF17, None) as out_doc:
10 # Create a font
11 font = create_font_with_fallbacks(out_doc, ARIAL_AND_FALLBACKS)
12
13 out_doc.language = "en"
14 out_doc.set_pdf_ua_conformant()
15 out_doc.metadata.title = "TaggedPDF"
16 out_doc.viewer_settings.display_document_title = True
17
18 # Create a page
19 page_size = Size(to_points(21, "cm"), to_points(29.7, "cm")) # DIN A4
20 out_page = Page.create(out_doc, page_size)
21
22 create_and_tag_content(out_doc, out_page, input_image_path, font)
23 out_doc.pages.append(out_page)
Tag existing PDF content
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 outDoc.Language = "en";
13 outDoc.SetPdfUaConformant();
14 outDoc.Metadata.Title = "TaggedPDF";
15 outDoc.ViewerSettings.DisplayDocumentTitle = true;
16
17 // Create empty output page
18 Page inPage = inDoc.Pages[0];
19 Page outPage = Page.Create(outDoc, inPage.Size);
20
21 // We create an output page and copy the content elements from the input page to the output page.
22 // While copying, we also check if the current element is the one we want to tag.
23 // If it is, we tag it and update the logical structure accordingly.
24 // You can easily adapt this sample to fit similar scenarios.
25 CopyAndTagContent(inPage, outPage, outDoc);
26 outDoc.Pages.Add(outPage);
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 CopyAndTagContent(Page inPage, Page outPage, Document outDoc)
2{
3 var structTree = new Tree(outDoc);
4 var documentNode = structTree.DocumentNode;
5 var section = new Node("Sect", outDoc, outPage);
6 documentNode.Children.Add(section);
7
8 // Use a content extractor and a content generator to copy content
9 ContentExtractor extractor = new ContentExtractor(inPage.Content);
10 using ContentGenerator generator = new ContentGenerator(outPage.Content, false);
11
12 Node p = new Node("P", outDoc);
13
14 // Iterate over all content elements
15 foreach (ContentElement inElement in extractor)
16 {
17 ContentElement outElement;
18 // Special treatment for group elements
19 if (inElement is GroupElement inGroupElement)
20 {
21 // Create empty output group element
22 GroupElement outGroupElement = GroupElement.CopyWithoutContent(outDoc, inGroupElement);
23 outElement = outGroupElement;
24 // Call CopyAndTagContent() recursively for the group element's content
25 CopyAndTagContent(inPage, outPage, outDoc);
26 }
27 else
28 {
29 // Copy the content element to the output document
30 outElement = ContentElement.Copy(outDoc, inElement);
31 if (outElement is TextElement outTextElement)
32 {
33 if (outTextElement.Text[0].Text == "This is a properly tagged heading")
34 {
35 CopyAndTagTextElement(outTextElement, section, generator, outPage, outDoc, "H1");
36 }
37 else if (outTextElement.Text[0].Text == "This is a properly tagged paragraph. Both heading and paragraph belong to a section.")
38 {
39 p = CopyAndTagTextElement(outTextElement, section, generator, outPage, outDoc, "P");
40 }
41
42 }
43 else if (outElement is ImageElement imageElement)
44 {
45 var bbox = imageElement.Transform.TransformRectangle(outElement.BoundingBox);
46 if (Math.Abs(bbox.BottomLeft.X - 70.86) < 0.5 && Math.Abs(bbox.BottomLeft.Y - 632.65) < 0.5 && Math.Abs(bbox.TopRight.X - 127.559) < 0.5 && Math.Abs(bbox.TopRight.Y - 689.34) < 0.5)
47 {
48 CopyAndTagImageElement(imageElement, generator, outPage, outDoc, "PdfTools AG Logo", p);
49 }
50 }
51 else
52 {
53 throw new InvalidOperationException("Unexpected content element found.");
54 }
55 }
56 }
57}
1private static void CopyAndTagImageElement(ImageElement imageElement, ContentGenerator generator, Page outPage, Document outDoc, string alternateText, Node p)
2{
3 Node imgElement = new Node("Figure", outDoc, outPage);
4
5 imgElement.AlternateText = alternateText;
6 imgElement.Language = "en";
7
8 var bbox = imageElement.Transform.TransformRectangle(imageElement.BoundingBox);
9 var rectangle = new Rectangle();
10 rectangle.Left = bbox.BottomLeft.X;
11 rectangle.Bottom = bbox.BottomLeft.Y;
12 rectangle.Right = bbox.TopRight.X;
13 rectangle.Top = bbox.TopRight.Y;
14
15 imgElement.BoundingBox = rectangle;
16 imgElement.SetStringAttribute("O", "Layout");
17
18 p.Children.Add(imgElement);
19
20 generator.TagAs(imgElement);
21
22 generator.AppendContentElement(imageElement);
23
24 generator.StopTagging();
25}
1private static Node CopyAndTagTextElement(TextElement textElement, Node section, ContentGenerator generator, Page outPage, Document outDoc, string tag)
2{
3 Node element = new Node(tag, outDoc, outPage);
4 element.ActualText = textElement.Text[0].Text;
5 element.Language = "en";
6
7 section.Children.Add(element);
8
9 generator.TagAs(element);
10
11 generator.AppendContentElement(textElement);
12
13 generator.StopTagging();
14
15 return element;
16}
1try (FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
2 Document inDoc = Document.open(inStream, null);
3 FileStream outStream = new FileStream(outPath, FileStream.Mode.READ_WRITE_NEW);
4 Document outDoc = Document.create(outStream, inDoc.getConformance(), null)) {
5
6 // Copy document-wide data
7 copyDocumentData(inDoc, outDoc);
8
9 outDoc.setLanguage("en");
10 outDoc.setPdfUaConformant();
11 outDoc.getMetadata().setTitle("TaggedPDF");
12 outDoc.getViewerSettings().setDisplayDocumentTitle(true);
13
14 // Create empty output page
15 Page inPage = inDoc.getPages().get(0);
16 Page outPage = Page.create(outDoc, inPage.getSize());
17
18 // We create an output page and copy the content elements from the input page to the output page.
19 // While copying, we also check if the current element is the one we want to tag.
20 // If it is, we tag it and update the logical structure accordingly.
21 // You can easily adapt this sample to fit similar scenarios.
22 copyAndTagContent(inPage, outPage, outDoc);
23 outDoc.getPages().add(outPage);
24}
25
1private static void copyDocumentData(Document inDoc, Document outDoc) throws Exception {
2 // Copy output intent
3 if (inDoc.getOutputIntent() != null)
4 outDoc.setOutputIntent(IccBasedColorSpace.copy(outDoc, inDoc.getOutputIntent()));
5
6 // Copy metadata
7 outDoc.setMetadata(Metadata.copy(outDoc, inDoc.getMetadata()));
8
9 // Copy viewer settings
10 outDoc.setViewerSettings(ViewerSettings.copy(outDoc, inDoc.getViewerSettings()));
11
12 // Copy associated files
13 FileReferenceList outAssociatedFiles = outDoc.getAssociatedFiles();
14 for (FileReference inFileRef : inDoc.getAssociatedFiles()) {
15 outAssociatedFiles.add(FileReference.copy(outDoc, inFileRef));
16 }
17
18 // Copy plain embedded files
19 FileReferenceList outEmbeddedFiles = outDoc.getPlainEmbeddedFiles();
20 for (FileReference inFileRef : inDoc.getPlainEmbeddedFiles()) {
21 outEmbeddedFiles.add(FileReference.copy(outDoc, inFileRef));
22 }
23}
1private static void copyAndTagContent(Page inPage, Page outPage, Document outDoc) throws ToolboxException, IOException {
2 Tree structTree = new Tree(outDoc);
3 Node documentNode = structTree.getDocumentNode();
4 Node section = new Node("Sect", outDoc, outPage);
5 documentNode.getChildren().add(section);
6
7 Node p = new Node("P", outDoc, null);
8
9 ContentExtractor extractor = new ContentExtractor(inPage.getContent());
10 try (ContentGenerator generator = new ContentGenerator(outPage.getContent(), false)) {
11 for (ContentElement inElement : extractor) {
12 ContentElement outElement;
13
14 if (inElement instanceof GroupElement) {
15 GroupElement inGroup = (GroupElement) inElement;
16 GroupElement outGroup = GroupElement.copyWithoutContent(outDoc, inGroup);
17 outElement = outGroup;
18 // Call CopyAndTagContent() recursively for the group element's content
19 copyAndTagContent(inPage, outPage, outDoc);
20 } else {
21 outElement = ContentElement.copy(outDoc, inElement);
22
23 if (outElement instanceof TextElement) {
24 TextElement text = (TextElement) outElement;
25 String str = text.getText().get(0).getText();
26
27 if ("This is a properly tagged heading".equals(str)) {
28 copyAndTagTextElement(text, section, generator, outPage, outDoc, "H1");
29 } else if ("This is a properly tagged paragraph. Both heading and paragraph belong to a section.".equals(str)) {
30 p = copyAndTagTextElement(text, section, generator, outPage, outDoc, "P");
31 }else{
32 throw new RuntimeException("Unexpected content element found.");
33 }
34 } else if (outElement instanceof ImageElement) {
35 ImageElement image = (ImageElement) outElement;
36 Quadrilateral bbox = image.getTransform().transformRectangle(image.getBoundingBox());
37
38 if (Math.abs(bbox.getBottomLeft().getX() - 70.86) < 0.5 &&
39 Math.abs(bbox.getBottomLeft().getY() - 632.65) < 0.5 &&
40 Math.abs(bbox.getTopRight().getX() - 127.559) < 0.5 &&
41 Math.abs(bbox.getTopRight().getY() - 689.34) < 0.5) {
42
43 copyAndTagImageElement(image, p, generator, outPage, outDoc, "PdfTools AG Logo");
44 }else{
45 throw new RuntimeException("Unexpected content element found.");
46 }
47 } else {
48 throw new RuntimeException("Unexpected content element found.");
49 }
50 }
51 }
52 }
53}
1private static void copyAndTagImageElement(ImageElement imageElement, Node parentNode, ContentGenerator generator,
2 Page outPage, Document outDoc, String altText) throws NotFoundException, UnsupportedFeatureException {
3 Node figure = new Node("Figure", outDoc, outPage);
4 figure.setAlternateText(altText);
5
6 figure.setLanguage("en");
7
8 Quadrilateral bbox = imageElement.getTransform().transformRectangle(imageElement.getBoundingBox());
9 Rectangle rectangle = new Rectangle();
10 rectangle.setLeft(bbox.getBottomLeft().getX());
11 rectangle.setBottom(bbox.getBottomLeft().getY());
12 rectangle.setRight(bbox.getTopRight().getX());
13 rectangle.setTop(bbox.getTopRight().getY());
14
15 figure.setBoundingBox(rectangle);
16 figure.setStringAttribute("O", "Layout");
17
18 parentNode.getChildren().add(figure);
19
20 generator.tagAs(figure);
21 generator.appendContentElement(imageElement);
22 generator.stopTagging();
23}
1private static Node copyAndTagTextElement(TextElement textElement, Node section, ContentGenerator generator,
2 Page outPage, Document outDoc, String tag) throws NotFoundException, UnsupportedFeatureException {
3 Node tagNode = new Node(tag, outDoc, outPage);
4 tagNode.setActualText(textElement.getText().get(0).getText());
5 section.getChildren().add(tagNode);
6
7 tagNode.setLanguage("en");
8
9 generator.tagAs(tagNode);
10 generator.appendContentElement(textElement);
11 generator.stopTagging();
12
13 return tagNode;
14}
1def copy_document_data(in_doc: Document, out_doc: Document):
2 if in_doc.output_intent is not None:
3 out_doc.output_intent = IccBasedColorSpace.copy(out_doc, in_doc.output_intent)
4
5 out_doc.metadata = Metadata.copy(out_doc, in_doc.metadata)
6 out_doc.viewer_settings = ViewerSettings.copy(out_doc, in_doc.viewer_settings)
7
8 out_associated_files = out_doc.associated_files
9 for in_file_ref in in_doc.associated_files:
10 out_associated_files.append(FileReference.copy(out_doc, in_file_ref))
11
12 out_embedded_files = out_doc.plain_embedded_files
13 for in_file_ref in in_doc.plain_embedded_files:
14 out_embedded_files.append(FileReference.copy(out_doc, in_file_ref))
1def copy_and_tag_text_element(text_element: TextElement, section_node: Node, generator: ContentGenerator,
2 out_page: Page, out_doc: Document, tag: str):
3 text_node = Node(tag, out_doc, out_page)
4 text_node.actual_text = text_element.text[0].text
5 text_node.language = "en"
6 section_node.children.append(text_node)
7
8 generator.tag_as(text_node)
9 generator.append_content_element(text_element)
10 generator.stop_tagging()
11
12 return text_node
1def copy_and_tag_image_element(image_element: ImageElement, parent: Node, generator: ContentGenerator,
2 out_page: Page, out_doc: Document, alternate_text: str):
3 image_node = Node("Figure", out_doc, out_page)
4 image_node.alternate_text = alternate_text
5 image_node.language = "en"
6 image_node.set_string_attribute("O", "Layout")
7
8 bbox = image_element.transform.transform_rectangle(image_element.bounding_box)
9 rectangle = Rectangle()
10 rectangle.left = bbox.bottom_left.x
11 rectangle.bottom = bbox.bottom_left.y
12 rectangle.right = bbox.top_right.x
13 rectangle.top = bbox.top_right.y
14
15 image_node.bounding_box = rectangle
16
17 parent.children.append(image_node)
18
19 generator.tag_as(image_node)
20 generator.append_content_element(image_element)
21 generator.stop_tagging()
1def copy_and_tag_content(in_page: Page, out_page: Page, out_doc: Document):
2 struct_tree = Tree(out_doc)
3 document_node = struct_tree.document_node
4 section_node = Node("Sect", out_doc, out_page)
5 document_node.children.append(section_node)
6
7 extractor = ContentExtractor(in_page.content)
8
9 p = Node("P", out_doc, None)
10
11 with ContentGenerator(out_page.content, False) as generator:
12 for in_element in extractor:
13 if isinstance(in_element, GroupElement):
14 out_group = GroupElement.copy_without_content(out_doc, in_element)
15 copy_and_tag_content(in_page, out_page, out_doc)
16 else:
17 out_element = ContentElement.copy(out_doc, in_element)
18
19 if isinstance(out_element, TextElement):
20 text = out_element.text[0].text
21 if text == "This is a properly tagged heading":
22 copy_and_tag_text_element(out_element, section_node, generator, out_page, out_doc, "H1")
23 elif text == "This is a properly tagged paragraph. Both heading and paragraph belong to a section.":
24 p = copy_and_tag_text_element(out_element, section_node, generator, out_page, out_doc, "P")
25 else:
26 raise RuntimeError("Unexpected content element found.")
27 elif isinstance(out_element, ImageElement):
28 bbox: Quadrilateral = out_element.transform.transform_rectangle(out_element.bounding_box)
29 if (
30 abs(bbox.bottom_left.x - 70.86) < 0.5
31 and abs(bbox.bottom_left.y - 632.65) < 0.5
32 and abs(bbox.top_right.x - 127.559) < 0.5
33 and abs(bbox.top_right.y - 689.34) < 0.5
34 ):
35 copy_and_tag_image_element(out_element, p, generator, out_page, out_doc, "PdfTools AG Logo")
36 else:
37 raise RuntimeError("Unexpected content element found.")
38 else:
39 raise RuntimeError("Unexpected content element found.")
1with io.FileIO(input_file_path, 'rb') as in_stream:
2 with Document.open(in_stream, None) as in_doc:
3 with io.FileIO(output_file_path, 'wb+') as out_stream:
4 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
5
6 # Copy document-wide data
7 copy_document_data(in_doc, out_doc)
8
9 # Create empty output page
10 in_page = in_doc.pages[0]
11 out_page = Page.create(out_doc, in_page.size)
12
13 out_doc.language = "en"
14 out_doc.set_pdf_ua_conformant()
15 out_doc.metadata.title = "TaggedPDF"
16 out_doc.viewer_settings.display_document_title = True
17
18 # We create an output page and copy the content elements from the input page to the output page.
19 # While copying, we also check if the current element is the one we want to tag.
20 # If it is, we tag it and update the logical structure accordingly.
21 # You can easily adapt this sample to fit similar scenarios.
22 copy_and_tag_content(in_page, out_page, out_doc)
23 out_doc.pages.append(out_page)
Traverse the Document Structure
1
2// Open input document
3using (Stream inStream = new FileStream(inPath, FileMode.Open, FileAccess.Read))
4using (Document inDoc = Document.Open(inStream, null))
5{
6 var tree = new Tree(inDoc);
7 foreach (var child in tree.Children)
8 {
9 PrintNodeRecursively(child);
10 }
11}
1static void PrintProperty(int level, String name, String value)
2{
3 Console.Write($"{new string(' ', level * 2)}");
4 Console.WriteLine($"{name}: '{value}'");
5}
1static void PrintNodeRecursively(Node node, int level = 0)
2{
3 PrintProperty(level, "Tag", node.Tag);
4 PrintProperty(level, "Alternative text", node.AlternateText);
5 PrintProperty(level, "Actual text", node.ActualText);
6 PrintProperty(level, "Abbreviation", node.Abbreviation);
7 PrintProperty(level, "Language", node.Language);
8
9 foreach (var child in node.Children)
10 {
11 PrintNodeRecursively(child, level + 1);
12 }
13}
1try (// Open input document
2 FileStream inStream = new FileStream(inPath, FileStream.Mode.READ_ONLY);
3 Document inDoc = Document.open(inStream, null)) {
4 Tree tree = new Tree(inDoc);
5 for (Node node : tree.getChildren()) {
6 printNodeRecursively(node, 0);
7 }
8}
9
10
1static void printProperty(int level, String name, String value) {
2 for (int i = 0; i< level; ++i) {
3 System.out.print(" ");
4 }
5 System.out.println(name + ": " + value);
6}
1static void printNodeRecursively(Node node, int level) throws NotFoundException {
2 printProperty(level, "Tag", node.getTag());
3 printProperty(level, "Alternative text", node.getAlternateText());
4 printProperty(level, "Actual text", node.getActualText());
5 printProperty(level, "Abbreviation", node.getAbbreviation());
6 printProperty(level, "Language", node.getLanguage());
7 for (Node child : node.getChildren()) {
8 printNodeRecursively(child, level + 1);
9 }
10 }
1def print_node_recursive(node: Node, level: int):
2 print(" " * level, "Tag: ", node.tag)
3 print(" " * level, "Alternative text: ", node.alternate_text)
4 print(" " * level, "Actual text: ", node.actual_text)
5 print(" " * level, "Abbreviation: ", node.abbreviation)
6 print(" " * level, "Language: ", node.language)
7
8 for child in node.children:
9 print_node_recursive(child, level + 1)
1def print_document_structure(in_doc: Document):
2 tree = Tree(in_doc)
3 for node in tree.children:
4 print_node_recursive(node, 0)
1# Open the input document
2with open(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4 print_document_structure(in_doc)
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)
1# Define global variables
2page_size = Size(1190.0, 842.0) # A3 portrait
3border = 10.0
4cell_width = (page_size.width - 3 * border) / 2
5cell_height = page_size.height - 2 * border
6cell_left = border
7cell_right = 2 * border + cell_width
8cell_y_pos = border
9
10# Open input document
11with io.FileIO(input_file_path, "rb") as in_stream:
12 with Document.open(in_stream, None) as in_doc:
13
14 # Create output document
15 with io.FileIO(output_file_path, "wb+") as output_stream:
16 with Document.create(output_stream, in_doc.conformance, None) as out_doc:
17
18 # Copy document-wide data
19 copy_document_data(in_doc, out_doc)
20
21 # Create a font
22 font = Font.create_from_system(out_doc, "Arial", "Italic", True)
23
24 # Copy pages
25 in_pages = in_doc.pages
26 out_pages = out_doc.pages
27 number_of_sheets = (len(in_pages) + 3) // 4
28
29 for sheet_number in range(number_of_sheets):
30 # Add front side
31 create_booklet(in_pages, out_doc, out_pages, 4 * number_of_sheets - 2 * sheet_number - 1, 2 * sheet_number, font)
32 # Add back side
33 create_booklet(in_pages, out_doc, out_pages, 2 * sheet_number + 1, 4 * number_of_sheets - 2 * sheet_number - 2, font)
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)
1# Define global variables
2TARGET_SIZE = Size(width=595, height=842) # A4 portrait
3ALLOW_ROTATE = True
4
5# Open input document
6with io.FileIO(input_file_path, "rb") as in_stream:
7 with Document.open(in_stream, None) as in_doc:
8
9 # Create output document
10 with io.FileIO(output_file_path, "wb+") as out_stream:
11 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
12
13 # Copy document-wide data
14 copy_document_data(in_doc, out_doc)
15
16 # Process and resize pages
17 scale_pages_to_fit(in_doc, out_doc)
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}
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# Define global variables
2nx = 2
3ny = 2
4page_size = Size(595.0, 842.0) # A4 portrait
5border = 10.0
6
7# Open input document
8with io.FileIO(input_file_path, 'rb') as in_stream:
9 with Document.open(in_stream, None) as input_document:
10
11 # Create output document
12 with io.FileIO(output_file_path, 'wb+') as output_stream:
13 with Document.create(output_stream, input_document.conformance, None) as output_document:
14 out_pages = output_document.pages
15 page_count = 0
16 generator = None
17 out_page = None
18
19 # Copy document-wide data
20 copy_document_data(input_document, output_document)
21
22 # Copy all pages from input document
23 for in_page in input_document.pages:
24 if page_count == nx * ny:
25 # Add to output document
26 generator.__exit__(None, None, None)
27 out_pages.append(out_page)
28 out_page = None
29 page_count = 0
30 if out_page is None:
31 # Create a new output page
32 out_page = Page.create(output_document, page_size)
33 generator = ContentGenerator(out_page.content, False)
34
35 # Get area where group has to be (// calculates the floor of the division)
36 x = int(page_count % nx)
37 y = int(ny - (page_count // nx) - 1)
38
39 # Compute cell size
40 cell_width = (page_size.width - ((nx + 1) * border)) / nx
41 cell_height = (page_size.height - ((ny + 1) * border)) / ny
42
43 # Compute cell position
44 cell_x = border + x * (cell_width + border)
45 cell_y = border + y * (cell_height + border)
46
47 # Define page copy options
48 copy_options = PageCopyOptions()
49
50 # Copy page as group from input to output
51 group = Group.copy_from_page(output_document, in_page, copy_options)
52
53 # Compute group position
54 group_size = group.size
55 scale = min(cell_width / group_size.width, cell_height / group_size.height)
56
57 # Compute target size
58 target_width = group_size.width * scale
59 target_height = group_size.height * scale
60
61 # Compute position
62 target_x = cell_x + ((cell_width - target_width) / 2)
63 target_y = cell_y + ((cell_height - target_height) / 2)
64
65 # Compute rectangle
66 target_rect = Rectangle()
67 target_rect.left = target_x
68 target_rect.bottom = target_y
69 target_rect.right = target_x + target_width
70 target_rect.top = target_y + target_height
71
72 # Add group to page
73 generator.paint_group(group, target_rect, None)
74 page_count += 1
75
76 # Add page
77 if out_page:
78 generator.__exit__(None, None, None)
79 out_pages.append(out_page)
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}
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# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Define page copy options
13 page_copy_options = PageCopyOptions()
14
15 # Copy all pages
16 copied_pages = PageList.copy(out_doc, in_doc.pages, page_copy_options)
17
18 # Rotate selected pages by 90 degrees
19 for page_number in page_numbers:
20 copied_pages[int(page_number) - 1].rotate(Rotation.CLOCKWISE)
21
22 # Add pages to output document
23 out_doc.pages.extend(copied_pages)
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(".") + 1);
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(".") + 1);
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)
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4
5 # Create output document
6 with io.FileIO(output_file_path, "wb+") as out_stream:
7 with Document.create(out_stream, in_doc.conformance, None) as out_doc:
8
9 # Copy document-wide data
10 copy_document_data(in_doc, out_doc)
11
12 # Define page copy options
13 copy_options = PageCopyOptions()
14
15 # Copy all pages and append to output document
16 copied_pages = PageList.copy(out_doc, in_doc.pages, copy_options)
17 out_doc.pages.extend(copied_pages)
18
19 embed_file(out_doc, file_to_embed, page_number)
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(chr(0), "")
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)
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4 file_ref_list = in_doc.all_embedded_files
5 for file_ref in file_ref_list:
6 extract_file(file_ref, output_dir)
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}")
1# Ensure the output directory exists
2os.makedirs(output_dir, exist_ok=True)
3
4# Open input document
5with io.FileIO(input_file_path, "rb") as in_stream:
6 with Document.open(in_stream, None) as in_doc:
7
8 for page_number, page in enumerate(in_doc.pages, start=1):
9 process_page_content(page, page_number, output_dir)
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}")
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4 # Process the PDF
5 list_content_bounds(in_doc)
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}")
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, pdf_password) as in_doc:
4 # Process the PDF
5 list_pdf_info(in_doc)
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
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")
1# Open input document
2with io.FileIO(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4 # List all signatures of the PDF document
5 list_signatures(in_doc)
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)
1# Open the input document
2with open(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4 print_outline_items(in_doc.outline, "", 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}
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))
1# Open input document
2with open(input_file_path, "rb") as in_stream:
3 with Document.open(in_stream, None) as in_doc:
4 page_number = 1
5
6 # Process each page
7 for in_page in in_doc.pages:
8 print(f"==========\nPage: {page_number}\n==========")
9
10 extractor = ContentExtractor(in_page.content)
11 extractor.ungrouping = UngroupingSelection.ALL
12
13 # Iterate over all content elements and only process text elements
14 for element in extractor:
15 if isinstance(element, TextElement):
16 write_text(element.text)
17 page_number += 1