├── .gitattributes
├── .github
└── workflows
│ └── go.yml
├── .gitignore
├── README.md
├── accessibility
├── README.md
├── logo.png
├── pdf_add_image_alt_text.go
├── pdf_copy_page_with_accessibility.go
└── pdf_set_language_identifier.go
├── advanced
├── README.md
├── grayscale_input.pdf
├── grayscale_output.pdf
└── pdf_grayscale_transform.go
├── analysis
├── README.md
├── pdf_all_objects.go
├── pdf_detect_scanned.go
├── pdf_get_object.go
├── pdf_info.go
├── pdf_inspect.go
├── pdf_print_content_streams.go
└── pdf_summarize_images.go
├── annotations
├── README.md
├── pdf_annotate_add_ellipse.go
├── pdf_annotate_add_file.go
├── pdf_annotate_add_ink.go
├── pdf_annotate_add_line.go
├── pdf_annotate_add_rectangle.go
├── pdf_annotate_add_text.go
└── pdf_list_annotations.go
├── arabic-text
├── Amiri-Regular.ttf
├── arabic-text.pdf
└── pdf_write_arabic.go
├── attachment
├── README.md
├── dummy.xml
├── minimal.pdf
├── pdf_add_attachment.go
└── pdf_get_attachment.go
├── barcode
├── README.md
├── pdf_add_barcode.go
└── pdf_add_qr_code.go
├── build_examples.sh
├── compress
├── README.md
├── outputs
│ ├── ouput_file_1.pdf
│ ├── ouput_file_2.pdf
│ └── ouput_file_3.pdf
├── pdf_font_subsetting.go
├── pdf_optimize.go
├── pdf_remove_unused_resources.go
└── test_files
│ ├── test_file_1.pdf
│ ├── test_file_2.pdf
│ └── test_file_3.pdf
├── concurrent-processing
├── README.md
└── concurrent_extraction.go
├── drawing
├── README.md
├── pdf_draw_lines.go
├── pdf_draw_shapes.go
├── unipdf-draw-lines.pdf
└── unipdf-draw-shapes.pdf
├── extract-bullet-lists
├── README.md
├── extract_bullet_list.go
├── output
│ ├── list_file1.txt
│ ├── list_file2_page1.txt
│ └── list_file2_page2.txt
└── test-files
│ ├── tagged-pdf-2.pdf
│ └── untagged-pdf-3.pdf
├── extract
├── README.md
├── extract_text_bound.go
├── pdf_extract_fonts.go
├── pdf_extract_images.go
├── pdf_extract_location.go
├── pdf_extract_text.go
├── pdf_simple_extraction.go
├── pdf_tables.go
├── reconstruct_text.go
└── reconstruct_words.go
├── forms
├── DoHyeon-Regular.ttf
├── README.md
├── fdf_fields_info.go
├── filled_form_rich.pdf
├── form-fill-custom-text-color.go
├── form_field_with_colored_text_fields.pdf
├── form_fields_rotations.json
├── form_fields_rotations.pdf
├── formdata.json
├── images
│ └── 1.jpg
├── pdf_fill_and_flatten_with_apearance.go
├── pdf_form_action.go
├── pdf_form_add.go
├── pdf_form_fields_rotations.go
├── pdf_form_fill_custom_font.go
├── pdf_form_fill_fdf_merge.go
├── pdf_form_fill_image.go
├── pdf_form_fill_json.go
├── pdf_form_flatten.go
├── pdf_form_flatten_non_url.go
├── pdf_form_get_field_data.go
├── pdf_form_list_fields.go
├── pdf_form_partial_flatten.go
├── pdf_form_with_text_color.go
├── rounded-mplus-1p-regular.ttf
├── sample_form.json
├── sample_form.pdf
├── sample_form_output.pdf
├── sample_form_rich.json
└── template1.pdf
├── go.mod
├── go.sum
├── grid
├── README.md
├── logo.png
├── pdf_grid_colspan.go
├── pdf_grid_rowspan.go
├── pdf_grid_simple.go
├── pdf_grid_wrapping.go
├── unipdf-grid-colspan.pdf
├── unipdf-grid-rowspan.pdf
├── unipdf-grid-simple.pdf
└── unipdf-grid-wrapping.pdf
├── hebrew-text
├── OpenSans-Regular.ttf
├── hebrew-text.pdf
└── pdf_write_hebrew.go
├── image
├── README.md
├── pdf_add_image_to_page.go
├── pdf_images_to_pdf.go
├── pdf_images_to_pdf_lazy.go
└── pdf_list_images.go
├── invoice
├── README.md
├── invoice_advanced.pdf
├── invoice_simple.pdf
├── pdf_invoice_advanced.go
├── pdf_invoice_simple.go
└── unidoc-logo.png
├── javascript
└── pdf_add_javascript_docopen.go
├── jbig2
├── checkerboard-squares-black-white.jb2
├── checkerboard-squares-black-white.jpg
├── document.jb2
├── jbig2_compress_image.go
├── jbig2_compress_image_in_pdf.go
├── jbig2_decompress.go
├── jbig2_decompress_with_globals.go
└── jbig2_globals.jb2
├── license
├── README.md
├── unipdf_license_key_usage_log.go
├── unipdf_license_loading_metered.go
├── unipdf_license_loading_offline.go
└── unipdf_offline_license_info.go
├── metadata
├── README.md
├── pdf_get_custom_xmp_metadata.go
├── pdf_get_xmp_media_management_metadata.go
├── pdf_get_xmp_pdf_metadata.go
├── pdf_get_xmp_pdfaid_metadata.go
├── pdf_metadata_get_docinfo.go
├── pdf_metadata_get_xml.go
├── pdf_metadata_set_docinfo.go
├── pdf_set_custom_xmp_metadata.go
├── pdf_set_xmp_media_management_metadata.go
└── pdf_set_xmp_pdf_metadata.go
├── multi-font-encoder
├── fonts
│ ├── Batang.ttf
│ ├── NotoSerifEthiopic_Condensed-Black.ttf
│ ├── OpenSans-Regular.ttf
│ └── PCSB Hebrew Regular.ttf
├── multiple-language-text-using-multi-font.pdf
└── use_composite_TTFPdfFonts.go
├── outlines
├── README.md
├── pdf_create_outlines.go
├── pdf_get_outlines.go
└── pdf_set_outlines.go
├── pages
├── README.md
├── pdf_4up.go
├── pdf_append_contents.go
├── pdf_crop.go
├── pdf_merge.go
├── pdf_merge_advanced.go
├── pdf_merge_with_page_numbers.go
├── pdf_page_info.go
├── pdf_page_rotate.go
├── pdf_page_side_note.go
├── pdf_rotate.go
├── pdf_rotate_flatten.go
├── pdf_split.go
├── pdf_split_advanced.go
└── pdf_split_and_remove_unused_resources.go
├── pdfa
├── pdf_apply_standard.go
├── pdf_validate_standard.go
├── pdfa2_apply_standard.go
├── pdfa2_validate_standard.go
├── pdfa3_apply_standard.go
└── pdfa3_validate_standard.go
├── redact
├── README.md
├── outputs
│ └── test_file01_redacted.pdf
├── redact_text.go
└── test_files
│ └── test_file01.pdf
├── render
├── README.md
├── jpeg2k
│ └── lib_jpeg2k_encoder.go
├── pdf_image_render.go
└── pdf_image_render_custom_encoder_cgo.go
├── report
├── README.md
├── Roboto-Bold.ttf
├── Roboto-Regular.ttf
├── pdf-custom-toc.pdf
├── pdf_custom_toc.go
├── pdf_report.go
├── pdf_report_from_csv.go
├── pdf_report_landscape.go
├── pdf_tables.go
├── report_from_csv.pdf
├── report_from_csv_preview.png
├── test-data.csv
├── unidoc-logo.png
├── unidoc-report-landscape.pdf
├── unidoc-report.pdf
└── unipdf-tables.pdf
├── sanitize
├── README.md
├── outputs
│ └── JSPopupCalendarSanitized.pdf
├── pdf_modify_contents.go
├── pdf_sanitize_document.go
├── test-files
│ └── JSPopupCalendar.pdf
├── unidoc-file-modified.pdf
└── unidoc-file.pdf
├── search-and-replace
├── READ.md
├── replace_text.go
├── search_text.go
└── test-data
│ ├── file1.pdf
│ └── result.pdf
├── security
├── README.md
├── pdf_check_permissions.go
├── pdf_protect.go
├── pdf_security_info.go
└── pdf_unlock.go
├── signatures
├── README.md
├── ltv
│ ├── README.md
│ ├── pdf_ltv_enable_signed_file.go
│ ├── pdf_sign_ltv_extra_revision.go
│ ├── pdf_sign_ltv_one_revision.go
│ └── pdf_sign_ltv_timestamp_revision.go
├── pdf_image_sign_appearance.go
├── pdf_sign_and_encrypt_pdf.go
├── pdf_sign_appearance.go
├── pdf_sign_docmdp.go
├── pdf_sign_docmdp_invalid_changes.go
├── pdf_sign_docmdp_valid_changes.go
├── pdf_sign_external.go
├── pdf_sign_external_aws_kms.go
├── pdf_sign_external_globalsign.go
├── pdf_sign_external_google_cloud_kms.go
├── pdf_sign_generate_keys.go
├── pdf_sign_get_revision.go
├── pdf_sign_hsm_pkcs11_cgo.go
├── pdf_sign_new_page.go
├── pdf_sign_pades_b_b.go
├── pdf_sign_pades_b_lt.go
├── pdf_sign_pades_b_lta.go
├── pdf_sign_pades_b_t.go
├── pdf_sign_pem_multicert.go
├── pdf_sign_pkcs12.go
├── pdf_sign_timestamp.go
├── pdf_sign_twice_visible_annotation.go
├── pdf_sign_validate.go
├── pdf_sign_validate_pades_b_b.go
└── pdf_sign_validate_timestamp.go
├── svg
├── fonts
│ ├── Roboto-Bold.ttf
│ └── Roboto-Regular.ttf
├── pdf_report_with_logo.go
├── pdf_shapes_and_text_svg.pdf
├── pdf_svg_shapes_and_text.go
├── svgs
│ ├── different_shapes.svg
│ └── unidoc-logo.svg
└── unidoc-report_with_svg.pdf
├── table-info
├── README.md
├── output
│ ├── partitioned_content_1.txt
│ └── partitioned_content_2.txt
├── partition_text.go
├── table_content.go
└── test-files
│ ├── PDF Tables.pdf
│ └── table.pdf
├── tables
├── README.md
├── images
│ ├── image1.jpg
│ ├── image2.jpg
│ ├── image3.jpg
│ ├── image4.jpg
│ ├── image5.jpg
│ ├── image6.jpg
│ ├── image7.jpg
│ └── image8.jpg
├── pdf_tables_colspan.go
├── pdf_tables_division_layout.go
├── pdf_tables_header_images.go
├── pdf_tables_row_wrap.go
├── pdf_tables_rowspan.go
├── pdf_tables_simple.go
├── pdf_tables_styling.go
├── pdf_tables_subtables.go
├── unidoc-logo.png
├── unipdf-colSpan-tables.pdf
├── unipdf-header-imgs-tables.pdf
├── unipdf-rowSpan-tables.pdf
├── unipdf-simple-tables.pdf
├── unipdf-style-tables.pdf
├── unipdf-subtables-tables.pdf
├── unipdf-tables-division-layout.pdf
└── unipdf-tables-row-wrap.pdf
├── templates
├── README.md
├── airplane-ticket
│ ├── README.md
│ ├── pdf_airplane_ticket.go
│ ├── templates
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── logo.png
│ │ │ └── screenshot.png
│ ├── ticket.json
│ └── unipdf-airplain-ticket.pdf
├── aviation-checklist
│ ├── README.md
│ ├── checklist.json
│ ├── pdf_aviation_checklist.go
│ ├── templates
│ │ ├── footer.tpl
│ │ ├── header.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── logo.png
│ │ │ └── screenshot.png
│ └── unipdf-aviation-checklist.pdf
├── bank-account-statement
│ ├── README.md
│ ├── account_statement.json
│ ├── pdf_bank_account_statement.go
│ ├── templates
│ │ ├── footer.tpl
│ │ ├── header.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── logo.png
│ │ │ └── screenshot.png
│ └── unipdf-bank-account-statement.pdf
├── boarding-pass
│ ├── README.md
│ ├── boarding_pass.json
│ ├── pdf_boarding_pass.go
│ ├── templates
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── baggage.png
│ │ │ ├── logo.png
│ │ │ ├── screenshot.png
│ │ │ └── seat_icon.png
│ └── unipdf-boarding-pass.pdf
├── concert-ticket
│ ├── README.md
│ ├── concert-ticket.json
│ ├── pdf_concert_ticket.go
│ ├── templates
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── map.png
│ │ │ ├── red-guitar.png
│ │ │ ├── screenshot.png
│ │ │ ├── ticket-img.png
│ │ │ └── unidoc-logo.png
│ └── unipdf-ticket.pdf
├── documentation
│ ├── README.md
│ ├── pdf_templates_documentation.go
│ ├── templates
│ │ ├── chapters
│ │ │ ├── 01_00_Introduction.tpl
│ │ │ ├── 02_00_Components.tpl
│ │ │ ├── 02_01_Paragraphs.tpl
│ │ │ ├── 02_02_Images.tpl
│ │ │ ├── 02_03_Rectangles.tpl
│ │ │ ├── 02_04_Ellipses.tpl
│ │ │ ├── 02_05_Lines.tpl
│ │ │ ├── 02_06_Charts.tpl
│ │ │ ├── 02_07_Page_Breaks.tpl
│ │ │ ├── 03_00_Container_Components.tpl
│ │ │ ├── 03_01_Divisions.tpl
│ │ │ ├── 03_02_Tables.tpl
│ │ │ ├── 03_03_Lists.tpl
│ │ │ ├── 03_04_Chapters.tpl
│ │ │ ├── 04_00_Attributes_and_Resources.tpl
│ │ │ ├── 04_01_Fonts.tpl
│ │ │ ├── 04_02_Images.tpl
│ │ │ ├── 04_03_Colors.tpl
│ │ │ ├── 04_04_Margin_and_Padding.tpl
│ │ │ ├── 04_05_Border_Radius.tpl
│ │ │ └── 05_00_Golang_Interface.tpl
│ │ ├── footer.tpl
│ │ ├── front-page.tpl
│ │ ├── header.tpl
│ │ ├── helpers.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── fonts
│ │ │ ├── DejaVuSansMono.ttf
│ │ │ └── Roboto-Regular.ttf
│ │ │ └── images
│ │ │ ├── hero0.png
│ │ │ ├── hero1.png
│ │ │ ├── hero2.png
│ │ │ ├── hero3.png
│ │ │ ├── logo.png
│ │ │ ├── reports.png
│ │ │ ├── sample-image-2.jpg
│ │ │ ├── sample-image-3.jpg
│ │ │ ├── sample-image-4.jpg
│ │ │ ├── sample-image-5.jpg
│ │ │ ├── sample-image.jpg
│ │ │ └── screenshot.png
│ └── unipdf-templates-documentation.pdf
├── lab-results
│ ├── README.md
│ ├── lab_results.json
│ ├── pdf_lab_results.go
│ ├── templates
│ │ ├── footer.tpl
│ │ ├── header.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── logo.png
│ │ │ └── screenshot.png
│ └── unipdf-lab-results.pdf
├── log-book-report
│ ├── README.md
│ ├── contents
│ │ └── operations_log.json
│ ├── pdf_log_book.go
│ ├── templates
│ │ ├── footer.tpl
│ │ ├── front-page.tpl
│ │ ├── header.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── Exo-Bold.ttf
│ │ │ ├── Exo-Italic.ttf
│ │ │ ├── Exo-Regular.ttf
│ │ │ └── pages.png
│ └── unipdf-log-book.pdf
├── medical-bill
│ ├── README.md
│ ├── medical_bill.json
│ ├── pdf_medical_bill.go
│ ├── templates
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── clinic_care.png
│ │ │ ├── health_care.png
│ │ │ ├── hospital_logo.png
│ │ │ └── screenshot.png
│ └── unipdf-medical-bill.pdf
├── medication-schedule-report
│ ├── README.md
│ ├── data.json
│ ├── pdf_medication_schedule.go
│ ├── templates
│ │ ├── footer.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── arial.ttf
│ │ │ ├── arialbd.ttf
│ │ │ ├── bar-code.png
│ │ │ ├── checkmark-empty.png
│ │ │ ├── checkmark.png
│ │ │ ├── logo.png
│ │ │ └── screenshot.png
│ └── unipdf-medication-schedule.pdf
├── receipt
│ ├── README.md
│ ├── contents
│ │ └── receipt.json
│ ├── pdf_receipt.go
│ ├── templates
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── screenshot.png
│ │ │ └── unidoc-logo.png
│ └── unipdf-receipt.pdf
├── rental-agreement
│ ├── README.md
│ ├── pdf_rental_agreement.go
│ ├── rental_data.json
│ ├── templates
│ │ ├── footer.tpl
│ │ ├── header.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── arialbd.ttf
│ │ │ ├── house.png
│ │ │ ├── logo.png
│ │ │ ├── pages.png
│ │ │ └── qr.png
│ └── unipdf-rental-agreement.pdf
├── security-report
│ ├── README.md
│ ├── pdf_security_report.go
│ ├── templates
│ │ ├── footer.tpl
│ │ ├── front-page.tpl
│ │ ├── header.tpl
│ │ ├── main.tpl
│ │ └── res
│ │ │ ├── hero.png
│ │ │ ├── logo.png
│ │ │ ├── page1.png
│ │ │ └── pages.png
│ └── unipdf-security-report.pdf
├── trade-confirmation
│ ├── README.md
│ ├── pdf_trade_confirmation.go
│ ├── templates
│ │ ├── main.tpl
│ │ └── res
│ │ │ └── screenshot.png
│ ├── trade.json
│ └── unipdf-trade-confirmation.pdf
└── warehouse-shipment-report
│ ├── README.md
│ ├── pdf_warehouse_shipment_report.go
│ ├── shipment_report.json
│ ├── templates
│ ├── header.tpl
│ ├── main.tpl
│ └── res
│ │ ├── logo.png
│ │ └── screenshot.png
│ └── unipdf-warehouse-shipment-report.pdf
├── testing
├── README.md
├── formdata.json
├── pdf_count_color_pages_bench.go
├── pdf_grayscale_convert_bench.go
├── pdf_passthrough_bench.go
├── pdf_update_fields.go
└── sample_form.pdf
├── text
├── README.md
├── Roboto-Regular.ttf
├── pdf_cmyk_color.go
├── pdf_detect_signature.go
├── pdf_formatted_text.go
├── pdf_highlight_text.go
├── pdf_insert_text.go
├── pdf_search_replace.go
├── pdf_search_replace_advanced.go
├── pdf_text_color.go
├── pdf_text_locations.go
├── pdf_text_vertical_alignment.go
├── pdf_to_csv.go
├── pdf_using_unicode_font.go
├── rounded-mplus-1p-regular.ttf
└── styled_paragraph.pdf
├── watermarks
├── README.md
├── Roboto-Regular.ttf
├── pdf_add_text_watermark.go
├── pdf_remove_watermark_image.go
├── pdf_watermark_image.go
├── watermark_input.pdf
└── watermark_output.pdf
└── writer
├── pdf_modify_contents.go
├── unidoc-file-modified.pdf
└── unidoc-file.pdf
/.gitattributes:
--------------------------------------------------------------------------------
1 | * -crlf
2 |
--------------------------------------------------------------------------------
/.github/workflows/go.yml:
--------------------------------------------------------------------------------
1 | name: Build all examples
2 |
3 | on:
4 | push:
5 | branches: [ master ]
6 | pull_request:
7 | branches: [ master ]
8 |
9 | jobs:
10 | build:
11 | name: Build Go ${{ matrix.go }}
12 | runs-on: ubuntu-latest
13 | strategy:
14 | matrix:
15 | go: [ '1.24', '1.23', '1.22', '1.21', '1.20' ]
16 | steps:
17 | - name: Check out code into the Go module directory
18 | uses: actions/checkout@v2
19 |
20 | - name: Setup go
21 | uses: actions/setup-go@v1
22 | with:
23 | go-version: ${{ matrix.go }}
24 |
25 | - name: Setup ImageMagick's MagickWand
26 | run:
27 | sudo apt-get install libmagickwand-dev imagemagick
28 |
29 | - name: Build all
30 | run: |
31 | ./build_examples.sh
32 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | *.mdb
3 | *.userprefs
4 | *.pidb
5 | *.suo
6 | *.out
7 | *.pyc
8 | *.wixobj
9 | *.msi
10 | *.wixpdb
11 | build
12 | dist
13 | setuptools-*
14 | .DS_Store
15 | *.so
16 | nohup.out
17 | *.orig
18 | *.rej
19 | *~
20 | *.o
21 | *.pyo
22 | tests/*.err
23 | *.swp
24 | *.swo
25 | store/*
26 | *.log
27 | *.egg-info
28 | dist/
29 | doc/_build/
30 | distribute-*
31 | pip-log.txt
32 | .coverage
33 | data/
34 | *.egg
35 | .tox
36 | out.txt
37 | junit*.xml
38 | .ropeproject
39 | .cache
40 | tmp/
41 | bin/
42 | *.sublime-project
43 | *.sublime-workspace
44 | *.pprof
45 | gin-bin
46 | pkg/buildinfo/buildinfo.go
47 | temp/
48 | buildinfo.json
49 | .vscode
50 |
51 | pdf/bak
52 |
53 | pdf/report/pdf_report
54 |
55 | pdf/outlines
56 |
57 | pdf/testing/pdf_count_color_pages_bench
58 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | This example repository demonstrates many use cases for UniDoc's UniPDF library. Example code should make
4 | it easy for users to get started with UniPDF. Feel free to add to this by submitting
5 | a pull request.
6 |
7 | While the majority of examples are fully in pure Go, there are a few examples that demonstrate additional
8 | functionality that requires CGO and external dependencies. Those examples are clarified by filename suffix "_cgo.go".
9 |
10 | ## License codes
11 | UniPDF requires license codes to operate, there are two options:
12 | - Metered License API keys: Free ones can be obtained at https://cloud.unidoc.io
13 | - Offline codes: Can be purchased at https://unidoc.io/pricing
14 |
15 | Most of the examples demonstrate loading the Metered License API keys through an environment
16 | variable `UNIDOC_LICENSE_API_KEY`.
17 |
18 | Examples for Offline License Key loading can be found in the license subdirectory.
19 |
20 | ### Build all examples
21 |
22 | #### Building with go modules:
23 | Simply run the build script which builds all the binaries to subfolder `bin/`
24 |
25 | ```bash
26 | $ ./build_examples.sh
27 | ```
28 |
29 | #### Building with GOPATH:
30 | Building with GOPATH requires a slightly different approach due to the `/v4` semantic import portion of the unipdf import paths. There are two options:
31 |
32 | Both options start with:
33 | - `go get github.com/unidoc/unipdf/...` to download the packages
34 |
35 | Then one can decide between the two options:
36 |
37 | 1. Remove the `/v4/` in the unipdf import paths, e.g. use `github.com/unidoc/unipdf/core` instead of `github.com/unidoc/unipdf/v4/core`
38 | 2. Alternatively create a symbolic link from the v3 subdirectory of unipdf to the unipdf repository, i.e.
39 | ```bash
40 | ln -s $GOPATH/src/github.com/unidoc/unipdf $GOPATH/src/github.com/unidoc/unipdf/v4
41 | ```
42 | or move/copy the unipdf folder to unipdf/v4 if symbolic links are not an option.
43 |
44 | Once this has been done, then can build using the build script as well:
45 | ```bash
46 | $ ./build_examples.sh
47 | ```
48 | or build individual example codes as desired.
49 |
--------------------------------------------------------------------------------
/accessibility/README.md:
--------------------------------------------------------------------------------
1 | ## PDF Accessibility Examples.
2 |
3 | The examples in this section are showcasing how to work with accessibility features.
4 |
5 | ## Examples
6 |
7 | - [pdf_add_image_alt_text.go](pdf_add_image_alt_text.go) showcases how to constuct a `StructTreeRoot` object and add alternate text for images.
8 | - [pdf_set_language_identifier.go](pdf_set_language_identifier.go) demonstrates how to set the language identifier for the document and its content.
9 | - [pdf_copy_page_with_accessibility.go](pdf_copy_page_with_accessibility.go) demonstrates how to copy pages from an existing PDF file to a new PDF file and preserve the structure tree information.
--------------------------------------------------------------------------------
/accessibility/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/accessibility/logo.png
--------------------------------------------------------------------------------
/advanced/README.md:
--------------------------------------------------------------------------------
1 | ## Advanced UniPDF Examples
2 |
3 | - pdf_grayscale_transform.go converts an entire PDF file to grayscale in a vectorized fashion,
4 | including images and all content.
5 |
6 | This advanced example demonstrates some of the more complex capabilities of UniPDF, showing the capability to process
7 | and transform objects and contents.
8 |
9 | The conversion applies to:
10 | 1. XObject images - and transforming through each color component to corresponding DeviceGray component.
11 | 2. Inline images.
12 | 3. Shapes such as lines as curves in the content stream.
13 | 4. Shadings and patterns.
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/advanced/grayscale_input.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/advanced/grayscale_input.pdf
--------------------------------------------------------------------------------
/advanced/grayscale_output.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/advanced/grayscale_output.pdf
--------------------------------------------------------------------------------
/analysis/README.md:
--------------------------------------------------------------------------------
1 | # PDF analysis and debugging.
2 |
3 | The examples in this section are intended to be used for debugging and getting information from
4 | PDF files.
5 |
6 | ## Examples
7 |
8 | - [pdf_all_objects.go](pdf_all_objects.go) outputs all numbered objects decoded and sorted to assist with debugging.
9 | - [pdf_detect_scanned.go](pdf_detect_scanned.go) checks for the signs of a scanned document.
10 | - [pdf_get_object.go](pdf_get_object.go) retrieves and writes out a specific numbered object (decoded).
11 | - [pdf_info.go](pdf_info.go) outputs basic info about a PDF file.
12 | - [pdf_inspect.go](pdf_inspect.go) performs a basic inspection on a PDF file and outptus some statistics on objects present.
13 | - [pdf_print_content_streams.go](pdf_print_content_streams.go) outputs the content streams for a specific page or all pages in a PDF file.
14 |
15 |
--------------------------------------------------------------------------------
/analysis/pdf_detect_scanned.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Detect scanned PDF files by looking through the object types and determining whether it is likely to be a scanned file.
3 | *
4 | * Run as: go run pdf_detect_scanned.go input.pdf
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/common/license"
14 | "github.com/unidoc/unipdf/v4/model"
15 | )
16 |
17 | func init() {
18 | // Make sure to load your metered License API key prior to using the library.
19 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
20 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
21 | if err != nil {
22 | panic(err)
23 | }
24 | }
25 |
26 | func main() {
27 | if len(os.Args) < 2 {
28 | fmt.Printf("Syntax: go run pdf_detect_scanned.go input1.pdf input2.pdf ...\n")
29 | os.Exit(1)
30 | }
31 |
32 | for _, inputPath := range os.Args[1:] {
33 | err := detectScanned(inputPath)
34 | if err != nil {
35 | fmt.Printf("Error: %v\n", err)
36 | }
37 | }
38 | }
39 |
40 | func detectScanned(inputPath string) error {
41 | pdfReader, f, err := model.NewPdfReaderFromFile(inputPath, nil)
42 | if err != nil {
43 | return err
44 | }
45 | defer f.Close()
46 |
47 | numPages, err := pdfReader.GetNumPages()
48 | if err != nil {
49 | return err
50 | }
51 | fmt.Printf("%s (%d pages) - ", inputPath, numPages)
52 | objTypes, err := pdfReader.Inspect()
53 | if err != nil {
54 | return err
55 | }
56 |
57 | fontObjs, ok := objTypes["Font"]
58 | if !ok || fontObjs < 2 {
59 | fmt.Printf("SCANNED!\n")
60 | } else {
61 | fmt.Printf("not scanned (has text objects)\n")
62 | }
63 |
64 | return nil
65 | }
66 |
--------------------------------------------------------------------------------
/analysis/pdf_info.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Prints basic PDF info: number of pages and encryption status.
3 | *
4 | * Run as: go run pdf_info.go input1.pdf [input2.pdf] ...
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/common/license"
14 | "github.com/unidoc/unipdf/v4/model"
15 | )
16 |
17 | func init() {
18 | // Make sure to load your metered License API key prior to using the library.
19 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
20 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
21 | if err != nil {
22 | panic(err)
23 | }
24 | }
25 |
26 | func main() {
27 | if len(os.Args) < 2 {
28 | fmt.Printf("Print out basic properties of PDF files\n")
29 | fmt.Printf("Usage: go run pdf_info.go input.pdf [input2.pdf] ...\n")
30 | os.Exit(1)
31 | }
32 |
33 | for _, inputPath := range os.Args[1:len(os.Args)] {
34 | fmt.Printf("Input file: %s\n", inputPath)
35 |
36 | ret, err := getPdfProperties(inputPath)
37 | if err != nil {
38 | fmt.Printf("Error: %v\n", err)
39 | os.Exit(1)
40 | }
41 |
42 | fmt.Printf(" Num Pages: %d\n", ret.NumPages)
43 | fmt.Printf(" Is Encrypted: %t\n", ret.IsEncrypted)
44 | fmt.Printf(" Is Viewable (without pass): %t\n", ret.CanView)
45 | }
46 | }
47 |
48 | type PdfProperties struct {
49 | IsEncrypted bool
50 | CanView bool // Is the document viewable without password?
51 | NumPages int
52 | }
53 |
54 | func getPdfProperties(inputPath string) (*PdfProperties, error) {
55 | ret := PdfProperties{}
56 |
57 | f, err := os.Open(inputPath)
58 | if err != nil {
59 | return nil, err
60 | }
61 |
62 | defer f.Close()
63 |
64 | pdfReader, err := model.NewPdfReader(f)
65 | if err != nil {
66 | return nil, err
67 | }
68 |
69 | isEncrypted, err := pdfReader.IsEncrypted()
70 | if err != nil {
71 | return nil, err
72 | }
73 |
74 | ret.IsEncrypted = isEncrypted
75 | ret.CanView = true
76 |
77 | // Try decrypting with an empty one.
78 | if isEncrypted {
79 | auth, err := pdfReader.Decrypt([]byte(""))
80 | if err != nil {
81 | return nil, err
82 | }
83 | ret.CanView = auth
84 | return &ret, nil
85 | }
86 |
87 | numPages, err := pdfReader.GetNumPages()
88 | if err != nil {
89 | return nil, err
90 | }
91 | ret.NumPages = numPages
92 |
93 | return &ret, nil
94 | }
95 |
--------------------------------------------------------------------------------
/annotations/README.md:
--------------------------------------------------------------------------------
1 | # PDF Annotations
2 |
3 | Annotations are different from normal PDF page contents and are stored separately. They are intended to mark up
4 | document contents, without changing the original document contents.
5 |
6 | Support for creating annotations in UniPDF is through the unipdf/annotator package.
7 | The annotator package creates the Annotation object and also an appearance stream, which is required to make
8 | the annotation look the same in all viewers.
9 |
10 | UniPDF's model package has support for all types of PDF annotations, whereas the annotator currently supports Square,
11 | Circle, Ellipse, Ink, Line, and File attachment annotations. Support for more annotation types will be added over time.
12 |
13 | If you need support for an unsupported annotation, please create an issue in this repository.
14 |
15 | The examples in this folder illustrate a few capabilities for creating ellipse, file attachment, ink, lines, rectangles, and text annotation.
16 |
17 | ## Examples
18 |
19 | - [pdf_annotate_add_ellipse.go](pdf_annotate_add_ellipse.go) adds a circle/ellipse annotation to a specified location on a page.
20 | - [pdf_annotate_add_file.go](pdf_annotate_add_file.go) adds a file attachment annotation placed in certain position in a page.
21 | - [pdf_annotate_add_ink.go](pdf_annotate_add_ink.go) adds an ink annotation to a specified location on a page.
22 | - [pdf_annotate_add_line.go](pdf_annotate_add_line.go) adds a line with arrowhead between two specified points on a page.
23 | - [pdf_annotate_add_rectangle.go](pdf_annotate_add_rectangle.go) adds a rectangle annotation to a specified location on a page.
24 | - [pdf_annotate_add_text.go](pdf_annotate_add_text.go) adds a text annotation with a user specified string to a fixed location on every page.
25 | - [pdf_list_annotations.go](pdf_list_annotations.go) lists all annotations in a PDF file.
26 |
27 |
--------------------------------------------------------------------------------
/annotations/pdf_list_annotations.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Lists annotations in a PDF file.
3 | *
4 | * Run as: go run pdf_list_annotations.go input.pdf [input2.pdf] ...
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/common/license"
14 | "github.com/unidoc/unipdf/v4/model"
15 | )
16 |
17 | func init() {
18 | // Make sure to load your metered License API key prior to using the library.
19 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
20 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
21 | if err != nil {
22 | panic(err)
23 | }
24 | }
25 |
26 | func main() {
27 | if len(os.Args) < 2 {
28 | fmt.Printf("Usage: go run pdf_list_annotations.go input.pdf [input2.pdf] ...\n")
29 | os.Exit(1)
30 | }
31 |
32 | for _, inputPath := range os.Args[1:len(os.Args)] {
33 | err := listAnnotations(inputPath)
34 | if err != nil {
35 | fmt.Printf("Error: %v\n", err)
36 | os.Exit(1)
37 | }
38 | }
39 | }
40 |
41 | func listAnnotations(inputPath string) error {
42 | pdfReader, f, err := model.NewPdfReaderFromFile(inputPath, nil)
43 | if err != nil {
44 | return err
45 | }
46 | defer f.Close()
47 |
48 | numPages, err := pdfReader.GetNumPages()
49 | if err != nil {
50 | return err
51 | }
52 | for i := 0; i < numPages; i++ {
53 | page, err := pdfReader.GetPage(i + 1)
54 | if err != nil {
55 | fmt.Printf("Error: %v\n", err)
56 | }
57 |
58 | fmt.Printf("-- Page %d\n", i+1)
59 | annotations, err := page.GetAnnotations()
60 | if err != nil {
61 | return err
62 | }
63 | printAnnotations(annotations)
64 | }
65 |
66 | return nil
67 | }
68 |
69 | func printAnnotations(annotations []*model.PdfAnnotation) {
70 | for idx, annotation := range annotations {
71 | fmt.Printf(" %d. %s\n", idx+1, annotation.String())
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/arabic-text/Amiri-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/arabic-text/Amiri-Regular.ttf
--------------------------------------------------------------------------------
/arabic-text/arabic-text.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/arabic-text/arabic-text.pdf
--------------------------------------------------------------------------------
/attachment/README.md:
--------------------------------------------------------------------------------
1 | # File Attachments
2 |
3 | Exemplify how to attach files into a PDF document and retrieves it.
4 |
5 | ## Examples
6 |
7 | - [pdf_add_attachment.go](pdf_add_attachment.go) Attach files into a PDF document, either by manually loading the file content or passing the file name.
8 | - [pdf_get_attachment.go](pdf_get_attachment.go) Retrieve list of file attachment and save it locally.
--------------------------------------------------------------------------------
/attachment/dummy.xml:
--------------------------------------------------------------------------------
1 |
2 | Tove
3 | Jani
4 | Reminder
5 | Don't forget me this weekend!
6 |
--------------------------------------------------------------------------------
/attachment/minimal.pdf:
--------------------------------------------------------------------------------
1 | %PDF-1.1
2 | %¥±ë
3 |
4 | 1 0 obj
5 | << /Type /Catalog
6 | /Pages 2 0 R
7 | >>
8 | endobj
9 |
10 | 2 0 obj
11 | << /Type /Pages
12 | /Kids [3 0 R]
13 | /Count 1
14 | /MediaBox [0 0 300 144]
15 | >>
16 | endobj
17 |
18 | 3 0 obj
19 | << /Type /Page
20 | /Parent 2 0 R
21 | /Resources
22 | << /Font
23 | << /F1
24 | << /Type /Font
25 | /Subtype /Type1
26 | /BaseFont /Times-Roman
27 | >>
28 | >>
29 | >>
30 | /Contents 4 0 R
31 | >>
32 | endobj
33 |
34 | 4 0 obj
35 | << /Length 55 >>
36 | stream
37 | BT
38 | /F1 18 Tf
39 | 0 0 Td
40 | (Hello World) Tj
41 | ET
42 | endstream
43 | endobj
44 |
45 | xref
46 | 0 5
47 | 0000000000 65535 f
48 | 0000000018 00000 n
49 | 0000000077 00000 n
50 | 0000000178 00000 n
51 | 0000000457 00000 n
52 | trailer
53 | << /Root 1 0 R
54 | /Size 5
55 | >>
56 | startxref
57 | 565
58 | %%EOF
59 |
--------------------------------------------------------------------------------
/attachment/pdf_get_attachment.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Retrieve list of attachment file and save it locally.
3 | */
4 |
5 | package main
6 |
7 | import (
8 | "fmt"
9 | "os"
10 | "path/filepath"
11 |
12 | "github.com/unidoc/unipdf/v4/common/license"
13 | "github.com/unidoc/unipdf/v4/model"
14 | )
15 |
16 | func init() {
17 | // Make sure to load your metered License API key prior to using the library.
18 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
19 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
20 | if err != nil {
21 | panic(err)
22 | }
23 | }
24 |
25 | func main() {
26 | inputPath := "output.pdf"
27 |
28 | err := listAttachments(inputPath)
29 | if err != nil {
30 | fmt.Printf("%v\n", err)
31 | os.Exit(1)
32 | }
33 |
34 | fmt.Println("Done")
35 | }
36 |
37 | func listAttachments(inputPath string) error {
38 | // Read the input pdf file.
39 | f, err := os.Open(inputPath)
40 | if err != nil {
41 | return err
42 | }
43 | defer f.Close()
44 |
45 | pdfReader, err := model.NewPdfReader(f)
46 | if err != nil {
47 | return err
48 | }
49 |
50 | files, err := pdfReader.GetAttachedFiles()
51 | if err != nil {
52 | return err
53 | }
54 |
55 | _, err = os.Stat("output")
56 | if os.IsNotExist(err) {
57 | err = os.Mkdir("output", 0777)
58 | if err != nil {
59 | return err
60 | }
61 | }
62 |
63 | for _, v := range files {
64 | err := os.WriteFile(filepath.Join("output", fmt.Sprintf("%s.xml", v.Name)), v.Content, 0655)
65 | if err != nil {
66 | return err
67 | }
68 |
69 | fmt.Printf("Name: %s; Hash: %s\n", v.Name, v.Hash)
70 | }
71 |
72 | return nil
73 | }
74 |
--------------------------------------------------------------------------------
/barcode/README.md:
--------------------------------------------------------------------------------
1 | # Barcode/QR PDF creation
2 |
3 | Exemplifies how to apply barcode and QR codes to existing PDF files or newly generates PDFs.
4 |
5 | The examples use github.com/boombuler/barcode for creating the codes.
6 |
7 | ## Examples
8 |
9 | - [pdf_add_barcode.go](pdf_add_barcode.go) creates a barcode and inserts on a specific location in a PDf file.
10 | - [pdf_add_qr_code.go](pdf_add_qr_code.go) creates QR code and inserts on a specific location in a PDf file.
11 |
--------------------------------------------------------------------------------
/build_examples.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # Stop script execution on error
4 | set -euo pipefail
5 |
6 | mkdir -p bin
7 |
8 | echo "Building to bin/ folder"
9 |
10 | # CGO required to build example relying on crypto11 and imagick dependency.
11 | find . -name "*.go" ! -name "*_cgo.go" ! -name "lib_*" -print0 | CGO_ENABLED=0 xargs -0 -n1 -I% bash -c 'go build -o bin % || exit 255'
12 | find . -name "*_cgo.go" -print0 | CGO_ENABLED=1 CGO_CFLAGS_ALLOW='-Xpreprocessor' xargs -0 -n1 -I% bash -c 'go build -o bin % || exit 255'
13 |
--------------------------------------------------------------------------------
/compress/README.md:
--------------------------------------------------------------------------------
1 | # PDF compression (optimization)
2 |
3 | Optimization of PDF output is implemented in the PDF writer of UniPDF and contains multiple options (optimize.Options)
4 | ```go
5 | // Options describes PDF optimization parameters.
6 | type Options struct {
7 | CombineDuplicateStreams bool
8 | CombineDuplicateDirectObjects bool
9 | ImageUpperPPI float64
10 | ImageQuality int
11 | UseObjectStreams bool
12 | CombineIdenticalIndirectObjects bool
13 | CompressStreams bool
14 | CleanFonts bool
15 | SubsetFonts bool
16 | CleanContentstream bool
17 | CleanUnusedResources bool
18 | }
19 | ```
20 |
21 | From the available filters listed above, all of them except `ImageQuality` and `ImageUpperPPI` enable lossless compression.
22 |
23 | ## Examples
24 |
25 | - [pdf_optimize.go](pdf_optimize.go) compresses a PDF file with some typical options.
26 | - [pdf_font_subsetting.go](pdf_font_subsetting.go) illustrates how to reduce a PDF file size by subsetting all fonts used in the document using `SubsetFonts` Optimizer option.
27 | - [pdf_remove_unused_resources.go](pdf_remove_unused_resources.go) reduces file size by removing unused resources such as Images, Xforms, fonts and external graphics state dictionaries.
28 |
--------------------------------------------------------------------------------
/compress/outputs/ouput_file_1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/compress/outputs/ouput_file_1.pdf
--------------------------------------------------------------------------------
/compress/outputs/ouput_file_2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/compress/outputs/ouput_file_2.pdf
--------------------------------------------------------------------------------
/compress/outputs/ouput_file_3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/compress/outputs/ouput_file_3.pdf
--------------------------------------------------------------------------------
/compress/test_files/test_file_1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/compress/test_files/test_file_1.pdf
--------------------------------------------------------------------------------
/compress/test_files/test_file_2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/compress/test_files/test_file_2.pdf
--------------------------------------------------------------------------------
/compress/test_files/test_file_3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/compress/test_files/test_file_3.pdf
--------------------------------------------------------------------------------
/concurrent-processing/README.md:
--------------------------------------------------------------------------------
1 | # concurrent processing
2 |
3 | UniPDF supports document level concurrent processing. This means processing each document separately in its own go routine.
4 | The concurrency is supported on document level for now. Page level concurrency in UniPDF is not safe yet.
5 |
6 | ## Examples
7 | - [concurrent_extraction.go](concurrent_extraction.go) Extracts text from multiple documents provided via the command line arguments concurrently and saves the result to a text file.
--------------------------------------------------------------------------------
/drawing/README.md:
--------------------------------------------------------------------------------
1 | # Drawing on PDF
2 | Drawing in PDF is done through vectorized operands in the content stream.
3 | UniPDF provides functions to do this for common shapes, otherwise custom
4 | objects can always be applied to the content stream directly.
5 |
6 | ## Examples
7 |
8 | - [pdf_draw_shapes.go](pdf_draw_shapes.go) draws multiple shapes in a new PDF file.
9 | - [pdf_draw_lines.go](pdf_draw_lines.go) showcases the capabilities of creator lines.
10 |
--------------------------------------------------------------------------------
/drawing/unipdf-draw-lines.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/drawing/unipdf-draw-lines.pdf
--------------------------------------------------------------------------------
/drawing/unipdf-draw-shapes.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/drawing/unipdf-draw-shapes.pdf
--------------------------------------------------------------------------------
/extract-bullet-lists/README.md:
--------------------------------------------------------------------------------
1 | # Bullet list extractor examples
2 |
3 | This example demonstrates how to extract bullet point lists from a pdf document.
4 | bullet point lists are lists that are marked with bullet point characters, with sequential numbering system i.e roman numerals, english alphabet, or hindu arabic numerals (1,2,3).
5 | The extracted content only contains the texts that are part of the bullet list and related sub lists.
6 | The rest of contents is ignored.
7 |
8 | To extract bullet point lists from a given pdf page:
9 | - First construct an `extractor` from a given pdf page.
10 | - Then get the `PageText` object by calling `ExtractPageText()` method.
11 | - Finally get the slice of bullet point lists from `PageText.List()`.
12 | This returns a slice of lists that have a tree structure.
13 | ```go
14 | ex, err := extractor.New(pdfPage)
15 | // handle error
16 | pageText, _, _, err := ex.ExtractPageText()
17 | // handle another error
18 | bulletLists := pageText.List()
19 | ```
20 |
21 | The textual representation is found by calling the `Text()` method on the bulletLists.
22 |
23 | By default the bullet list in a given pdf page are extracted in two ways.
24 | 1. Using document accessibility tags if the file is tagged
25 | 2. If tags are not available then simple regex matching is performed on the raw text of that page to detect the possible bullet point lists.
26 |
27 | However this behavior can be changed using the `DisableDocumentTags` attribute of `Options` object in extractor package.
28 |
29 | This can be done as follows.
30 | ```go
31 | options := &extractor.Options{
32 | DisableDocumentTags: true,
33 | }
34 | ex, err := extractor.NewWithOptions(pdfPage, options)
35 | ```
36 | If the pdf document was tagged poorly, especially if the bullet lists were not tagged with appropriate tag structures, then the second way of extracting may give a better result. This way we can take advantage of both extraction methods.
--------------------------------------------------------------------------------
/extract-bullet-lists/extract_bullet_list.go:
--------------------------------------------------------------------------------
1 | /*
2 | * An example code to extract bullet point list from pdf document.
3 | *
4 | * Run as: go run extract_bullet_list.go input.pdf 1 output.txt
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 | "strconv"
13 |
14 | "github.com/unidoc/unipdf/v4/common/license"
15 | "github.com/unidoc/unipdf/v4/extractor"
16 | "github.com/unidoc/unipdf/v4/model"
17 | )
18 |
19 | func init() {
20 | // Make sure to load your metered License API key prior to using the library.
21 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
22 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
23 | if err != nil {
24 | panic(err)
25 | }
26 | }
27 |
28 | func main() {
29 | if len(os.Args) < 4 {
30 | fmt.Printf("Usage: go run extract_bullet_list.go inputFile.pdf 1 output.txt \n")
31 | os.Exit(1)
32 | }
33 | inputFile := os.Args[1]
34 | p := os.Args[2]
35 | output := os.Args[3]
36 | page, err := strconv.Atoi(p)
37 | if err != nil {
38 | fmt.Printf("wrong page value.\nUsage: go run extract_bullet_list.go inputFile.pdf 1 output.txt\n")
39 | os.Exit(1)
40 | }
41 | fout, err := os.Create(output)
42 | if err != nil {
43 | fmt.Printf("failed: %s", err)
44 | os.Exit(1)
45 | }
46 | defer fout.Close()
47 | txt := extractBulletList(inputFile, page)
48 | _, err = fout.WriteString(txt)
49 | if err != nil {
50 | fmt.Printf("failed to write: %s ", err)
51 | os.Exit(1)
52 | }
53 | fmt.Println(txt)
54 | }
55 |
56 | // extractBulletList extracts bullet point lists on `file` at `pageNum` and returns the string representation of the list.
57 | func extractBulletList(file string, pageNum int) string {
58 | pdfReader, f, err := model.NewPdfReaderFromFile(file, nil)
59 | if err != nil {
60 | panic(err)
61 | }
62 | defer f.Close()
63 | page, err := pdfReader.GetPage(pageNum)
64 | if err != nil {
65 | panic(err)
66 | }
67 | options := &extractor.Options{
68 | DisableDocumentTags: false,
69 | }
70 | ex, err := extractor.NewWithOptions(page, options)
71 | if err != nil {
72 | panic(err)
73 | }
74 | pageText, _, _, err := ex.ExtractPageText()
75 | if err != nil {
76 | panic(err)
77 | }
78 | lists := pageText.List()
79 | txt := lists.Text()
80 | return txt
81 | }
82 |
--------------------------------------------------------------------------------
/extract-bullet-lists/output/list_file2_page2.txt:
--------------------------------------------------------------------------------
1 | 2.2. Put your cursor in a paragraph of the style you want to modify. So if you want to modify the
2 | style Body Text, put your cursor in a paragraph of Body Text style.
3 | 2.3. Use Format > Font, Format > Paragraph, Format > Borders and Shading etc to make the
4 | required changes
5 | 2.4. If you're modifying a paragraph style, click within the paragraph (so no text is selected) or,
6 | select the whole paragraph (triple-click to select the whole paragraph). If you're modifying
7 | a character style, select one or more characters in that character style.
8 | 2.5. From the "Styles" box on the Formatting toolbar, re-choose the name of the style. Word
9 | will ask if you want to update the style, or reapply the current style to the selected text, as
10 | shown in Figure 1. If you want to say sane, do not tick the Automatically Update Style box.
11 |
--------------------------------------------------------------------------------
/extract-bullet-lists/test-files/tagged-pdf-2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/extract-bullet-lists/test-files/tagged-pdf-2.pdf
--------------------------------------------------------------------------------
/extract-bullet-lists/test-files/untagged-pdf-3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/extract-bullet-lists/test-files/untagged-pdf-3.pdf
--------------------------------------------------------------------------------
/extract/README.md:
--------------------------------------------------------------------------------
1 | Various extraction example code.
2 |
3 | ## Examples
4 |
5 | - [extract_text_bound.go](extract_text_bound.go) The example showcases how to extract all text for each page along with it's boundary information.
6 | - [pdf_extract_location.go](pdf_extract_location.go) The example showcases how to extract text at certain location.
7 | - [pdf_extract_text.go](pdf_extract_text.go) The example showcases how to extract all text for each page of a PDF file.
8 | - [pdf_simple_extraction.go](pdf_simple_extraction.go) The example showcases how to use a simple extraction procedure in the text extraction process, which skips table processing and topological ordering. This procedure could be useful in some cases where full extraction process giving unwanted extraction result, especially when processing tables.
9 | - [pdf_tables.go](pdf_tables.go) The example showcase how to extract all tables from the specified pages of one or more PDF files.
10 | - [reconstruct_text.go](reconstruct_text.go) Example that illustrates the accuracy of the text extraction, by first extracting all TextMarks and then reconstructing the text by writing out the text page-by-page to a new PDF with the creator package.
11 | - [reconstruct_words.go](reconstruct_words.go) The example expands upon [reconstruct_text.go](reconstruct_text.go) to show word placements.
12 | - [pdf_extract_images.go](pdf_extract_images.go) explains how to extract images from an existing PDF. The code passes through each page, goes through the content stream and finds XObject Images and inline images. Also handles images referred within XObject Form content streams. The output files are saved as a zip archive.
13 |
--------------------------------------------------------------------------------
/extract/pdf_extract_text.go:
--------------------------------------------------------------------------------
1 | /*
2 | * PDF to text: Extract all text for each page of a pdf file.
3 | *
4 | * Run as: go run pdf_extract_text.go input.pdf
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/common/license"
14 | "github.com/unidoc/unipdf/v4/extractor"
15 | "github.com/unidoc/unipdf/v4/model"
16 | )
17 |
18 | func init() {
19 | // Make sure to load your metered License API key prior to using the library.
20 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
21 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
22 | if err != nil {
23 | panic(err)
24 | }
25 | }
26 |
27 | func main() {
28 | if len(os.Args) < 2 {
29 | fmt.Printf("Usage: go run pdf_extract_text.go input.pdf\n")
30 | os.Exit(1)
31 | }
32 |
33 | inputPath := os.Args[1]
34 |
35 | err := outputPdfText(inputPath)
36 | if err != nil {
37 | fmt.Printf("Error: %v\n", err)
38 | os.Exit(1)
39 | }
40 | }
41 |
42 | // outputPdfText prints out contents of PDF file to stdout.
43 | func outputPdfText(inputPath string) error {
44 | f, err := os.Open(inputPath)
45 | if err != nil {
46 | return err
47 | }
48 |
49 | defer f.Close()
50 |
51 | pdfReader, err := model.NewPdfReader(f)
52 | if err != nil {
53 | return err
54 | }
55 |
56 | numPages, err := pdfReader.GetNumPages()
57 | if err != nil {
58 | return err
59 | }
60 |
61 | fmt.Printf("--------------------\n")
62 | fmt.Printf("PDF to text extraction:\n")
63 | fmt.Printf("--------------------\n")
64 | for i := 0; i < numPages; i++ {
65 | pageNum := i + 1
66 |
67 | page, err := pdfReader.GetPage(pageNum)
68 | if err != nil {
69 | return err
70 | }
71 |
72 | ex, err := extractor.New(page)
73 | if err != nil {
74 | return err
75 | }
76 |
77 | text, err := ex.ExtractText()
78 | if err != nil {
79 | return err
80 | }
81 |
82 | fmt.Println("------------------------------")
83 | fmt.Printf("Page %d:\n", pageNum)
84 | fmt.Printf("\"%s\"\n", text)
85 | fmt.Println("------------------------------")
86 | }
87 |
88 | return nil
89 | }
90 |
--------------------------------------------------------------------------------
/extract/pdf_simple_extraction.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Using a plain/simple extraction mode in the text extraction process, which skips table processing and topological ordering.
3 | *
4 | * Run as: go run pdf_simple_extraction.go input.pdf
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/common/license"
14 | "github.com/unidoc/unipdf/v4/extractor"
15 | "github.com/unidoc/unipdf/v4/model"
16 | )
17 |
18 | func init() {
19 | // Make sure to load your metered License API key prior to using the library.
20 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
21 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
22 | if err != nil {
23 | panic(err)
24 | }
25 | }
26 |
27 | func main() {
28 | if len(os.Args) < 2 {
29 | fmt.Printf("Usage: go run pdf_simple_extraction.go input.pdf\n")
30 | os.Exit(1)
31 | }
32 |
33 | inputPath := os.Args[1]
34 |
35 | err := outputPdfText(inputPath)
36 | if err != nil {
37 | fmt.Printf("Error: %v\n", err)
38 | os.Exit(1)
39 | }
40 | }
41 |
42 | // outputPdfText prints out contents of PDF file to stdout.
43 | func outputPdfText(inputPath string) error {
44 | f, err := os.Open(inputPath)
45 | if err != nil {
46 | return err
47 | }
48 |
49 | defer f.Close()
50 |
51 | pdfReader, err := model.NewPdfReader(f)
52 | if err != nil {
53 | return err
54 | }
55 |
56 | numPages, err := pdfReader.GetNumPages()
57 | if err != nil {
58 | return err
59 | }
60 |
61 | fmt.Printf("--------------------\n")
62 | fmt.Printf("PDF to text extraction:\n")
63 | fmt.Printf("--------------------\n")
64 | for i := 0; i < numPages; i++ {
65 | pageNum := i + 1
66 |
67 | page, err := pdfReader.GetPage(pageNum)
68 | if err != nil {
69 | return err
70 | }
71 |
72 | ex, err := extractor.NewWithOptions(page, &extractor.Options{
73 | ExtractionMode: extractor.ExtractionModePlain,
74 | })
75 | if err != nil {
76 | return err
77 | }
78 |
79 | text, err := ex.ExtractText()
80 | if err != nil {
81 | return err
82 | }
83 |
84 | fmt.Println("------------------------------")
85 | fmt.Printf("Page %d:\n", pageNum)
86 | fmt.Printf("\"%s\"\n", text)
87 | fmt.Println("------------------------------")
88 | }
89 |
90 | return nil
91 | }
92 |
--------------------------------------------------------------------------------
/forms/DoHyeon-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/DoHyeon-Regular.ttf
--------------------------------------------------------------------------------
/forms/fdf_fields_info.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Prints basic FDF field data in terms of key and values.
3 | *
4 | * Run as: go run fdf_fields_info.go input1.fdf [input2.fdf ...]
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 | "sort"
13 |
14 | "github.com/unidoc/unipdf/v4/common/license"
15 | "github.com/unidoc/unipdf/v4/core"
16 | "github.com/unidoc/unipdf/v4/fdf"
17 | )
18 |
19 | func init() {
20 | // Make sure to load your metered License API key prior to using the library.
21 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
22 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
23 | if err != nil {
24 | panic(err)
25 | }
26 | }
27 |
28 | func main() {
29 | if len(os.Args) < 2 {
30 | fmt.Printf("Print out basic properties of FDF files\n")
31 | fmt.Printf("Usage: go run fdf_fields_info.go input.fdf [input2.pdf] ...\n")
32 | os.Exit(1)
33 | }
34 |
35 | // Enable debug-level logging.
36 | // common.SetLogger(common.NewConsoleLogger(common.LogLevelDebug))
37 |
38 | for _, inputPath := range os.Args[1:len(os.Args)] {
39 | fmt.Printf("Input file: %s\n", inputPath)
40 |
41 | err := printFdfInfo(inputPath)
42 | if err != nil {
43 | fmt.Printf("Error: %v\n", err)
44 | os.Exit(1)
45 | }
46 | }
47 | }
48 |
49 | func printFdfInfo(inputPath string) error {
50 | fdf, err := fdf.LoadFromPath(inputPath)
51 | if err != nil {
52 | return err
53 | }
54 |
55 | fieldMap, err := fdf.FieldDictionaries()
56 | if err != nil {
57 | return err
58 | }
59 |
60 | // Sort field names alphabetically.
61 | keys := []string{}
62 | for key, _ := range fieldMap {
63 | keys = append(keys, key)
64 | }
65 | sort.Strings(keys)
66 |
67 | for _, key := range keys {
68 | fieldDict := fieldMap[key]
69 | // Key value field data.
70 | t, _ := core.GetString(fieldDict.Get("T"))
71 | v := core.TraceToDirectObject(fieldDict.Get("V"))
72 | if t != nil && v != nil {
73 | fmt.Printf("Field T: %v, V: %v\n", t, v.String())
74 | }
75 |
76 | }
77 |
78 | return nil
79 | }
80 |
--------------------------------------------------------------------------------
/forms/filled_form_rich.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/filled_form_rich.pdf
--------------------------------------------------------------------------------
/forms/form_field_with_colored_text_fields.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/form_field_with_colored_text_fields.pdf
--------------------------------------------------------------------------------
/forms/form_fields_rotations.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "textfield1",
4 | "value": "Test Text Fill"
5 | },
6 | {
7 | "name": "cb1",
8 | "value": "true"
9 | },
10 | {
11 | "name": "cb2",
12 | "value": "true"
13 | }
14 | ]
--------------------------------------------------------------------------------
/forms/form_fields_rotations.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/form_fields_rotations.pdf
--------------------------------------------------------------------------------
/forms/formdata.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "formID",
4 | "value": "202286033286049"
5 | },
6 | {
7 | "name": "pdf_submission_new",
8 | "value": "1"
9 | },
10 | {
11 | "name": "simple_spc",
12 | "value": "202286033286049-202286033286049"
13 | },
14 | {
15 | "name": "adobeWarning",
16 | "value": "In order to submit this form, you should open it with Adobe Acrobat Reader."
17 | },
18 | {
19 | "name": "name3[first]",
20 | "value": "John"
21 | },
22 | {
23 | "name": "name3[last]",
24 | "value": "Doe"
25 | },
26 | {
27 | "name": "email4",
28 | "value": "alpha@omega.com"
29 | },
30 | {
31 | "name": "address5[addr_line1]",
32 | "value": "高橋町鈴木5-4-1"
33 | },
34 | {
35 | "name": "address5[addr_line2]",
36 | "value": "-"
37 | },
38 | {
39 | "name": "address5[city]",
40 | "value": "小泉市"
41 | },
42 | {
43 | "name": "address5[state]",
44 | "value": "-"
45 | },
46 | {
47 | "name": "address5[postal]",
48 | "value": "3538148"
49 | },
50 | {
51 | "name": "fakeSubmitButton",
52 | "value": "Submit"
53 | },
54 | {
55 | "name": "submitButton",
56 | "value": ""
57 | }
58 | ]
59 |
--------------------------------------------------------------------------------
/forms/images/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/images/1.jpg
--------------------------------------------------------------------------------
/forms/pdf_form_flatten_non_url.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Partially flatten form data in PDF files by using a callback to filter a non URL annotations.
3 | *
4 | * Run as: go run pdf_form_flatten_non_url.go pdf_file
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/annotator"
14 | "github.com/unidoc/unipdf/v4/common/license"
15 | "github.com/unidoc/unipdf/v4/model"
16 | )
17 |
18 | func init() {
19 | // Make sure to load your metered License API key prior to using the library.
20 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
21 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
22 | if err != nil {
23 | panic(err)
24 | }
25 | }
26 |
27 | func main() {
28 | if len(os.Args) < 2 {
29 | fmt.Printf("Usage: go run pdf_form_flatten_non_url.go \n")
30 | os.Exit(1)
31 | }
32 |
33 | inputPath := os.Args[1]
34 | outputPath := fmt.Sprintf("flatten_non_url_%s", inputPath)
35 |
36 | err := nonUrlFlattenPdf(inputPath, outputPath)
37 | if err != nil {
38 | fmt.Printf("%s - Error: %v\n", inputPath, err)
39 | }
40 | }
41 |
42 | // nonUrlFlattenPdf flattens non url annotations.
43 | func nonUrlFlattenPdf(inputPath, outputPath string) error {
44 | f, err := os.Open(inputPath)
45 | if err != nil {
46 | return err
47 | }
48 | defer f.Close()
49 |
50 | pdfReader, err := model.NewPdfReader(f)
51 | if err != nil {
52 | return err
53 | }
54 |
55 | // Define annotation filter to exclude URL from flattening process.
56 | nonUrlFlattenOpts := model.FieldFlattenOpts{
57 | AnnotFilterFunc: func(pa *model.PdfAnnotation) bool {
58 | switch pa.GetContext().(type) {
59 | case *model.PdfAnnotationLink:
60 | return false
61 | }
62 |
63 | return true
64 | },
65 | }
66 |
67 | fieldAppearance := annotator.FieldAppearance{}
68 | err = pdfReader.FlattenFieldsWithOpts(fieldAppearance, &nonUrlFlattenOpts)
69 | if err != nil {
70 | return err
71 | }
72 |
73 | // Generate a PdfWriter instance from existing PdfReader.
74 | pdfWriter, err := pdfReader.ToWriter(nil)
75 | if err != nil {
76 | return err
77 | }
78 |
79 | // Write to file.
80 | err = pdfWriter.WriteToFile(outputPath)
81 | if err != nil {
82 | return err
83 | }
84 |
85 | return nil
86 | }
87 |
--------------------------------------------------------------------------------
/forms/pdf_form_get_field_data.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Get form field data for a specific field from a PDF file.
3 | *
4 | * Run as: go run pdf_form_get_field_data [full field name]
5 | * If no field specified will output values for all fields.
6 | */
7 |
8 | package main
9 |
10 | import (
11 | "errors"
12 | "fmt"
13 | "os"
14 |
15 | "github.com/unidoc/unipdf/v4/common/license"
16 | "github.com/unidoc/unipdf/v4/model"
17 | )
18 |
19 | func init() {
20 | // Make sure to load your metered License API key prior to using the library.
21 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
22 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
23 | if err != nil {
24 | panic(err)
25 | }
26 | }
27 |
28 | func main() {
29 | if len(os.Args) < 2 {
30 | fmt.Printf("Usage: go run pdf_forms_list_fields.go [full field name]\n")
31 | os.Exit(1)
32 | }
33 |
34 | pdfPath := os.Args[1]
35 | fieldName := ""
36 | if len(os.Args) >= 3 {
37 | fieldName = os.Args[2]
38 | }
39 |
40 | err := printPdfFieldData(pdfPath, fieldName)
41 | if err != nil {
42 | fmt.Printf("Error: %v\n", err)
43 | os.Exit(1)
44 | }
45 | }
46 |
47 | func printPdfFieldData(inputPath, targetFieldName string) error {
48 | f, err := os.Open(inputPath)
49 | if err != nil {
50 | return err
51 | }
52 | fmt.Printf("Input file: %s\n", inputPath)
53 |
54 | defer f.Close()
55 |
56 | pdfReader, err := model.NewPdfReader(f)
57 | if err != nil {
58 | return err
59 | }
60 |
61 | acroForm := pdfReader.AcroForm
62 | if acroForm == nil {
63 | fmt.Printf(" No formdata present\n")
64 | return nil
65 | }
66 |
67 | match := false
68 | fields := acroForm.AllFields()
69 | for _, field := range fields {
70 | fullname, err := field.FullName()
71 | if err != nil {
72 | return err
73 | }
74 | if fullname == targetFieldName || targetFieldName == "" {
75 | match = true
76 | if field.V != nil {
77 | fmt.Printf("Field '%s': '%v' (%T)\n", fullname, field.V, field.V)
78 | } else {
79 | fmt.Printf("Field '%s': not filled\n", fullname)
80 | }
81 | }
82 | }
83 |
84 | if !match {
85 | return errors.New("field not found")
86 | }
87 | return nil
88 | }
89 |
--------------------------------------------------------------------------------
/forms/pdf_form_partial_flatten.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Partially flatten form data in PDF file by using a callback function to filter Fields.
3 | *
4 | * Run as: go run pdf_form_partial_flatten.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/annotator"
14 | "github.com/unidoc/unipdf/v4/common/license"
15 | "github.com/unidoc/unipdf/v4/model"
16 | )
17 |
18 | func init() {
19 | // Make sure to load your metered License API key prior to using the library.
20 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
21 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
22 | if err != nil {
23 | panic(err)
24 | }
25 | }
26 |
27 | func main() {
28 | inputFile := "sample_form.pdf"
29 | outputFile := "partial_flattened_sample_form.pdf"
30 | fieldToFlatten := []string{
31 | "email4",
32 | "address5[city]",
33 | }
34 |
35 | err := partialFlattenPdf(inputFile, outputFile, fieldToFlatten)
36 | if err != nil {
37 | fmt.Printf("%s - Error: %v\n", inputFile, err)
38 | os.Exit(1)
39 | }
40 | }
41 |
42 | // partialFlattenPdf partially flattens annotations and forms moving
43 | // the appearance stream to the page contents so cannot be modified.
44 | func partialFlattenPdf(inputPath, outputPath string, fieldToFlatten []string) error {
45 | f, err := os.Open(inputPath)
46 | if err != nil {
47 | return err
48 | }
49 | defer f.Close()
50 |
51 | pdfReader, err := model.NewPdfReader(f)
52 | if err != nil {
53 | return err
54 | }
55 |
56 | fieldFlattenOpts := model.FieldFlattenOpts{
57 | FilterFunc: func(pf *model.PdfField) bool {
58 | for _, fName := range fieldToFlatten {
59 | if pf.T.String() == fName {
60 | return true
61 | }
62 | }
63 |
64 | return false
65 | },
66 | }
67 |
68 | fieldAppearance := annotator.FieldAppearance{}
69 | err = pdfReader.FlattenFieldsWithOpts(fieldAppearance, &fieldFlattenOpts)
70 | if err != nil {
71 | return err
72 | }
73 |
74 | // Generate a PdfWriter instance from existing PdfReader.
75 | pdfWriter, err := pdfReader.ToWriter(nil)
76 | if err != nil {
77 | return err
78 | }
79 |
80 | // Write to file.
81 | err = pdfWriter.WriteToFile(outputPath)
82 | return err
83 | }
84 |
--------------------------------------------------------------------------------
/forms/rounded-mplus-1p-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/rounded-mplus-1p-regular.ttf
--------------------------------------------------------------------------------
/forms/sample_form.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "formID",
4 | "value": "202286033286049"
5 | },
6 | {
7 | "name": "pdf_submission_new",
8 | "value": "1"
9 | },
10 | {
11 | "name": "simple_spc",
12 | "value": "202286033286049-202286033286049"
13 | },
14 | {
15 | "name": "adobeWarning",
16 | "value": "In order to submit this form, you should open it with Adobe Acrobat Reader."
17 | },
18 | {
19 | "name": "name3[first]",
20 | "value": "John"
21 | },
22 | {
23 | "name": "name3[last]",
24 | "value": "Doe"
25 | },
26 | {
27 | "name": "email4",
28 | "value": "alpha@omega.com"
29 | },
30 | {
31 | "name": "address5[addr_line1]",
32 | "value": "sample address line 1"
33 | },
34 | {
35 | "name": "address5[addr_line2]",
36 | "value": "sample address line 2"
37 | },
38 | {
39 | "name": "address5[city]",
40 | "value": "sample address"
41 | },
42 | {
43 | "name": "address5[state]",
44 | "value": "sample state"
45 | },
46 | {
47 | "name": "address5[postal]",
48 | "value": "3538148"
49 | },
50 | {
51 | "name": "fakeSubmitButton",
52 | "value": "Submit"
53 | },
54 | {
55 | "name": "submitButton",
56 | "value": ""
57 | }
58 | ]
59 |
--------------------------------------------------------------------------------
/forms/sample_form.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/sample_form.pdf
--------------------------------------------------------------------------------
/forms/sample_form_output.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/sample_form_output.pdf
--------------------------------------------------------------------------------
/forms/sample_form_rich.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "formID",
4 | "value": "202286033286049"
5 | },
6 | {
7 | "name": "pdf_submission_new",
8 | "value": "1",
9 | "text_color": "#40E0D0"
10 | },
11 | {
12 | "name": "simple_spc",
13 | "value": "202286033286049-202286033286049",
14 | "text_color": "#6495ED"
15 | },
16 | {
17 | "name": "adobeWarning",
18 | "value": "In order to submit this form, you should open it with Adobe Acrobat Reader.",
19 | "text_color": "#008000"
20 | },
21 | {
22 | "name": "name3[first]",
23 | "value": "John",
24 | "text_color": "#0000FF",
25 | "fill_color": "#FFD700",
26 | "border_color": "#CD5C5C"
27 | },
28 | {
29 | "name": "name3[last]",
30 | "value": "Doe",
31 | "text_color": "#7dcea0"
32 | },
33 | {
34 | "name": "email4",
35 | "value": "alpha@omega.com",
36 | "text_color": "#CD5C5C"
37 | },
38 | {
39 | "name": "address5[addr_line1]",
40 | "value": "sample address line 1",
41 | "text_color": "#008000"
42 | },
43 | {
44 | "name": "address5[addr_line2]",
45 | "value": "sample address line 2",
46 | "text_color": "#40E0D0"
47 | },
48 | {
49 | "name": "address5[city]",
50 | "value": "sample address",
51 | "text_color": "#00FF00"
52 | },
53 | {
54 | "name": "address5[state]",
55 | "value": "sample state",
56 | "text_color": "#2596be"
57 | },
58 | {
59 | "name": "address5[postal]",
60 | "value": "3538148",
61 | "text_color": "#063970"
62 | },
63 | {
64 | "name": "fakeSubmitButton",
65 | "value": "Submit"
66 | },
67 | {
68 | "name": "submitButton",
69 | "value": ""
70 | }
71 | ]
--------------------------------------------------------------------------------
/forms/template1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/forms/template1.pdf
--------------------------------------------------------------------------------
/grid/README.md:
--------------------------------------------------------------------------------
1 | # PDF Grid
2 |
3 | The example explains how to create grids in your PDF reports. The grid component can be used for creating different layouts in the report, or for creating tables.
4 |
5 | ## Examples
6 |
7 | - [pdf_grid_simple.go](pdf_grid_simple.go) The example showcases how you can use the power of the `creator` package to create a simple grid.
8 | - [pdf_grid_colspan.go](pdf_grid_colspan.go) The example showcases how to create grid with a cell occupying several columns.
9 | - [pdf_grid_rowspan.go](pdf_grid_rowspan.go) The example showcases how to create grid with a cell occupying several rows.
10 | - [pdf_grid_wrapping.go](pdf_grid_wrapping.go) The example showcases how to create grid wrapped across the pages.
--------------------------------------------------------------------------------
/grid/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/grid/logo.png
--------------------------------------------------------------------------------
/grid/unipdf-grid-colspan.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/grid/unipdf-grid-colspan.pdf
--------------------------------------------------------------------------------
/grid/unipdf-grid-rowspan.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/grid/unipdf-grid-rowspan.pdf
--------------------------------------------------------------------------------
/grid/unipdf-grid-simple.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/grid/unipdf-grid-simple.pdf
--------------------------------------------------------------------------------
/grid/unipdf-grid-wrapping.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/grid/unipdf-grid-wrapping.pdf
--------------------------------------------------------------------------------
/hebrew-text/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/hebrew-text/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/hebrew-text/hebrew-text.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/hebrew-text/hebrew-text.pdf
--------------------------------------------------------------------------------
/hebrew-text/pdf_write_hebrew.go:
--------------------------------------------------------------------------------
1 | /*
2 | * An example of writing Hebrew text
3 | *
4 | * Run as: go run pdf_write_hebrew.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "os"
11 |
12 | "github.com/unidoc/unipdf/v4/common/license"
13 | "github.com/unidoc/unipdf/v4/creator"
14 | "github.com/unidoc/unipdf/v4/model"
15 | )
16 |
17 | func init() {
18 | // Make sure to load your metered License API key prior to using the library.
19 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
20 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
21 | if err != nil {
22 | panic(err)
23 | }
24 | }
25 |
26 | func main() {
27 | font, err := model.NewCompositePdfFontFromTTFFile("./OpenSans-Regular.ttf")
28 | if err != nil {
29 | panic(err)
30 | }
31 |
32 | c := creator.New()
33 | c.SetPageSize(creator.PageSizeA5)
34 |
35 | hebrew := `שונה תוכל חפש מה, דת חפש היום כדור מיזמים, היא מה גרמנית מרצועת. לעריכת האנציקלופדיה או קרן, ספינות מדויקים או לוח. של סדר ניהול ויקיפדיה. של המלחמה פיסיקה קישורים עזה. אם טבלאות ממונרכיה כתב, שתפו ישראל ננקטת אם אתה, אם חפש בהשחתה פסיכולוגיה. בדף על ברית ריקוד חבריכם, אחד אל ריקוד להפוך אווירונאוטיקה.`
36 | p := c.NewStyledParagraph()
37 | style := &p.Append(hebrew).Style
38 | style.Font = font
39 |
40 | err = c.Draw(p)
41 | if err != nil {
42 | panic(err)
43 | }
44 |
45 | hebrew = `ב אחד כלליים חופשית, עוד אירועים ותשובות האנציקלופדיה על. אל אתה מושגי הבהרה ויקימדיה. ב עזה חשמל בלשנות, מה החלה.`
46 | p = c.NewStyledParagraph()
47 | style = &p.Append(hebrew).Style
48 | style.Font = font
49 |
50 | err = c.Draw(p)
51 | if err != nil {
52 | panic(err)
53 | }
54 |
55 | if err := c.WriteToFile("hebrew-text.pdf"); err != nil {
56 | panic(err)
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/image/README.md:
--------------------------------------------------------------------------------
1 | # PDF Images
2 |
3 | UniPDF allows you to add, extract, list images in your PDF documents. Having the ability to play around with images allows for the creation of attractive PDF reports.
4 |
5 | ## Examples
6 |
7 | - [pdf_add_image_to_page.go](pdf_add_image_to_page.go) explains how to add an image in a PDF document
8 | - [pdf_images_to_pdf.go](pdf_images_to_pdf.go) explains how to add multiple images in a PDF document, one image per page.
9 | - [pdf_list_images.go](pdf_list_images.go) explains how to list images in a PDF file. Passes through each page, goes through the content stream and finds instances of both. XObject Images and inline images. Also handles images referred within XObject Form content streams.
10 | - Image extraction example can be found in [../extract](extract) example subfolder.
11 |
--------------------------------------------------------------------------------
/image/pdf_images_to_pdf.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Add images to a PDF file, one image per page.
3 | *
4 | * Run as: go run pdf_images_to_pdf.go output.pdf img1.jpg img2.jpg img3.png ...
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/common"
14 | "github.com/unidoc/unipdf/v4/common/license"
15 | "github.com/unidoc/unipdf/v4/creator"
16 | )
17 |
18 | func init() {
19 | // Make sure to load your metered License API key prior to using the library.
20 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
21 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
22 | if err != nil {
23 | panic(err)
24 | }
25 | }
26 |
27 | func main() {
28 | if len(os.Args) < 3 {
29 | fmt.Printf("Usage: go run pdf_images_to_pdf.go output.pdf img1.jpg img2.jpg ...\n")
30 | os.Exit(1)
31 | }
32 |
33 | outputPath := os.Args[1]
34 | inputPaths := os.Args[2:len(os.Args)]
35 |
36 | err := imagesToPdf(inputPaths, outputPath)
37 | if err != nil {
38 | fmt.Printf("Error: %v\n", err)
39 | os.Exit(1)
40 | }
41 |
42 | fmt.Printf("Complete, see output file: %s\n", outputPath)
43 | }
44 |
45 | // Images to PDF.
46 | func imagesToPdf(inputPaths []string, outputPath string) error {
47 | c := creator.New()
48 |
49 | for _, imgPath := range inputPaths {
50 | common.Log.Debug("Image: %s", imgPath)
51 |
52 | img, err := c.NewImageFromFile(imgPath)
53 | if err != nil {
54 | common.Log.Debug("Error loading image: %v", err)
55 | return err
56 | }
57 | // Use page width of 612 points, and calculate the height proportionally based on the image.
58 | // Standard PPI is 72 points per inch, thus a width of 8.5"
59 | pageWidth := 612.0
60 | img.ScaleToWidth(pageWidth)
61 |
62 | pageHeight := pageWidth * img.Height() / img.Width()
63 | c.SetPageSize(creator.PageSize{pageWidth, pageHeight})
64 | c.NewPage()
65 | img.SetPos(0, 0)
66 | _ = c.Draw(img)
67 | }
68 |
69 | err := c.WriteToFile(outputPath)
70 | return err
71 | }
72 |
--------------------------------------------------------------------------------
/invoice/README.md:
--------------------------------------------------------------------------------
1 | # PDF Invoices
2 |
3 | Using UniPDF, you can create beautifully formatted automated invoices using code written in GoLang. This example contains two types of invoices, a simple one and an advanced invoice that has better formatting.
4 |
5 | ## Examples
6 |
7 | - [pdf_invoice_simple.go](pdf_invoice_simple.go) explains how to create a simple invoice
8 | - [pdf_invoice_advanced.go](pdf_invoice_advanced.go) explains how to create a better invoice that has customized formatting and coloring and a lot of other customized content.
9 |
--------------------------------------------------------------------------------
/invoice/invoice_advanced.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/invoice/invoice_advanced.pdf
--------------------------------------------------------------------------------
/invoice/invoice_simple.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/invoice/invoice_simple.pdf
--------------------------------------------------------------------------------
/invoice/unidoc-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/invoice/unidoc-logo.png
--------------------------------------------------------------------------------
/jbig2/checkerboard-squares-black-white.jb2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/jbig2/checkerboard-squares-black-white.jb2
--------------------------------------------------------------------------------
/jbig2/checkerboard-squares-black-white.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/jbig2/checkerboard-squares-black-white.jpg
--------------------------------------------------------------------------------
/jbig2/document.jb2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/jbig2/document.jb2
--------------------------------------------------------------------------------
/jbig2/jbig2_decompress.go:
--------------------------------------------------------------------------------
1 | /*
2 | * This example showcases the decompression of the jbig2 encoded document and storing into
3 | * commonly used jpg format.
4 | *
5 | * Syntax: go run jbig2_decompress.go img.jb2
6 | */
7 |
8 | package main
9 |
10 | import (
11 | "fmt"
12 | "image"
13 | "image/jpeg"
14 | "io/ioutil"
15 | "log"
16 | "os"
17 |
18 | "github.com/unidoc/unipdf/v4/common/license"
19 | "github.com/unidoc/unipdf/v4/core"
20 | )
21 |
22 | func init() {
23 | // Make sure to load your metered License API key prior to using the library.
24 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
25 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
26 | if err != nil {
27 | panic(err)
28 | }
29 | }
30 |
31 | func main() {
32 | if len(os.Args) < 2 {
33 | fmt.Printf("Usage: go run jbig2_decompress.go img.jb2 ...\n")
34 | os.Exit(1)
35 | }
36 | inputImage := os.Args[1]
37 |
38 | f, err := os.Open(inputImage)
39 | if err != nil {
40 | log.Fatalf("Error: %v\n", err)
41 | }
42 | defer f.Close()
43 |
44 | data, err := ioutil.ReadAll(f)
45 | if err != nil {
46 | log.Fatalf("Error: %v\n", err)
47 | }
48 |
49 | // Create new JBIG2 Encoder/Decoder context.
50 | enc := &core.JBIG2Encoder{}
51 |
52 | // Decode all images from the 'data'.
53 | images, err := enc.DecodeImages(data)
54 | if err != nil {
55 | log.Fatalf("Error: %v\n", err)
56 | }
57 |
58 | // Store all images in the jpg format.
59 | saveImage := func(i int, img image.Image) {
60 | output := fmt.Sprintf("jbig2_decoded_%d.jpg", i+1)
61 | imgFile, err := os.Create(output)
62 | if err != nil {
63 | log.Fatalf("Error: %v\n", err)
64 | }
65 | defer imgFile.Close()
66 |
67 | err = jpeg.Encode(imgFile, img, &jpeg.Options{Quality: 80})
68 | if err != nil {
69 | log.Fatalf("Error: %v\n", err)
70 | }
71 | fmt.Printf("Decompressed and stored the output to: '%s' with success.\n", output)
72 | }
73 |
74 | for i, img := range images {
75 | saveImage(i, img)
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/jbig2/jbig2_globals.jb2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/jbig2/jbig2_globals.jb2
--------------------------------------------------------------------------------
/license/README.md:
--------------------------------------------------------------------------------
1 | # UniPDF License Loading.
2 |
3 | The examples here illustrate how to work with UniPDF license codes and keys.
4 | There are two types of licenses.
5 |
6 | ## Offline License
7 | Offline licenses are cryptography based and contain full signed information that is verified based on signatures without making any outbound connections,
8 | hence the name "offline". This kind of license is suitable for users deploying OEM products to their customers or where there are strict restrictions
9 | on outbound connections due to firewalls and/or compliance requirements.
10 |
11 | ## Metered License (API keys)
12 | The metered license is the most convenient way to get started with UniDoc products and the Free tier enables a powerful way to get started for free.
13 | Anyone can get a free metered API key by signing up on http://cloud.unidoc.io/
14 |
15 | > Metered License (API keys) requires read-write permission to $HOME directory for storing API Keys usage,
16 | > however you can set `HOME` environment to another directory if you wish.
17 |
18 | ## Metered License API Key Usage Logs
19 | By setting the `SetMeteredKeyUsageLogVerboseMode` to true using `license.SetMeteredKeyUsageLogVerboseMode(true)` you can see full information on the credit usage status of each logs of each document as follows.
20 | 
21 |
22 | ## Examples
23 |
24 | - [unipdf_license_loading_metered.go](unipdf_license_loading_metered.go) Demonstrates how to load the Metered API license key and how to print out relevant information.
25 | - [unipdf_offline_license_info.go](unipdf_offline_license_info.go) Demonstrates how to print out information about the license after loading an offline license key.
26 | - [unipdf_license_usage_log.go](unipdf_license_usage_log.go) Demonstrates how to enable the license key verbose mode logging.
--------------------------------------------------------------------------------
/license/unipdf_license_loading_metered.go:
--------------------------------------------------------------------------------
1 | /*
2 | * unipdf_license_loading_metered.go:
3 | * Illustrates how to load a metered license API key.
4 | * Free api keys can be obtained at: https://cloud.unidoc.io
5 | *
6 | * Run as: go run unipdf_license_loading_metered.go
7 | */
8 |
9 | package main
10 |
11 | import (
12 | "fmt"
13 |
14 | "github.com/unidoc/unipdf/v4/common/license"
15 | )
16 |
17 | func init() {
18 | // To get your free API key for metered license, sign up on: https://cloud.unidoc.io
19 | // Make sure to be using UniPDF v3.19.1 or newer for Metered API key support.
20 | err := license.SetMeteredKey(`my metered api key goes here`)
21 | if err != nil {
22 | fmt.Printf("ERROR: Failed to set metered key: %v\n", err)
23 | fmt.Printf("Make sure to get a valid key from https://cloud.unidoc.io\n")
24 | panic(err)
25 | }
26 | }
27 |
28 | func main() {
29 | lk := license.GetLicenseKey()
30 | if lk == nil {
31 | fmt.Printf("Failed retrieving license key")
32 | return
33 | }
34 | fmt.Printf("License: %s\n", lk.ToString())
35 |
36 | // GetMeteredState freshly checks the state, contacting the licensing server.
37 | state, err := license.GetMeteredState()
38 | if err != nil {
39 | fmt.Printf("ERROR getting metered state: %+v\n", err)
40 | panic(err)
41 | }
42 | fmt.Printf("State: %+v\n", state)
43 | if state.OK {
44 | fmt.Printf("State is OK\n")
45 | } else {
46 | fmt.Printf("State is not OK\n")
47 | }
48 | fmt.Printf("Credits: %v\n", state.Credits)
49 | fmt.Printf("Used credits: %v\n", state.Used)
50 | }
51 |
--------------------------------------------------------------------------------
/license/unipdf_license_loading_offline.go:
--------------------------------------------------------------------------------
1 | /*
2 | * unipdf_license_loading_offline.go:
3 | * Illustrates how to load an offline license key.
4 | * Offline keys can be purchased at https://www.unidoc.io
5 | *
6 | * Run as: go run unipdf_license_loading_offline.go
7 | */
8 |
9 | package main
10 |
11 | import (
12 | "fmt"
13 |
14 | "github.com/unidoc/unipdf/v4/common/license"
15 | )
16 |
17 | // Example of an offline license key.
18 | const offlineLicenseKey = `
19 | -----BEGIN UNIDOC LICENSE KEY-----
20 | contents here.
21 | -----END UNIDOC LICENSE KEY-----
22 | `
23 |
24 | func init() {
25 | // The customer name needs to match the entry that is embedded in the signed key.
26 | customerName := `My Company`
27 |
28 | // Good to load the license key in `init`. Needs to be done prior to using the library, otherwise operations
29 | // will result in an error.
30 | err := license.SetLicenseKey(offlineLicenseKey, customerName)
31 | if err != nil {
32 | panic(err)
33 | }
34 | }
35 |
36 | func main() {
37 | lk := license.GetLicenseKey()
38 | if lk == nil {
39 | fmt.Printf("Failed retrieving license key")
40 | return
41 | }
42 | fmt.Printf("License: %s\n", lk.ToString())
43 | }
44 |
--------------------------------------------------------------------------------
/license/unipdf_offline_license_info.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Check UniPDF License key info for an offline license key.
3 | *
4 | * Run as: go run unipdf_offline_license_info.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 |
12 | "github.com/unidoc/unipdf/v4/common/license"
13 | )
14 |
15 | const offlineLicenseKey = `
16 | -----BEGIN UNIDOC LICENSE KEY-----
17 | Key contents here.
18 | -----END UNIDOC LICENSE KEY-----
19 | `
20 |
21 | func init() {
22 | // Load the offline license key.
23 | err := license.SetLicenseKey(offlineLicenseKey, `Company Name`)
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | lk := license.GetLicenseKey()
31 | if lk == nil {
32 | fmt.Printf("Failed retrieving license key")
33 |
34 | return
35 | }
36 |
37 | fmt.Printf("%s\n", lk.ToString())
38 | }
39 |
--------------------------------------------------------------------------------
/metadata/README.md:
--------------------------------------------------------------------------------
1 | # Metadata
2 |
3 | ## Examples
4 |
5 | - pdf_metadata_get_docinfo.go outputs the document information dictionary information
6 | - pdf_metadata_get_xml.go outputs metadata streams XML
7 | - pdf_metadata_set_docinfo.go showcase how to set a default and custom metadata information
8 |
9 | ## Background
10 | According to section 14.3 Metadata (p. 556 in PDF32000_2008) metadata can be stores in two ways:
11 | 1. In metadata streams associated with the document or a component of the document (newer, preferred approach)
12 | 2. In a document information dictionary associated with the document (old way)
13 |
14 | The document information dictionary has fixed field such as:
15 | - Title
16 | The document’s title.
17 |
18 | - Author
19 | The name of the person who created the document.
20 |
21 | - Subject
22 | The subject of the document.
23 |
24 | - Keywords
25 | Keywords associated with the document.
26 |
27 | - Creator
28 | If the document was converted to PDF from another format, the name of the conforming product that created the original document from which it was converted.
29 |
30 | - Producer
31 | If the document was converted to PDF from another format, the name of the conforming product that converted it to PDF.
32 |
33 | - CreationDate
34 | The date and time the document was created, in human- readable form.
35 |
36 | - ModDate
37 | The date and time the document was most recently modified, in human-readable form.
38 |
39 | - Trapped
40 | A name object indicating whether the document has been modified to include trapping information.
41 |
42 |
43 | Aside from the default fields mentioned above, the metadata dictionary could contain other keys that hold custom string metadata.
44 |
--------------------------------------------------------------------------------
/multi-font-encoder/fonts/Batang.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/multi-font-encoder/fonts/Batang.ttf
--------------------------------------------------------------------------------
/multi-font-encoder/fonts/NotoSerifEthiopic_Condensed-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/multi-font-encoder/fonts/NotoSerifEthiopic_Condensed-Black.ttf
--------------------------------------------------------------------------------
/multi-font-encoder/fonts/OpenSans-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/multi-font-encoder/fonts/OpenSans-Regular.ttf
--------------------------------------------------------------------------------
/multi-font-encoder/fonts/PCSB Hebrew Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/multi-font-encoder/fonts/PCSB Hebrew Regular.ttf
--------------------------------------------------------------------------------
/multi-font-encoder/multiple-language-text-using-multi-font.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/multi-font-encoder/multiple-language-text-using-multi-font.pdf
--------------------------------------------------------------------------------
/multi-font-encoder/use_composite_TTFPdfFonts.go:
--------------------------------------------------------------------------------
1 | /*
2 | * renders a multi language text using a multi font encoder.
3 | *
4 | * Run as: go run render_multi_language_text.go
5 | */
6 | package main
7 |
8 | import (
9 | "os"
10 |
11 | "github.com/unidoc/unipdf/v4/common/license"
12 | "github.com/unidoc/unipdf/v4/creator"
13 | "github.com/unidoc/unipdf/v4/model"
14 | )
15 |
16 | func init() {
17 | // Make sure to load your metered License API key prior to using the library.
18 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
19 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
20 | if err != nil {
21 | panic(err)
22 | }
23 | }
24 |
25 | func main() {
26 | inputText := "Sample text 示例文本 טקסט לדוגמה ጽሑፍ ኣብነት 샘플 텍스트"
27 | fonts := getFonts([]string{
28 | "./fonts/PCSB Hebrew Regular.ttf",
29 | "./fonts/NotoSerifEthiopic_Condensed-Black.ttf",
30 | "./fonts/OpenSans-Regular.ttf",
31 | "./fonts/Batang.ttf",
32 | })
33 |
34 | c := creator.New()
35 | c.SetPageSize(creator.PageSizeA5)
36 | p := c.NewStyledParagraph()
37 | style := &p.Append(inputText).Style
38 | style.MultiFont = model.NewMultipleFontEncoder(fonts)
39 |
40 | err := c.Draw(p)
41 | if err != nil {
42 | panic(err)
43 | }
44 | if err := c.WriteToFile("multiple-language-text-multi-font.pdf"); err != nil {
45 | panic(err)
46 | }
47 | }
48 |
49 | // getFonts returns list of *model.PdfFont from list of paths to fonts files.
50 | func getFonts(fontPaths []string) []*model.PdfFont {
51 | fonts := []*model.PdfFont{}
52 | for _, path := range fontPaths {
53 | font, err := model.NewCompositePdfFontFromTTFFile(path)
54 | if err != nil {
55 | panic(err)
56 | }
57 | fonts = append(fonts, font)
58 | }
59 |
60 | return fonts
61 | }
62 |
--------------------------------------------------------------------------------
/outlines/README.md:
--------------------------------------------------------------------------------
1 | # PDF Outlines
2 |
3 | The example explains how to work with outlines (bookmarks) using UniPDF.
4 |
5 | ## Examples
6 |
7 | - [pdf_get_outlines.go](pdf_get_outlines.go) explains how to retrieve outlines (bookmarks) from a PDF file and prints them out in JSON format. Note: The JSON output can be used with the related pdf_set_outlines.go example to apply outlines to a PDF file.
8 | - [pdf_set_outlines.go](pdf_set_outlines.go) explains how to apply outlines to a PDF file. The files are read from a JSON formatted file, which can be created via pdf_get_outlines which outputs outlines for an input PDF file in the JSON format.
--------------------------------------------------------------------------------
/outlines/pdf_create_outlines.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Creates outlines for a PDF file.
3 | *
4 | * Run as: go run pdf_create_outlines.go input.pdf output.pdf
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "os"
12 |
13 | "github.com/unidoc/unipdf/v4/common/license"
14 | "github.com/unidoc/unipdf/v4/model"
15 | )
16 |
17 | func init() {
18 | // Make sure to load your metered License API key prior to using the library.
19 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
20 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
21 | if err != nil {
22 | panic(err)
23 | }
24 | }
25 |
26 | func main() {
27 | if len(os.Args) < 3 {
28 | fmt.Printf("Usage: go run pdf_create_outlines.go input.pdf output.pdf\n")
29 | os.Exit(1)
30 | }
31 |
32 | inputPath := os.Args[1]
33 | outPath := os.Args[2]
34 |
35 | fmt.Printf("Input file: %s\n", inputPath)
36 | fmt.Printf("Output file: %s\n", outPath)
37 |
38 | pdfReader, f, err := model.NewPdfReaderFromFile(inputPath, nil)
39 | if err != nil {
40 | fmt.Printf("Error: %v\n", err)
41 | os.Exit(1)
42 | }
43 | defer f.Close()
44 |
45 | // Check number of PDF pages.
46 | numPages, err := pdfReader.GetNumPages()
47 | if err != nil {
48 | fmt.Printf("Error: %v\n", err)
49 | os.Exit(1)
50 | }
51 |
52 | if numPages < 3 {
53 | fmt.Printf("Too short PDF file. At least 3 pages are needed for this outline example.")
54 | os.Exit(1)
55 | }
56 |
57 | // Don't copy document outlines.
58 | opt := &model.ReaderToWriterOpts{
59 | SkipOutlines: true,
60 | }
61 |
62 | // Generate a PdfWriter instance from existing PdfReader.
63 | pdfWriter, err := pdfReader.ToWriter(opt)
64 | if err != nil {
65 | fmt.Printf("Error: %v\n", err)
66 | os.Exit(1)
67 | }
68 |
69 | // Add the new document outlines.
70 | outline := model.NewOutline()
71 | for i := 0; i < 3; i++ {
72 | page, _ := pdfReader.GetPage(i + 1)
73 | _, y, _ := page.Size()
74 | // Create outline for the top left corner of each page. Note that PDF y coordinate goes from bottom to top.
75 | outline.Add(model.NewOutlineItem(fmt.Sprintf("page%d", i+1), model.NewOutlineDest(int64(i), 0, y)))
76 | }
77 |
78 | pdfWriter.AddOutlineTree(outline.ToOutlineTree())
79 |
80 | // Write output file.
81 | err = pdfWriter.WriteToFile(outPath)
82 | if err != nil {
83 | fmt.Printf("Error: %v\n", err)
84 | os.Exit(1)
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/outlines/pdf_get_outlines.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Retrieves outlines (bookmarks) from a PDF file and prints out in JSON format.
3 | * Note: The JSON output can be used with the related pdf_set_outlines.go example to
4 | * apply outlines to a PDF file.
5 | *
6 | * Run as: go run pdf_get_outlines.go input.pdf > outlines.json
7 | */
8 |
9 | package main
10 |
11 | import (
12 | "encoding/json"
13 | "fmt"
14 | "os"
15 |
16 | "github.com/unidoc/unipdf/v4/common/license"
17 | "github.com/unidoc/unipdf/v4/model"
18 | )
19 |
20 | func init() {
21 | // Make sure to load your metered License API key prior to using the library.
22 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
23 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | if len(os.Args) < 2 {
31 | fmt.Printf("Usage: go run pdf_get_outlines.go input.pdf\n")
32 | os.Exit(1)
33 | }
34 |
35 | inputPath := os.Args[1]
36 |
37 | fmt.Printf("Input file: %s\n", inputPath)
38 |
39 | err := getOutlines(inputPath)
40 | if err != nil {
41 | fmt.Printf("Error: %v\n", err)
42 | os.Exit(1)
43 | }
44 | }
45 |
46 | func getOutlines(inputPath string) error {
47 | pdfReader, f, err := model.NewPdfReaderFromFile(inputPath, nil)
48 | if err != nil {
49 | return err
50 | }
51 | defer f.Close()
52 |
53 | outlines, err := pdfReader.GetOutlines()
54 | if err != nil {
55 | return err
56 | }
57 |
58 | data, err := json.MarshalIndent(outlines, "", " ")
59 | if err != nil {
60 | return err
61 | }
62 | fmt.Printf("%s\n", data)
63 |
64 | return nil
65 | }
66 |
--------------------------------------------------------------------------------
/outlines/pdf_set_outlines.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Applies outlines to a PDF file. The files are read from a JSON formatted file,
3 | * which can be created via pdf_get_outlines which outputs outlines for an input PDF file
4 | * in the JSON format.
5 | *
6 | * Run as: go run pdf_set_outlines.go input.pdf outlines.json output.pdf
7 | */
8 |
9 | package main
10 |
11 | import (
12 | "encoding/json"
13 | "fmt"
14 | "io/ioutil"
15 | "os"
16 |
17 | "github.com/unidoc/unipdf/v4/common/license"
18 | "github.com/unidoc/unipdf/v4/model"
19 | )
20 |
21 | func init() {
22 | // Make sure to load your metered License API key prior to using the library.
23 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
24 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
25 | if err != nil {
26 | panic(err)
27 | }
28 | }
29 |
30 | func main() {
31 | if len(os.Args) < 4 {
32 | fmt.Printf("Usage: go run pdf_set_outlines.go input.pdf outlines.json output.pdf\n")
33 | os.Exit(1)
34 | }
35 |
36 | inputPath := os.Args[1]
37 | outlinesPath := os.Args[2]
38 | outPath := os.Args[3]
39 |
40 | fmt.Printf("Input file: %s\n", inputPath)
41 | fmt.Printf("Outlines file (JSON): %s\n", outlinesPath)
42 | fmt.Printf("Output file: %s\n", outPath)
43 |
44 | err := applyOutlines(inputPath, outlinesPath, outPath)
45 | if err != nil {
46 | fmt.Printf("Error: %v\n", err)
47 | os.Exit(1)
48 | }
49 | }
50 |
51 | func applyOutlines(inputPath, outlinesPath, outPath string) error {
52 | data, err := ioutil.ReadFile(outlinesPath)
53 | if err != nil {
54 | return err
55 | }
56 |
57 | var newOutlines model.Outline
58 | err = json.Unmarshal(data, &newOutlines)
59 | if err != nil {
60 | return err
61 | }
62 |
63 | pdfReader, f, err := model.NewPdfReaderFromFile(inputPath, nil)
64 | if err != nil {
65 | return err
66 | }
67 | defer f.Close()
68 |
69 | // Don't copy document outlines.
70 | opt := &model.ReaderToWriterOpts{
71 | SkipOutlines: true,
72 | }
73 |
74 | // Generate a PdfWriter instance from existing PdfReader.
75 | pdfWriter, err := pdfReader.ToWriter(opt)
76 | if err != nil {
77 | return err
78 | }
79 |
80 | // Add the new document outline.
81 | pdfWriter.AddOutlineTree(newOutlines.ToOutlineTree())
82 |
83 | return pdfWriter.WriteToFile(outPath)
84 | }
85 |
--------------------------------------------------------------------------------
/pages/README.md:
--------------------------------------------------------------------------------
1 | # PDF Page Manipulation
2 |
3 | The example explains how to work with and manipulate PDF pages using UniPDF library. You can perform a number of manipulations such as crop, merge, rotate and many more.
4 |
5 | ## Examples
6 |
7 | - [pdf_4up.go](pdf_4up.go) The example outputs multiple pages (4) per page to an output PDF from an input PDF. Showcases page templating by loading pages as Blocks and manipulating with the creator package.
8 | - [pdf_crop.go](pdf_crop.go) The example Crop pages in a PDF file. Crops the view to a certain percentage of the original. The percentage specifies the trim-off percentage, both widthwise and heightwise.
9 | - [pdf_merge.go](pdf_merge.go) The example highlights basic merging of PDF files. Simply loads all pages for each file and writes to the output file.
10 | - [pdf_merge_advanced.go](pdf_merge_advanced.go) The example merges PDF files, including form field data (AcroForms). For a more basic merging of PDF page contents, see pdf_merge.go.
11 | - [pdf_page_info.go](pdf_page_info.go) The example prints PDF page info: Mediabox size and other parameters. If [page num] is not specified prints out info for all pages.
12 | - [pdf_page_rotate.go](pdf_page_rotate.go) The example rotate certain page in a PDF file. Degrees needs to be a multiple of 90.
13 | - [pdf_page_side_note.go](pdf_page_side_note.go) The example showcases how to add information on page's margin left or right.
14 | - [pdf_rotate_flatten.go](pdf_rotate_flatten.go) The example rotates the contents of a PDF file in accordance with each page's Rotate entry and then sets Rotate to 0. That is, flattens the rotation. Will look the same in viewer, but when working with the PDF, the upper left corner will be the origin (in unidoc coordinate system).
15 | - [pdf_rotate.go](pdf_rotate.go) The example rotate pages in a PDF file using global flag instead of rotating each page one by one. Degrees needs to be a multiple of 90.
16 | - [pdf_split.go](pdf_split.go) The example highlights basic PDF split example: Splitting by page range.
17 | - [pdf_split_advanced.go](pdf_split_advanced.go) The example highlights advanced PDF split example: Takes into account optional content - OCProperties (rarely used).
18 | - [pdf_append_contents.go](pdf_append_contents.go) The example for append PDF Files contents into single PDF file.
19 |
--------------------------------------------------------------------------------
/pages/pdf_rotate.go:
--------------------------------------------------------------------------------
1 | /*
2 | * Rotate pages in a PDF file using global flag instead of
3 | * rotating each page one by one.
4 | * Degrees needs to be a multiple of 90.
5 | *
6 | * Run as: go run pdf_rotate.go input.pdf output.pdf
7 | * The angle is specified in degrees.
8 | */
9 |
10 | package main
11 |
12 | import (
13 | "fmt"
14 | "os"
15 | "strconv"
16 |
17 | "github.com/unidoc/unipdf/v4/common/license"
18 | "github.com/unidoc/unipdf/v4/model"
19 | )
20 |
21 | func init() {
22 | // Make sure to load your metered License API key prior to using the library.
23 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
24 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
25 | if err != nil {
26 | panic(err)
27 | }
28 | }
29 |
30 | func main() {
31 | if len(os.Args) < 4 {
32 | fmt.Printf("Usage: go run pdf_rotate.go input.pdf output.pdf\n")
33 | os.Exit(1)
34 | }
35 |
36 | inputPath := os.Args[1]
37 | outputPath := os.Args[3]
38 |
39 | degrees, err := strconv.ParseInt(os.Args[2], 10, 64)
40 | if err != nil {
41 | fmt.Printf("Invalid degrees: %v\n", err)
42 | os.Exit(1)
43 | }
44 | if degrees%90 != 0 {
45 | fmt.Printf("Degrees needs to be a multiple of 90\n")
46 | os.Exit(1)
47 | }
48 |
49 | err = rotatePdf(inputPath, degrees, outputPath)
50 | if err != nil {
51 | fmt.Printf("Error: %v\n", err)
52 | os.Exit(1)
53 | }
54 |
55 | fmt.Printf("Complete, see output file: %s\n", outputPath)
56 | }
57 |
58 | // Rotate all pages by degrees.
59 | func rotatePdf(inputPath string, degrees int64, outputPath string) error {
60 | pdfReader, f, err := model.NewPdfReaderFromFile(inputPath, nil)
61 | if err != nil {
62 | return err
63 | }
64 | defer f.Close()
65 |
66 | pdfWriter, err := pdfReader.ToWriter(&model.ReaderToWriterOpts{})
67 | if err != nil {
68 | return nil
69 | }
70 |
71 | // Rotate all page degrees.
72 | err = pdfWriter.SetRotation(degrees)
73 | if err != nil {
74 | return nil
75 | }
76 |
77 | pdfWriter.WriteToFile(outputPath)
78 |
79 | return err
80 | }
81 |
--------------------------------------------------------------------------------
/pdfa/pdf_apply_standard.go:
--------------------------------------------------------------------------------
1 | /*
2 | * PDF optimization (compression) example.
3 | *
4 | * Run as: go run pdf_apply_standard.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "log"
12 | "os"
13 | "time"
14 |
15 | "github.com/unidoc/unipdf/v4/common/license"
16 | "github.com/unidoc/unipdf/v4/model"
17 | "github.com/unidoc/unipdf/v4/model/pdfa"
18 | )
19 |
20 | func init() {
21 | // Make sure to load your metered License API key prior to using the library.
22 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
23 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | args := os.Args
31 | if len(args) < 3 {
32 | fmt.Printf("Usage: %s INPUT_PDF_PATH OUTPUT_PDF_PATH", os.Args[0])
33 | return
34 | }
35 | inputPath := args[1]
36 | outputPath := args[2]
37 |
38 | // Initialize starting time.
39 | start := time.Now()
40 |
41 | // Create reader.
42 | reader, file, err := model.NewPdfReaderFromFile(inputPath, nil)
43 | if err != nil {
44 | log.Fatalf("Fail: %v\n", err)
45 | }
46 | defer file.Close()
47 |
48 | // Generate a PDFWriter from PDFReader.
49 | pdfWriter, err := reader.ToWriter(nil)
50 | if err != nil {
51 | log.Fatalf("Fail: %v\n", err)
52 | }
53 |
54 | // Apply standard PDF/A-1B.
55 | pdfWriter.ApplyStandard(pdfa.NewProfile1B(nil))
56 |
57 | // Create output file.
58 | err = pdfWriter.WriteToFile(outputPath)
59 | if err != nil {
60 | log.Fatalf("Fail: %v\n", err)
61 | }
62 |
63 | duration := float64(time.Since(start)) / float64(time.Millisecond)
64 | fmt.Printf("Processing time: %.2f ms\n", duration)
65 | }
66 |
--------------------------------------------------------------------------------
/pdfa/pdf_validate_standard.go:
--------------------------------------------------------------------------------
1 | /*
2 | * PDF optimization (compression) example.
3 | *
4 | * Run as: go run pdfa_validate_standard.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "log"
12 | "os"
13 | "time"
14 |
15 | "github.com/unidoc/unipdf/v4/common/license"
16 | "github.com/unidoc/unipdf/v4/model"
17 | "github.com/unidoc/unipdf/v4/model/pdfa"
18 | )
19 |
20 | func init() {
21 | // Make sure to load your metered License API key prior to using the library.
22 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
23 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | args := os.Args
31 | if len(args) < 2 {
32 | fmt.Printf("Usage: %s INPUT_PDF_PATH", os.Args[0])
33 | return
34 | }
35 | inputPath := args[1]
36 |
37 | // Initialize starting time.
38 | start := time.Now()
39 |
40 | // Create reader.
41 | inputFile, err := os.Open(inputPath)
42 | if err != nil {
43 | log.Fatalf("Fail: %v\n", err)
44 | }
45 | defer inputFile.Close()
46 |
47 | detailedReader, err := model.NewCompliancePdfReader(inputFile)
48 | if err != nil {
49 | log.Fatalf("Fail: %v\n", err)
50 | }
51 |
52 | // Apply standard PDF/A-1B.
53 | standards := []model.StandardImplementer{
54 | pdfa.NewProfile1A(nil),
55 | pdfa.NewProfile1B(nil),
56 | }
57 |
58 | // Iterate over input standards and check if the document passes its requirements.
59 | for _, standard := range standards {
60 | if err = standard.ValidateStandard(detailedReader); err != nil {
61 | fmt.Printf("Input document didn't pass the standard: %s - %v\n", standard.StandardName(), err)
62 | }
63 | }
64 |
65 | duration := float64(time.Since(start)) / float64(time.Millisecond)
66 | fmt.Printf("Processing time: %.2f ms\n", duration)
67 | }
68 |
--------------------------------------------------------------------------------
/pdfa/pdfa2_apply_standard.go:
--------------------------------------------------------------------------------
1 | /*
2 | * PDF/A-2 optimization (compression) example.
3 | *
4 | * Run as: go run pdfa2_apply_standard.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "log"
12 | "os"
13 | "time"
14 |
15 | "github.com/unidoc/unipdf/v4/common/license"
16 | "github.com/unidoc/unipdf/v4/model"
17 | "github.com/unidoc/unipdf/v4/model/pdfa"
18 | )
19 |
20 | func init() {
21 | // Make sure to load your metered License API key prior to using the library.
22 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
23 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | args := os.Args
31 | if len(args) < 3 {
32 | fmt.Printf("Usage: %s INPUT_PDF_PATH OUTPUT_PDF_PATH", os.Args[0])
33 | return
34 | }
35 | inputPath := args[1]
36 | outputPath := args[2]
37 |
38 | // Initialize starting time.
39 | start := time.Now()
40 |
41 | // Create reader.
42 | reader, file, err := model.NewPdfReaderFromFile(inputPath, nil)
43 | if err != nil {
44 | log.Fatalf("Fail: %v\n", err)
45 | }
46 | defer file.Close()
47 |
48 | // Generate a PDFWriter from PDFReader.
49 | pdfWriter, err := reader.ToWriter(nil)
50 | if err != nil {
51 | log.Fatalf("Fail: %v\n", err)
52 | }
53 |
54 | // Apply standard PDF/A-2B.
55 | pdfWriter.ApplyStandard(pdfa.NewProfile2B(nil))
56 |
57 | // Create output file.
58 | err = pdfWriter.WriteToFile(outputPath)
59 | if err != nil {
60 | log.Fatalf("Fail: %v\n", err)
61 | }
62 |
63 | duration := float64(time.Since(start)) / float64(time.Millisecond)
64 | fmt.Printf("Processing time: %.2f ms\n", duration)
65 | }
66 |
--------------------------------------------------------------------------------
/pdfa/pdfa2_validate_standard.go:
--------------------------------------------------------------------------------
1 | /*
2 | * PDF/A-2 optimization (compression) example.
3 | *
4 | * Run as: go run pdfa2_validate_standard.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "log"
12 | "os"
13 | "time"
14 |
15 | "github.com/unidoc/unipdf/v4/common/license"
16 | "github.com/unidoc/unipdf/v4/model"
17 | "github.com/unidoc/unipdf/v4/model/pdfa"
18 | )
19 |
20 | func init() {
21 | // Make sure to load your metered License API key prior to using the library.
22 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
23 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | args := os.Args
31 | if len(args) < 2 {
32 | fmt.Printf("Usage: %s INPUT_PDF_PATH", os.Args[0])
33 | return
34 | }
35 | inputPath := args[1]
36 |
37 | // Initialize starting time.
38 | start := time.Now()
39 |
40 | // Create reader.
41 | inputFile, err := os.Open(inputPath)
42 | if err != nil {
43 | log.Fatalf("Fail: %v\n", err)
44 | }
45 | defer inputFile.Close()
46 |
47 | detailedReader, err := model.NewCompliancePdfReader(inputFile)
48 | if err != nil {
49 | log.Fatalf("Fail: %v\n", err)
50 | }
51 |
52 | // Apply standard PDF/A-2.
53 | standards := []model.StandardImplementer{
54 | pdfa.NewProfile2A(nil),
55 | pdfa.NewProfile2B(nil),
56 | pdfa.NewProfile2U(nil),
57 | }
58 |
59 | // Iterate over input standards and check if the document passes its requirements.
60 | for _, standard := range standards {
61 | if err = standard.ValidateStandard(detailedReader); err != nil {
62 | fmt.Printf("Input document didn't pass the standard: %s - %v\n", standard.StandardName(), err)
63 | }
64 | }
65 |
66 | duration := float64(time.Since(start)) / float64(time.Millisecond)
67 | fmt.Printf("Processing time: %.2f ms\n", duration)
68 | }
69 |
--------------------------------------------------------------------------------
/pdfa/pdfa3_apply_standard.go:
--------------------------------------------------------------------------------
1 | /*
2 | * PDF/A-3 optimization (compression) example.
3 | *
4 | * Run as: go run pdfa3_apply_standard.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "log"
12 | "os"
13 | "time"
14 |
15 | "github.com/unidoc/unipdf/v4/common/license"
16 | "github.com/unidoc/unipdf/v4/model"
17 | "github.com/unidoc/unipdf/v4/model/pdfa"
18 | )
19 |
20 | func init() {
21 | // Make sure to load your metered License API key prior to using the library.
22 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
23 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | args := os.Args
31 | if len(args) < 3 {
32 | fmt.Printf("Usage: %s INPUT_PDF_PATH OUTPUT_PDF_PATH", os.Args[0])
33 | return
34 | }
35 | inputPath := args[1]
36 | outputPath := args[2]
37 |
38 | // Initialize starting time.
39 | start := time.Now()
40 |
41 | // Create reader.
42 | reader, file, err := model.NewPdfReaderFromFile(inputPath, nil)
43 | if err != nil {
44 | log.Fatalf("Fail: %v\n", err)
45 | }
46 | defer file.Close()
47 |
48 | // Generate a PDFWriter from PDFReader.
49 | pdfWriter, err := reader.ToWriter(nil)
50 | if err != nil {
51 | log.Fatalf("Fail: %v\n", err)
52 | }
53 |
54 | // Apply standard PDF/A-3B.
55 | pdfWriter.ApplyStandard(pdfa.NewProfile3B(nil))
56 |
57 | // Create output file.
58 | err = pdfWriter.WriteToFile(outputPath)
59 | if err != nil {
60 | log.Fatalf("Fail: %v\n", err)
61 | }
62 |
63 | duration := float64(time.Since(start)) / float64(time.Millisecond)
64 | fmt.Printf("Processing time: %.2f ms\n", duration)
65 | }
66 |
--------------------------------------------------------------------------------
/pdfa/pdfa3_validate_standard.go:
--------------------------------------------------------------------------------
1 | /*
2 | * PDF/A-3 optimization (compression) example.
3 | *
4 | * Run as: go run pdfa3_validate_standard.go
5 | */
6 |
7 | package main
8 |
9 | import (
10 | "fmt"
11 | "log"
12 | "os"
13 | "time"
14 |
15 | "github.com/unidoc/unipdf/v4/common/license"
16 | "github.com/unidoc/unipdf/v4/model"
17 | "github.com/unidoc/unipdf/v4/model/pdfa"
18 | )
19 |
20 | func init() {
21 | // Make sure to load your metered License API key prior to using the library.
22 | // If you need a key, you can sign up and create a free one at https://cloud.unidoc.io
23 | err := license.SetMeteredKey(os.Getenv(`UNIDOC_LICENSE_API_KEY`))
24 | if err != nil {
25 | panic(err)
26 | }
27 | }
28 |
29 | func main() {
30 | args := os.Args
31 | if len(args) < 2 {
32 | fmt.Printf("Usage: %s INPUT_PDF_PATH", os.Args[0])
33 | return
34 | }
35 | inputPath := args[1]
36 |
37 | // Initialize starting time.
38 | start := time.Now()
39 |
40 | // Create reader.
41 | inputFile, err := os.Open(inputPath)
42 | if err != nil {
43 | log.Fatalf("Fail: %v\n", err)
44 | }
45 | defer inputFile.Close()
46 |
47 | detailedReader, err := model.NewCompliancePdfReader(inputFile)
48 | if err != nil {
49 | log.Fatalf("Fail: %v\n", err)
50 | }
51 |
52 | // Apply standard PDF/A-3.
53 | standards := []model.StandardImplementer{
54 | pdfa.NewProfile3A(nil),
55 | pdfa.NewProfile3B(nil),
56 | pdfa.NewProfile3U(nil),
57 | }
58 |
59 | // Iterate over input standards and check if the document passes its requirements.
60 | for _, standard := range standards {
61 | if err = standard.ValidateStandard(detailedReader); err != nil {
62 | fmt.Printf("Input document didn't pass the standard: %s - %v\n", standard.StandardName(), err)
63 | }
64 | }
65 |
66 | duration := float64(time.Since(start)) / float64(time.Millisecond)
67 | fmt.Printf("Processing time: %.2f ms\n", duration)
68 | }
69 |
--------------------------------------------------------------------------------
/redact/README.md:
--------------------------------------------------------------------------------
1 | # PDF redactor Examples
2 |
3 | The example explains how a text is redacted from the a pdf file using the `redactor` package.
4 |
5 | To redact a given content from a pdf file:
6 | - First prepare the regular expressions that can match the target texts.
7 | - Then build `redactor.RedactionTerm` using the `regex` as shown in the [example](redact_text.go).
8 | - Finaly initialize a `redactor.Redactor` object using `model.PdfReader`, `redactor.RedactionOptions` and `redactor.RectangleProps` to apply redaction on the given pdf file.
9 |
10 | ## Example
11 |
12 | - [redact_text.go](redact_text.go) The example shows redaction of credit card numbers and emails from a pdf file using regex patterns.
--------------------------------------------------------------------------------
/redact/outputs/test_file01_redacted.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/redact/outputs/test_file01_redacted.pdf
--------------------------------------------------------------------------------
/redact/test_files/test_file01.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/redact/test_files/test_file01.pdf
--------------------------------------------------------------------------------
/render/README.md:
--------------------------------------------------------------------------------
1 | # Render
2 |
3 | ### Image rendering
4 |
5 | Examples showcasing rendering PDF pages to image files:
6 |
7 | - [pdf_image_render.go](pdf_image_render.go) The example renders PDF files to images. It renders all pages of all input files to PNG images, and saves them in the specified output directory.
8 | - [pdf_image_render_custom_encoder_cgo.go](pdf_image_render_custom_encoder_cgo.go) The example renders PDF files to images using a custom JPEG2000 encoder.
9 |
10 |
--------------------------------------------------------------------------------
/report/README.md:
--------------------------------------------------------------------------------
1 | # PDF Report Creation
2 |
3 | The example explains how to create PDF reports using UniPDF, it also shows you how to add tables. There is a separate example to highlight the functionality of `styled paragraphs`, which allows you to add paragraphs where each word can have different formatting.
4 |
5 | ## Examples
6 |
7 | - [pdf_report.go](pdf_report.go) The example showcases PDF report generation with UniPDF's creator package. The output is saved as unidoc-report.pdf which illustrates some of the features of the creator.
8 | - [pdf_tables.go](pdf_tables.go) The example showcases PDF tables features using UniPDF's creator package. The output is saved as UniPDF-tables.pdf which illustrates some of the features of the creator.
9 | - [pdf_custom_toc.go](pdf_custom_toc.go) The example showcases the capabilities of generating PDF custom table of contents layout. The output is saved as pdf-custom-toc.pdf.
10 | - [pdf_report_from_csv.go](pdf_report_from_csv.go) This example showcases how to prepare a report from csv data.
11 |
--------------------------------------------------------------------------------
/report/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/report/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/report/pdf-custom-toc.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/pdf-custom-toc.pdf
--------------------------------------------------------------------------------
/report/report_from_csv.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/report_from_csv.pdf
--------------------------------------------------------------------------------
/report/report_from_csv_preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/report_from_csv_preview.png
--------------------------------------------------------------------------------
/report/test-data.csv:
--------------------------------------------------------------------------------
1 | Date of Sale,Quantity Sold,Sale Price,Salesperson Name
2 | 2023-01-01,10,100,John Doe
3 | 2023-01-02,15,150,Jane Smith
4 | 2023-01-03,8,80,Jim Brown
5 | 2023-01-04,20,200,Jenny White
6 | 2023-01-05,5,50,John Doe
7 | 2023-01-06,12,120,Jane Smith
8 | 2023-01-07,22,220,Jim Brown
9 | 2023-01-08,14,140,Jenny White
10 | 2023-01-09,18,180,John Doe
11 | 2023-01-10,9,90,Jane Smith
12 | 2023-01-11,11,110,Jim Brown
13 | 2023-01-12,19,190,Jenny White
14 | 2023-01-13,6,60,John Doe
15 | 2023-01-14,25,250,Jane Smith
16 | 2023-01-15,16,160,Jim Brown
17 | 2023-01-16,10,100,Jenny White
18 | 2023-01-17,13,130,John Doe
19 | 2023-01-18,7,70,Jane Smith
20 | 2023-01-19,9,90,Jim Brown
21 | 2023-01-20,23,230,Jenny White
22 | 2023-01-21,17,170,John Doe
23 | 2023-01-22,4,40,Jane Smith
24 | 2023-01-23,21,210,Jim Brown
25 | 2023-01-24,8,80,Jenny White
26 | 2023-01-25,15,150,John Doe
27 | 2023-01-26,10,100,Jane Smith
28 | 2023-01-27,12,120,Jim Brown
29 | 2023-01-28,18,180,Jenny White
30 | 2023-01-29,6,60,John Doe
31 | 2023-01-30,20,200,Jane Smith
32 | 2023-01-31,14,140,Jim Brown
33 |
--------------------------------------------------------------------------------
/report/unidoc-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/unidoc-logo.png
--------------------------------------------------------------------------------
/report/unidoc-report-landscape.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/unidoc-report-landscape.pdf
--------------------------------------------------------------------------------
/report/unidoc-report.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/unidoc-report.pdf
--------------------------------------------------------------------------------
/report/unipdf-tables.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/report/unipdf-tables.pdf
--------------------------------------------------------------------------------
/sanitize/README.md:
--------------------------------------------------------------------------------
1 | # PDF Sanitize Contents
2 |
3 | The example explains how to sanitize PDF contents using UniPDF, it also shows you how to initiate `model.PdfWriter` and removes some of PDF page contents like annotations and PDF Javascript.
4 |
5 | ## Examples
6 |
7 | - [pdf_modify_contents.go](pdf_modify_contents.go) The example showcases PDF writer of UniPDF's model package can be used to initiate empty PDF then add page from UniPDF reader and removes page annotations.
8 |
--------------------------------------------------------------------------------
/sanitize/outputs/JSPopupCalendarSanitized.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/sanitize/outputs/JSPopupCalendarSanitized.pdf
--------------------------------------------------------------------------------
/sanitize/test-files/JSPopupCalendar.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/sanitize/test-files/JSPopupCalendar.pdf
--------------------------------------------------------------------------------
/sanitize/unidoc-file-modified.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/sanitize/unidoc-file-modified.pdf
--------------------------------------------------------------------------------
/sanitize/unidoc-file.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/unidoc/unipdf-examples/722a2409c1eae388f507dd7cf2287b47d2ddd89b/sanitize/unidoc-file.pdf
--------------------------------------------------------------------------------
/search-and-replace/READ.md:
--------------------------------------------------------------------------------
1 | # PDF Text Search and Replace
2 |
3 | This example shows how to do text search and replacement on PDF using unipdf.
4 |
5 | ## Examples
6 | - [search_text.go](search_text.go) This examples shows how to do text searching using unipdf's by providing the pattern string and the pages to search on.
7 | - [replace_text.go](replace_text.go) This example show how to replace a given text by searching for it using a pattern and a replacement string.
8 | A list of pages is also provided in the parameter to specify which to do the replacement.
--------------------------------------------------------------------------------
/search-and-replace/replace_text.go:
--------------------------------------------------------------------------------
1 | /*
2 | * This example code shows how to do search and replace operation in PDF using unipdf
3 | *
4 | * Run as: go run replace_text.go