From 3ac8d7ed91d2ccba04a65e5bbb8ce51915d32d58 Mon Sep 17 00:00:00 2001 From: Eliot Jones Date: Sat, 25 Jan 2020 14:36:07 +0000 Subject: [PATCH] update the github pages site updates the information on the github pages site for the new api changes. includes some more seo friendly terms to improve discoverability, more engaging images as well as comprehensive code examples to improve onboarding. --- docs/builder-output.png | Bin 0 -> 32212 bytes docs/index.md | 278 ++++++++++++++++++++++++++++------------ 2 files changed, 196 insertions(+), 82 deletions(-) create mode 100644 docs/builder-output.png diff --git a/docs/builder-output.png b/docs/builder-output.png new file mode 100644 index 0000000000000000000000000000000000000000..2126d66fd72187630379b17f1ddfa1572529c862 GIT binary patch literal 32212 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 literal 0 HcmV?d00001 diff --git a/docs/index.md b/docs/index.md index 20d21b2e..125ae4f1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,88 +1,202 @@ -[PdfPig](https://github.com/UglyToad/PdfPig) is a fully open-source .NET standard compatible library that enables users to extract text content from PDFs in C#. - -Using PdfPig users can read text from a PDF in C# without the need for commercial libraries. - -## Credit ## - -This project wouldn't be possible without the work done by the [PDFBox](https://pdfbox.apache.org/) team and the Apache Foundation. - -## Usage ## - -The ```PdfDocument``` class provides access to the contents of a document loaded either from file or passed in as bytes. To open from a file use the ```PdfDocument.Open``` static method: - - using UglyToad.PdfPig; - using UglyToad.PdfPig.Content; - - using (PdfDocument document = PdfDocument.Open(@"C:\my-file.pdf")) - { - int pageCount = document.NumberOfPages; - - Page page = document.GetPage(1); - - decimal widthInPoints = page.Width; - decimal heightInPoints = page.Height; - - string text = page.Text; - } - -```PdfDocument``` should only be used in a ```using``` statement since it implements ```IDisposable``` (unless the consumer disposes of it elsewhere). - -Since this is alpha software the consumer should wrap all access in a ```try catch``` block since it is extremely likely to throw exceptions. As a fallback you can try running PDFBox using [IKVM](https://www.ikvm.net/) or using [PDFsharp](http://www.pdfsharp.net). - -The document contains the version of the PDF specification it complies with, accessed by ```document.Version```: - - decimal version = document.Version; - -### Document Information ### - -The ```PdfDocument``` provides access to the document metadata as ```DocumentInformation``` defined in the PDF file. These tend not to be provided therefore most of these entries will be ```null```: - - PdfDocument document = PdfDocument.Open(fileName); - - // The name of the program used to convert this document to PDF. - string producer = document.Information.Producer; - - // The title given to the document - string title = document.Information.Title; - // etc... - -### Page ### - -The ```Page``` contains the page width and height in points as well as mapping to the ```PageSize``` enum: - - PageSize size = Page.Size; - - bool isA4 = size == PageSize.A4; - -```Page``` provides access to the text of the page: - - string text = page.Text; - -### Letter ### - -Due to the way a PDF is structured internally the page text may not be a readable representation of the text as it appears in the document. Since PDF is a presentation format, text can be drawn in any order, not necessarily reading order. This means spaces may be missing or words may be in unexpected positions in the text. - -To help users resolve actual text order on the page, the ```Page``` file provides access to a list of the letters: - - - IReadOnlyList letters = page.Letters; - -These letters contain: - -+ The text of the letter: ```letter.Value```. -+ The location of the lower left of the letter: ```letter.Location```. -+ The width of the letter: ```letter.Width```. -+ The font size in unscaled relative text units (these sizes are internal to the PDF and do not correspond to sizes in pixels, points or other units): ```letter.FontSize```. -+ The name of the font used to render the letter if available: ```letter.FontName```. - -Letter position is measured in PDF coordinates where the origin is the lower left corner of the page. Therefore an higher Y value means closer to the top of the page. - -At this stage letter position is experimental and **will change in future versions**! Do not rely on letter positions remaining constant between different versions of this package. +[PdfPig](https://github.com/UglyToad/PdfPig) is a fully open-source Apache 2.0 licensed and .NET Standard compatible library that enables users to read and create PDFs in C#, F# and other .NET languages. It supports all versions of .NET back to .NET 4.5. ## Installation ## -The **pre-release** package is available via the releases tab or from Nuget: +The package is available via the releases tab or from Nuget: -[https://www.nuget.org/packages/PdfPig/](https://www.nuget.org/packages/PdfPig/) \ No newline at end of file +[https://www.nuget.org/packages/PdfPig/](https://www.nuget.org/packages/PdfPig/) + +Or from the package manager command line: + + > Install-Package PdfPig + +## Features ## + ++ Extracts the position and size of letters from any PDF document. This enables access to the text and words in a PDF document. ++ Allows the user to retrieve images from the PDF document. ++ Allows the user to read PDF annotations, PDF forms, embedded documents and hyperlinks from a PDF. ++ Provides access to metadata in the document. ++ Exposes the internal structure of the PDF document. ++ Creates PDF documents containing text and path operations. ++ Read content from encrypted files by providing the password. + +This provides an alternative to the commercial libraries such as [SpirePDF](https://www.e-iceblue.com/Introduce/pdf-for-net-introduce.html) or copyleft alternatives such as [iText 7](https://github.com/itext/itext7-dotnet) (AGPL) for some use-cases. + +It should be noted the library does not support use-cases such as converting HTML to PDF or from other document formats to PDF. For HTML to PDF a good quality solution is [wkhtmltopdf](https://wkhtmltopdf.org/). It also does not currently support generating images from PDF pages. If you need this functionality see if [docnet](https://github.com/GowenGit/docnet) meets your requirements. + +## Getting Started ## + +The Portable Document Format (PDF) is a document format which is focused on presentation. This means as far as possible PDFs will appear the same on most devices. For this reason PDFs tend to lose semantic meaning for their content including ordering of text, separation of text sections, etc. + +PdfPig provides access to the letters on each page in a PDF. This can be used to rebuild text from a PDF in C# (or other .NET languages). + +To open a PDF document and read the letters, words and images: + + using System.Collections.Generic; + using System.Linq; + using UglyToad.PdfPig; + using UglyToad.PdfPig.Content; + + public static class Program + { + public static void Main() + { + using (PdfDocument document = PdfDocument.Open(@"C:\path\to\pdffile\file.pdf")) + { + foreach (Page page in document.GetPages()) + { + IReadOnlyList letters = page.Letters; + string example = string.Join(string.Empty, letters.Select(x => x.Value)); + + IEnumerable words = page.GetWords(); + + IEnumerable images = page.GetImages(); + } + } + } + } + +For password protected PDF documents you can provide a set of passwords using the parsing options class: + + ParsingOptions parsingOptions = new ParsingOptions + { + Passwords = new List {"a password", "password123"} + }; + + using (PdfDocument document = PdfDocument.Open(@"C:\path\to\pdffile\file.pdf", parsingOptions)) + { + // Get the title from the document metadata. + Console.WriteLine(document.Information.Title); + + foreach (Page page in document.GetPages()) + { + IReadOnlyList letters = page.Letters; + Console.WriteLine(letters.Count); + } + } + +This also shows accessing document metadata using the `document.Information` property. All metadata is optional according to the specification so all entries can be `null`. + +Letters can be used by consumers to build text and content extraction capabilities into their software. For example table detection. There are many properties for letters in PDFs. See the [wiki page](https://github.com/UglyToad/PdfPig/wiki/Letters) for full details of the `Letter` API. + +The image below shows an example of the letter (teal) and word (pink) bounding boxes (`GlyphRectangle` for letter): + +![Image shows three words 'Write something in' in 2 sections, the top section is the normal PDF output, the bottom section is the same text with 3 word bounding boxes in pink and letter bounding boxes in blue-green](https://raw.githubusercontent.com/UglyToad/Pdf/master/documentation/Letters/example-text-extraction.png) + +## Creating Documents ## + +PdfPig can be used to make a PDF document in C# and other .NET languages. At the moment the API supports drawing letters and paths. The code snippet shows creating a new PDF document with 1 A4 page and writing some text on that page in Helvetica before saving the file to `C:\temp\file.pdf`: + + using System.IO; + using UglyToad.PdfPig.Content; + using UglyToad.PdfPig.Core; + using UglyToad.PdfPig.Fonts.Standard14Fonts; + using UglyToad.PdfPig.Writer; + + public static class Program + { + public static void Main() + { + PdfDocumentBuilder builder = new PdfDocumentBuilder(); + + PdfDocumentBuilder.AddedFont helvetica = builder.AddStandard14Font(Standard14Font.Helvetica); + PdfDocumentBuilder.AddedFont helveticaBold = builder.AddStandard14Font(Standard14Font.HelveticaBold); + + PdfPageBuilder page = builder.AddPage(PageSize.A4); + + PdfPoint closeToTop = new PdfPoint(15, page.PageSize.Top - 25); + + page.AddText("My first PDF document!", 12, closeToTop, helvetica); + + page.AddText("Hello World!", 10, closeToTop.Translate(0, -15), helveticaBold); + + File.WriteAllBytes(@"C:\temp\file.pdf", builder.Build()); + } + } + +The output is a file with the text "My first PDF document!" and then "Hello World!". Since PDF coordinates run from the bottom of the page upwards the Y coordinate of the top of the page is higher than 0 and the bottom of the page has a Y value of 0. The output file is shown below in Chrome's PDF viewer: + +![Image shows a single page PDF document with the text "My first PDF document!" on line 1 and "Hello World!" on line 2 in bold smaller font.](https://raw.githubusercontent.com/UglyToad/Pdf/master/docs/builder-output.png) + +You can also use TrueType fonts which support non-ASCII text by registering the font with the `PdfDocumentBuilder` prior to use: + + PdfDocumentBuilder builder = new PdfDocumentBuilder(); + + // You must provide a valid path to a .ttf file. + byte[] robotoBytes = File.ReadAllBytes(@"C:\fonts\roboto.ttf"); + PdfDocumentBuilder.AddedFont roboto = builder.AddTrueTypeFont(robotoBytes); + +See the [document creation](https://github.com/UglyToad/PdfPig/wiki/Document-Creation) page on the wiki for more details. + +## PdfDocument ## + +The `PdfDocument` provides access to XMP format metadata, AcroForms, Embedded files used by file annotations, bookmarks indicating the internal structure of the document and much more. Some examples are shown in the code sample: + + using System; + using System.Collections.Generic; + using System.Xml.Linq; + using UglyToad.PdfPig; + using UglyToad.PdfPig.AcroForms; + using UglyToad.PdfPig.AcroForms.Fields; + using UglyToad.PdfPig.Content; + using UglyToad.PdfPig.Outline; + + public static class Program + { + public static void Main() + { + using (PdfDocument document = PdfDocument.Open(@"C:\temp\file.pdf")) + { + Console.WriteLine($"Document has {document.NumberOfPages} pages."); + + if (document.TryGetForm(out AcroForm form)) + { + foreach (AcroFieldBase field in form.GetFieldsForPage(1)) + { + switch (field) + { + case AcroCheckboxField cb: + if (cb.IsChecked) + { + Console.WriteLine($"Checkbox was checked: {cb.Information.MappingName}."); + } + break; + } + } + } + + if (document.TryGetXmpMetadata(out XmpMetadata metadata)) + { + XDocument xmp = metadata.GetXDocument(); + } + + if (document.TryGetBookmarks(out Bookmarks bookmarks)) + { + Console.WriteLine($"Document contained bookmarks with {bookmarks.Roots.Count} root nodes."); + } + + Console.WriteLine($"Document uses version {document.Version} of the PDF specification."); + + if (document.Advanced.TryGetEmbeddedFiles(out IReadOnlyList embeddedFiles)) + { + Console.WriteLine($"Document contains {embeddedFiles.Count} embedded files."); + } + } + } + } + +## Document Layout Analysis ## + +PdfPig also comes with some tools for document layout analysis such as the Recursive XY Cut, Document Spectrum and Nearest Neighbour algorithms, along with others. It also provides support for exporting page contents to Alto, PageXML and hOcr format. + +An example of the output of the Recursive XY Cut algorithm viewed in an external viewer such as [LayoutEvalGUI](https://www.primaresearch.org/tools/PerformanceEvaluation) is shown below: + +![Output is a single page with two columns and some bulleted lists. The page has been divided into regions bounded in blue and words bounded in red.](https://raw.githubusercontent.com/UglyToad/PdfPig/master/documentation/Document%20Layout%20Analysis/recursive%20xy%20cut%20example.png) + +See the [document layout analysis](https://github.com/UglyToad/PdfPig/wiki/Document-Layout-Analysis) page on the wiki for full details. + +## Credit ## + +This project wouldn't be possible without the work done by the [PDFBox](https://pdfbox.apache.org/) team and the Apache Foundation. \ No newline at end of file