Help us shape the future of Go! Take the 2026 Go Developer Survey

pdf

package module
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 10, 2026 License: Apache-2.0 Imports: 32 Imported by: 4

README

pdf

Go Reference CI

Robust PDF text extraction in pure Go — with glyph positions, hardened against real-world (and hostile) files.

Zero dependencies. Built entirely on Go's standard library.

import "github.com/giraffesyo/pdf"

doc, err := pdf.Extract(ctx, readerAt, size)
if err != nil { ... }

text := doc.Text()             // whole document, plain text
page := doc.Pages[0]
line := page.Text()            // per-page reconstruction
glyphs := page.Glyphs          // text, origin, advance, direction, size; Baseline(), Quad()

Page.Text reconstructs reading order from direction-aware glyph baselines, and word boundaries are recovered from glyph gaps and font metrics — so PDFs that encode no space characters at all still come out readable. Rotated and vertical runs retain their reading direction. Side-by-side columns — journal papers, newsletters, fact sheets — read one after another, with titles, full-width figures and text below the columns in their places, while tables keep their rows. Arabic and Hebrew, which PDFs paint in visual order, read back in logical order, with numbers and embedded left-to-right words in place (the Unicode Bidirectional Algorithm's reordering, applied in reverse). Page.TextIn and Page.GlyphsIn extract a rectangular region.

Extraction options and diagnostics

Extract is the permissive, all-pages convenience API. ExtractWithOptions adds passwords, page ranges, strict mode, configurable resource limits, artifact filtering, layout strategies, named CMap resolution, document extras, page images, and an optional OCR handoff:

doc, err := pdf.ExtractWithOptions(ctx, readerAt, size, pdf.Options{
    Password: "secret",
    Pages:    []pdf.PageRange{{First: 2, Last: 5}},
    Strict:   true,
    Layout:   pdf.LayoutOptions{Mode: pdf.LayoutColumns},

    IgnoreArtifacts:    true,
    IncludeMetadata:    true,
    IncludeOutlines:    true,
    IncludeAnnotations: true,
    IncludeFormValues:  true,
    IncludeImages:      true,
})

Ligature presentation forms (fi, fl, ff, ffi, ffl, ſt, st) fold to their letter sequences by default, as pdftotext and pdf.js do, so extracted text stays searchable; set PreserveLigatures: true to keep the raw codepoints.

Text painted twice at the same place — fake bold, drop shadows, fill-then-stroke headings — is read once, as pdftotext and PDFBox read it; LayoutOptions.KeepDuplicateGlyphs keeps the repeats, and Page.Glyphs reports every painted glyph either way. Text drawn over other text on the same baseline, such as an overlay or stamp, comes out on a line of its own instead of interleaved letter by letter. Text drawn wholly off the page — beyond the media box, as a Form XObject larger than its page draws it — is left out, as pdftotext and MuPDF leave it (LayoutOptions.KeepOffPageText keeps it); a line that merely runs past the edge stays whole.

Permissive extraction retains recoverable output and records conditions that may have made it incomplete in Document.Warnings and Page.Warnings. Strict mode returns the partial document with a *pdf.StrictError at the first such condition. pdf.ErrPasswordRequired is available for errors.Is.

Text that annotations paint over the page — filled form fields, free-text comments, stamps — is part of the page's text, as a viewer shows it and as pdftotext extracts it; text and choice fields are drawn from their values when the form asks viewers to regenerate appearances. Set IgnoreAnnotationAppearances: true for the page content alone.

For large files, ExtractPages invokes a callback one page at a time and does not retain page glyphs in the returned document:

summary, err := pdf.ExtractPages(ctx, readerAt, size, opts, func(page pdf.Page) error {
    consume(page)
    return nil
})

Images and OCR

Scanned pages have no text to extract; they have an image. With IncludeImages, every image a page paints — image XObjects and inline images, through Form XObjects — is reported in Page.Images with where it landed on the page and its data in the most directly usable form:

for _, im := range page.Images {
    im.Bounds()            // page-space rectangle; Quad() for rotated placements
    im.ToPage(x, y)        // image pixel → page point, for positioning OCR output
    im.Filter              // "DCTDecode": Data is a JPEG file; "JPXDecode", "CCITTFaxDecode",
                           // "JBIG2Decode": still encoded; "": unpacked samples
    img, err := im.Decode() // image.Image for raw samples, JPEG, JPEG 2000, CCITT G3/G4, JBIG2
}

Decode handles unpacked samples in the Device, Cal, ICCBased, Indexed and single-colorant Separation/DeviceN spaces and image masks at 1–16 bits per component (palettes over spot colours in their printed colour, through the PDF tint-transform functions), DCTDecode through image/jpeg (CMYK with or without an Adobe marker), and — natively, from the ITU-T specifications — JPEG 2000 (JP2 files and codestreams: every progression order, tiling, precinct and code-block option, both wavelets, palettes and channel definitions), CCITT Group 3/4 fax and JBIG2 (generic, symbol and text regions with arithmetic coding, which is what scanner pipelines emit). The rarer JBIG2 features (Huffman tables, refinement, halftones) return errors.ErrUnsupported; their Data is still handed over for an external decoder. Limits.MaxImagePixels bounds what Decode will allocate.

The core remains dependency-free: no OCR engine is bundled. Applications implement pdf.OCR, which receives the page's glyphs and images and returns positioned glyphs that join the page's text — Page.Text, TextIn and the layout modes then treat OCR words like typeset ones. Options.OCRPolicy selects the pages: those with no text (the default), those that paint an image (mixed typeset text and scanned figures), or all of them. Where none of the three is the rule a document needs — a form with a typed header over a scanned body has text, so the default passes it by — Options.OCRSelect takes a predicate instead:

OCRSelect: func(page pdf.Page) bool {
    return len(page.Glyphs) < 100 && page.ImageCount > 0
},

Page.OCRGlyphs counts the glyphs that came from OCR. Without IncludeImages, image data is read only for the pages the policy selects and is not retained afterwards; Page.ImageCount is reported either way, so a page with no text can be told apart from a page with no images — the first is a scan an OCR engine can read, the second has had its text converted to vector outlines and needs a renderer. OCR runs concurrently across pages under Options.Concurrency, so implementations — and an OCRSelect predicate — are expected to be safe for concurrent use.

ocr/tesseract is a reference implementation that shells out to the Tesseract command-line program (which must be installed), feeds it each image — JPEG as is, everything else through Decode as PNG — and maps its word boxes onto the page:

import "github.com/giraffesyo/pdf/ocr/tesseract"

doc, err := pdf.ExtractWithOptions(ctx, readerAt, size, pdf.Options{
    OCR: &tesseract.Engine{Languages: []string{"eng"}},
})

The same shape fits a cloud OCR API or a vision model: decode or forward Image.Data, and place the results with Image.ToPage. The request also carries the original io.ReaderAt for implementations that render the whole page with an external renderer — the only route for text that was converted to vector outlines.

Why another PDF text extractor

This package grew out of converting large corpora of real-world documents with ledongthuc/pdf, whose built-in text extraction breaks on files that are common in the wild:

Real-world file ledongthuc/pdf this package
Google Docs exports (text inside Form XObjects) extracts nothing full text
Word exports (Identity-H fonts + ToUnicode CMaps) U+FFFD soup decoded
Type3 fonts with ToUnicode but an /Encoding dict control-char garbage decoded
Td/T*-positioned text (most PDFs) positions lost positioned
Array token split across /Contents segments lexer hangs forever handled
Decompression bombs, stalled filter chains unbounded CPU/memory hard budgets
Cyclic page trees stack overflow (crash) rejected upfront
Inline images (BI/ID/EI) derails the lexer lexed exactly, reported as images

Everything is implemented here, from ISO 32000 directly, with no external dependencies: the object layer (cross-reference tables and streams, object streams, hybrid references, stream filters, and standard-handler decryption), the standard font encodings and Adobe Glyph List, and everything from the content stream down — lexer, interpreter, text state machine, CTM/Form-XObject handling, variable-width ToUnicode and encoding CMaps, horizontal/vertical CID metrics, embedded TrueType/CFF/Type1 fallbacks, and tagged-PDF /ActualText.

Undecodable glyphs (no ToUnicode, no standard encoding) are dropped, not emitted as garbage, so image-only or outlined-text PDFs yield empty output you can detect, instead of plausible-looking noise.

Ligature presentation forms (fi, fl, ff, ffi, ffl, ſt, st) — which TeX-generated PDFs reach through /Differences glyph names — fold to their letter sequences, as pdftotext and pdf.js do, so extracted text stays searchable.

Limitations

  • No bundled OCR: scanned pages and text converted to vector outlines have no text to extract unless the caller supplies an OCR implementation (see Images and OCR). The package does not rasterize pages, so outlined text needs an external renderer.
  • Layout reconstruction is heuristic. Column detection reads prose columns in order and keeps tables in rows, but irregular layouts — tables of sentences, text wrapped around figures — may still need application-specific analysis of glyph quads; LayoutColumns forces column reading and LayoutContentOrder keeps the stream's order.
  • Identity-H and Identity-V CMaps are built in, and the Unicode CMaps (UniJIS-UCS2-H, UniGB-UTF16-H, UniKS-UTF8-V, …) read without their data, since their codes are the text; their non-ASCII widths then take the font's default. Other named predefined CMaps — and the Unicode ones' exact widths — are loaded through Options.CMapResolver; embedded CMap streams and usecmap inheritance are parsed natively. A font in one of Adobe's CJK collections (Japan1, GB1, CNS1, Korea1, KR) with neither a ToUnicode map nor a cmap reads its CIDs through the collection's character table, built in (about 120 KB).
  • Image.Decode does not decode the Huffman, refinement and halftone parts of JBIG2, JPEG 2000 samples deeper than 16 bits or the Part 15 high-throughput coder (JPEG 2000 decodes to 8 bits per sample); their encoded data is still reported. Soft masks, colour-key masking and JPEG 2000 opacity channels are not applied.

Benchmarks

The benchmarks/ directory is a separate module (so its dependencies stay out of this one) that compares extraction against ledongthuc/pdf and rsc.io/pdf over identical synthetic corpora. The corpus checks both whether the expected text is recovered and whether extraction completes safely. A comparator that returns incorrect text, errors, or panics is excluded from the performance run for that fixture.

Results below were measured on 2026-09-23 at commit f238684, using Go 1.27.0 on macOS 26.5.1 (darwin/arm64, Apple M5 Pro). Values are the median of five runs of go test -bench . -benchmem -run '^$' -count=5 ./...; rerun on your own hardware before making a performance decision.

Corpus this package ledongthuc/pdf rsc.io/pdf
simple ok ok incorrect text
Form XObject ok incorrect text incorrect text
Flate-compressed content ok ok incorrect text
xref stream ok ok incorrect text
object stream ok ok incorrect text
RC4-encrypted ok unsupported unsupported

Latency (ns/op):

Corpus this package ledongthuc/pdf
simple 9,358 14,614
Form XObject 11,007 incorrect text
Flate content 10,450 19,881
xref stream 9,736 13,759
object stream 10,545 22,254
RC4-encrypted 30,332 unsupported

Memory (B/op) and allocations (allocs/op):

Corpus this package B/op ledongthuc/pdf B/op this package allocs/op ledongthuc/pdf allocs/op
simple 41,472 62,960 172 368
Form XObject 44,728 incorrect text 218 incorrect text
Flate content 43,272 107,888 184 386
xref stream 42,472 62,904 176 366
object stream 44,856 100,360 201 542
RC4-encrypted 72,768 unsupported 333 unsupported

To reproduce the support matrix and performance measurements:

cd benchmarks
go test -run TestCompetitorComparison -v ./...   # support matrix
go test -bench . -benchmem -run '^$' -count=5 ./... # results above (medians)

The corpus is synthetic and deliberately small: it measures parser and extractor behavior, not throughput on a representative production document set. For that, on a sample of 1,004 real documents from GovDocs1 (U.S. government PDFs from many producers and decades), extracting each file's text with a small command built on this package, one file at a time, took 10.3 s in all against 34.5 s for poppler's pdftotext on the same machine (2026-09-24, Apple M5 Pro), with 96.7% of pdftotext's words recovered. It does show that this package recovers the expected text from every fixture, including Form XObjects, xref streams, object streams, and encrypted files.

Concurrency

Extract reconstructs the pages of a long document in parallel, on cloned readers that share the cross-reference table and decryption key but resolve objects independently, and Document.Text reconstructs their text the same way. Output does not depend on it: pages, glyphs, and warnings come out in the same order either way. Options.Concurrency sets the number of workers — zero, the default, picks one per processor up to a cap and falls back to sequential extraction for short documents, and one extracts sequentially. Strict extraction and CMapResolver always run sequentially: strict mode stops at the first warning, and a resolver need not be safe for concurrent use. OCR implementations and an OCRSelect predicate are the exception — they are called concurrently, since OCR dominates the cost of a scanned document — so set Concurrency to one for an engine that cannot be shared.

Regression corpus

testdata/corpus/ holds real documents — LaTeX, Word, Acrobat PDFMaker, InDesign, LiveCycle forms, Chrome, macOS Quartz, Ghostscript, and scanning-pipeline output, with embedded Type1, TrueType, and CFF fonts and right-to-left text — under redistributable licenses (see testdata/corpus/NOTICE.md). TestCorpusGolden pins Document.Text for each file in testdata/corpus/golden/, so a decoding or layout change is a reviewable diff; accept an intentional change with go test -run TestCorpusGolden -update. TestCorpusAllocationBudget pins bytes and allocations per extraction for each file — stable across machines, unlike timing — in testdata/corpus/golden/budget.json, and fails when a file exceeds its budget by more than 15% (go test -run TestCorpusAllocationBudget -update accepts a deliberate change). BenchmarkCorpus measures Extract plus Document.Text over the same files, and CI fails a pull request that regresses it against its base. Documents that cannot be committed can be benchmarked locally with PDF_CORPUS_DIR=/path/to/pdfs go test -bench '^BenchmarkCorpus$' -run '^$' ..

pdftest

github.com/giraffesyo/pdf/pdftest builds minimal synthetic PDFs for tests (in the spirit of httptest): document skeletons, composite fonts, ToUnicode CMaps, Form XObjects, segmented content streams. This package's own regression suite is built on it — every failure pattern above is reproduced synthetically, with fuzzing on top.

License

Apache-2.0. See LICENSE. Embeds the Adobe Glyph List (Apache-2.0) for glyph-name decoding, and character tables for Adobe's Chinese, Japanese, and Korean collections derived from cmap-resources (BSD-3-Clause; see internal/cjk/data/NOTICE), and the advance widths of the 14 standard fonts derived from Adobe's Core 14 AFM files (see internal/stdfont/NOTICE and MustRead.html).

Documentation

Overview

Package pdf extracts text and direction-aware glyph geometry from PDF files.

Extract returns per-page glyph quads and baselines; Page.Text reconstructs plain text by clustering direction-compatible glyphs into lines and inserting word spacing derived from glyph gaps and font metrics.

The package is pure Go with no external dependencies. It implements the PDF object layer (cross-reference tables and streams, object streams, stream filters, and password-aware standard-handler decryption) natively per ISO 32000, and on top of it a content-stream lexer, interpreter, and font decoder tuned for real-world files: it descends into Form XObjects (where e.g. Google Docs exports keep their text), honors /ToUnicode even alongside an /Encoding dictionary, tracks positions through every text operator, honors tagged-PDF replacement text, never loops on tokens straddling /Contents array segments, and reports bounded partial extraction caused by decompression bombs, stalled filter chains, or work limits.

Scanned pages carry images rather than text. Options.IncludeImages reports every image a page paints with its placement and data (Image), Image.Decode turns raw samples, JPEG, CCITT fax and JBIG2 into an image.Image, and Options.OCR hands the pages an OCRPolicy selects to an OCR implementation whose words join the page's glyphs. No OCR engine is bundled; ocr/tesseract is a reference implementation over the Tesseract command-line program.

Index

Constants

This section is empty.

Variables

View Source
var ErrImageTooLarge = errors.New("pdf: image exceeds the pixel limit")

ErrImageTooLarge is returned by Image.Decode for an image whose pixel count exceeds Limits.MaxImagePixels.

View Source
var ErrPasswordRequired = crypt.ErrPasswordRequired

ErrPasswordRequired reports that an encrypted document could not be unlocked with the supplied password.

Functions

This section is empty.

Types

type Annotation added in v0.3.0

type Annotation struct {
	Subtype     string
	Rect        Rect
	Contents    string
	Title       string
	URL         string
	Destination Destination
}

Annotation contains text-bearing annotation and link information.

type CMapResolver added in v0.3.0

type CMapResolver func(name string) ([]byte, error)

CMapResolver supplies a named predefined CMap that is not built into the package. The returned bytes use normal PDF CMap syntax. Without one, the predefined Unicode CMaps still read, from their codes, with the font's default width for characters outside ASCII; a resolver supplying them gives their exact CIDs, and so widths.

type Destination added in v0.3.0

type Destination struct {
	Name string
	Page int
	X    float64
	Y    float64
	Zoom float64
}

Destination identifies a named destination or a destination on a page.

type Document

type Document struct {
	PageCount  int
	Pages      []Page
	Metadata   Metadata
	Outlines   []Outline
	FormFields []FormField
	Warnings   []Warning
}

Document is the extraction result for a whole file.

func Extract

func Extract(ctx context.Context, r io.ReaderAt, size int64) (*Document, error)

Extract parses the PDF in r and extracts every page's glyphs. Malformed pages yield whatever was decoded before the failure; a malformed file returns an error. The context is checked between pages and periodically while processing page operators and glyphs.

func ExtractPages added in v0.3.0

func ExtractPages(
	ctx context.Context,
	r io.ReaderAt,
	size int64,
	opts Options,
	yield func(Page) error,
) (*Document, error)

ExtractPages extracts pages one at a time and calls yield without retaining them in the returned Document. Document metadata, page count, form fields, outlines, and accumulated warnings are still returned.

func ExtractWithOptions added in v0.3.0

func ExtractWithOptions(ctx context.Context, r io.ReaderAt, size int64, opts Options) (*Document, error)

ExtractWithOptions extracts selected pages and document extras according to opts. In strict mode it returns the partial document together with the first warning as a *StrictError.

func (*Document) Text

func (d *Document) Text() string

Text reconstructs the whole document's plain text: pages separated by blank lines, empty pages skipped.

type FormField added in v0.3.0

type FormField struct {
	Name          string
	AlternateName string
	Type          string
	Value         string
	Page          int
}

FormField is one terminal AcroForm field.

type Glyph

type Glyph struct {
	Text string  // decoded text, non-empty
	X, Y float64 // origin: where the baseline starts
	// Advance is the glyph's width along the baseline in page units: its
	// font width, scaled. Character and word spacing (Tc, Tw) move the
	// next glyph on but are not part of this one, as poppler measures a
	// glyph's box; the gap to the next glyph includes them.
	Advance float64
	Size    float64 // effective font size

	// Direction is the unit direction the baseline runs in. Ascent and
	// Descent are the vectors from the baseline to the far and near
	// edges of the glyph box, preserving rotation, skew, and vertical
	// writing: horizontal text has Ascent spanning the font size along
	// the text-space y axis and a zero Descent; vertical text reaches
	// half the font size to either side of its baseline.
	Direction Point
	Ascent    Point
	Descent   Point
}

Glyph is one decoded glyph (or glyph cluster) with its position in unrotated page space.

The geometry is stored compactly — a document's glyph slice is its largest allocation — and Baseline and Quad derive the full shapes. A Glyph carrying only Text, X, Y, Advance, and Size (for example one supplied by an OCR hook) is treated as upright horizontal text.

func (Glyph) Baseline added in v0.3.0

func (g Glyph) Baseline() Line

Baseline returns the segment the glyph occupies along its writing direction: from the origin, |Advance| page units along Direction.

func (Glyph) Quad added in v0.3.0

func (g Glyph) Quad() Quad

Quad returns the glyph's region perimeter: the baseline offset by Descent, then the same edge returning along Ascent.

type Image added in v0.5.0

type Image struct {
	Width, Height    int
	BitsPerComponent int
	// Components is the number of samples per pixel in Data: 1 for image
	// masks and Indexed images, 3 for RGB, 4 for CMYK, and so on. It is
	// zero when the codec carries its own colour information (JPXDecode
	// without a /ColorSpace).
	Components int
	// ColorSpace is the colour space family: DeviceGray, DeviceRGB,
	// DeviceCMYK, Indexed, ICCBased, CalGray, CalRGB, Lab, Separation,
	// DeviceN or Pattern. It is empty for an image mask, and for a
	// JPXDecode image that carries its own colour space.
	ColorSpace string
	// ImageMask reports a stencil mask: one bit per pixel, where sample
	// 0 (or 1 under a /Decode [1 0]) marks the pixels painted in the
	// current fill colour. Scanned bilevel pages are often masks.
	ImageMask bool
	// Inline reports an inline image (BI … ID … EI) rather than an XObject.
	Inline bool
	Filter string
	Data   []byte
	// contains filtered or unexported fields
}

Image is one image painted on a page — an image XObject or an inline image — with the geometry it was painted at and its data in the most directly usable form the package can supply without decoding it.

Data holds the image after decryption and the general-purpose stream filters. When Filter is empty, Data is unpacked samples: Height rows of Width × Components samples of BitsPerComponent bits each, rows padded to a byte boundary. Otherwise Filter names the image codec Data is still encoded with: DCTDecode (Data is a complete JPEG file), JPXDecode (a JPEG 2000 codestream or JP2 file), CCITTFaxDecode or JBIG2Decode. An OCR engine or image library that accepts that format can take Data as is; Decode turns the formats the package understands into an image.Image.

Soft masks, colour-key masking and rendering intent are not reported.

func (Image) Bounds added in v0.5.0

func (im Image) Bounds() Rect

Bounds returns the page-space bounding box of Quad.

func (Image) Decode added in v0.5.0

func (im Image) Decode() (image.Image, error)

Decode returns the image's pixels. Unpacked samples in the Device, Cal, ICCBased, Indexed and single-colorant Separation and DeviceN spaces, and image masks, decode at 1, 2, 4, 8 or 16 bits per component; an Indexed palette over a Separation or DeviceN space decodes in its printed colour, through the space's tint transform. DCTDecode decodes through image/jpeg, including CMYK data without the Adobe marker image/jpeg expects. JPXDecode (JPEG 2000) decodes natively at 8 bits per sample, in the dictionary's colour space when it names one and otherwise the file's own, opacity channels dropped. CCITTFaxDecode and JBIG2Decode (generic, symbol and text regions with arithmetic coding) decode natively to one-bit grey. Other colour spaces, JBIG2 features outside that subset, and JPEG 2000 beyond 16 bits per sample or with the Part 15 high-throughput coder return an error wrapping errors.ErrUnsupported. An image with more than Limits.MaxImagePixels pixels returns ErrImageTooLarge rather than allocating.

Results are *image.Gray, *image.Gray16, *image.Paletted (Indexed), *image.RGBA, *image.CMYK, or whatever image/jpeg returns. A stencil mask decodes to *image.Gray with painted pixels black. CCITT data that ends early yields the rows decoded, the rest white.

func (Image) Quad added in v0.5.0

func (im Image) Quad() Quad

Quad returns the region the image was painted over: its bottom-left, bottom-right, top-right and top-left corners in page space, in that order, so the first edge follows the image's top-to-bottom rows' direction and the shape reflects any rotation or skew.

func (Image) ToPage added in v0.5.0

func (im Image) ToPage(x, y float64) Point

ToPage maps a pixel position to unrotated page space: x runs right and y runs down from the image's top-left sample, so (0, 0) is the top-left corner and (Width, Height) the bottom-right. Coordinates an OCR engine reports for the image land on the page through this mapping.

type LayoutMode added in v0.3.0

type LayoutMode uint8

LayoutMode selects how Page.Text reconstructs text.

const (
	// LayoutPosition groups glyphs into lines by their geometric
	// baselines and reads the page top to bottom, and side-by-side
	// columns of prose one after another: a band of lines split by a
	// common gutter reads column by column when a column holds prose,
	// while tables, whose short cells share every row, read row by row.
	// Text spanning the columns — a title, a full-width figure caption —
	// ends the band and reads in its place.
	LayoutPosition LayoutMode = iota
	// LayoutContentOrder preserves the order in which glyphs occur in content
	// streams, inserting line breaks only when the baseline changes.
	LayoutContentOrder
	// LayoutColumns reads every band of lines split by a common gutter
	// column by column, tables included: LayoutPosition's column reading
	// without its test for prose.
	LayoutColumns
)

type LayoutOptions added in v0.3.0

type LayoutOptions struct {
	Mode LayoutMode

	// KeepOffPageText keeps text drawn wholly outside the page's media
	// box, which no viewer shows and pdftotext and MuPDF do not extract:
	// a Form XObject larger than the page, content positioned off it.
	// Page.Glyphs reports it either way.
	KeepOffPageText bool

	// KeepDuplicateGlyphs keeps glyphs that repeat another on the same
	// line: the same text painted at the same place and size, as fake
	// bold, drop shadows, and fill-then-stroke headings are drawn. By
	// default text reconstruction reads each such glyph once, as poppler
	// and PDFBox do; Page.Glyphs reports every painted glyph either way.
	KeepDuplicateGlyphs bool
}

LayoutOptions controls plain-text reconstruction.

type Limits added in v0.3.0

type Limits struct {
	MaxStreamBytes      int
	MaxOperatorsPerPage int
	MaxGlyphsPerPage    int
	MaxFormDepth        int

	// MaxImagesPerPage bounds how many image paintings a page is read
	// for, whether or not their data is collected. Default 10,000.
	MaxImagesPerPage int
	// MaxImageBytesPerPage bounds the image data read for one page, over
	// all its distinct images, each of which MaxStreamBytes bounds on its
	// own. Images past the budget are left out with a WarningStreamLimit.
	// Default 256 MiB.
	MaxImageBytesPerPage int
	// MaxImagePixels bounds the images Image.Decode is willing to
	// allocate, in pixels. Default 64 Mi (a 600 dpi letter page is
	// 34 Mi). Larger images are still reported with their encoded Data.
	MaxImagePixels int
}

Limits bounds work performed on untrusted documents. Zero fields use the package defaults.

type Line added in v0.3.0

type Line struct {
	Start Point
	End   Point
}

Line describes a directed line segment.

type Metadata added in v0.3.0

type Metadata struct {
	Title        string
	Author       string
	Subject      string
	Keywords     string
	Creator      string
	Producer     string
	CreationDate string
	ModifiedDate string
	Trapped      string
	XMP          []byte
	Custom       map[string]string
}

Metadata contains common document information dictionary and XMP fields. Dates retain their original PDF string representation.

type OCR added in v0.3.0

type OCR interface {
	ExtractPage(context.Context, OCRRequest) ([]Glyph, error)
}

OCR supplies text for pages the content streams cannot. Implementations invoke an external renderer or OCR engine; the core package remains dependency-free. The glyphs returned are positioned in unrotated page space (Image.ToPage maps an engine's image coordinates there) and are appended to the page's glyphs; Page.OCRGlyphs counts them. Glyphs returned together with an error are kept, and the error is recorded as a WarningOCR.

Pages are OCR'd concurrently when Options.Concurrency allows: an implementation must be safe for concurrent use, or the caller sets Concurrency to one.

type OCRFunc added in v0.3.0

type OCRFunc func(context.Context, OCRRequest) ([]Glyph, error)

OCRFunc adapts a function to OCR.

func (OCRFunc) ExtractPage added in v0.3.0

func (f OCRFunc) ExtractPage(ctx context.Context, req OCRRequest) ([]Glyph, error)

ExtractPage calls f.

type OCRPolicy added in v0.5.0

type OCRPolicy uint8

OCRPolicy selects the pages an OCR implementation is asked about.

const (
	// OCRTextlessPages selects pages whose content streams produced no
	// glyphs: scanned pages, and pages whose text was converted to
	// outlines. This is the default.
	OCRTextlessPages OCRPolicy = iota
	// OCRImagePages selects pages that paint at least one image, with or
	// without text of their own, for documents that mix typeset text and
	// scanned figures or stamps.
	OCRImagePages
	// OCRAllPages selects every extracted page.
	OCRAllPages
)

type OCRRequest added in v0.3.0

type OCRRequest struct {
	Reader     io.ReaderAt
	Size       int64
	PageNumber int
	Page       Page
}

OCRRequest is passed to an external OCR implementation for a page the OCRPolicy, or OCRSelect, selects. Page carries whatever the content streams yielded — its Glyphs, and its Images with their placement and encoded data — so an implementation can OCR the page's images directly, through Image.Decode or by handing the still-encoded Data to an engine that reads JPEG. Reader and Size identify the original PDF for implementations that render the page with an external renderer instead, which is what text converted to vector outlines needs.

type Options added in v0.3.0

type Options struct {
	Password string
	Pages    []PageRange
	Strict   bool
	Limits   Limits
	Layout   LayoutOptions

	IgnoreArtifacts bool
	// IgnoreAnnotationAppearances leaves out the text that annotations
	// paint over the page: filled form fields, free-text comments, stamps.
	// By default a page's glyphs include it, after the page's own content,
	// as a viewer shows it and as poppler and MuPDF extract it; hidden
	// annotations are skipped either way. Text and choice fields are drawn
	// from their values when the form asks viewers to regenerate
	// appearances (/NeedAppearances) or a field has none. IncludeAnnotations
	// and IncludeFormValues report annotations and field values as data,
	// independently of this.
	IgnoreAnnotationAppearances bool
	IncludeMetadata             bool
	IncludeOutlines             bool
	IncludeAnnotations          bool
	IncludeFormValues           bool
	// IncludeImages reports the images each page paints in Page.Images,
	// with their placement and their data as described by Image. Without
	// it image data is never read, except for the pages an OCR
	// implementation is asked about, and those pages do not retain it.
	IncludeImages bool

	// PreserveLigatures keeps the Unicode presentation forms U+FB00–U+FB06
	// (ff fi fl ffi ffl ſt st) in glyph text. By default they fold to their letter
	// sequences (ff, fi, fl, ffi, ffl, st) — the form searchers, tokenizers
	// and other extractors expect — whether the glyph reached the ligature
	// codepoint through a glyph name (Type1 /Differences, the standard
	// encodings, an embedded font program) or through a ToUnicode CMap.
	PreserveLigatures bool

	CMapResolver CMapResolver

	// OCR is asked for text on the pages OCRPolicy selects. It runs after
	// the page's content streams are extracted, with the page's glyphs
	// and images in hand.
	OCR       OCR
	OCRPolicy OCRPolicy

	// OCRSelect chooses the pages OCR is asked about, and overrides
	// OCRPolicy where it is set. The three policies are the answers
	// worth naming, not the only reasonable ones: a form with a typed
	// header over a scanned body has glyphs, so OCRTextlessPages passes
	// it by, while OCRImagePages reads every figure in a document that
	// is mostly typeset. A predicate can say what the document actually
	// needs — a floor on glyphs per page, a page range, a size the
	// images have to reach.
	//
	// The page it receives is the one the content streams produced:
	// Glyphs and ImageCount are set, and Images is still empty, because
	// image data is read only once something asks for it. Like OCR
	// itself, it is called from the page workers and must be safe for
	// concurrent use; see Concurrency.
	OCRSelect func(page Page) bool

	// Concurrency bounds how many pages are extracted at once. Zero picks
	// a worker per available processor; one extracts sequentially.
	// Extraction stays deterministic either way: pages, their glyphs, and
	// their warnings come out in the same order.
	//
	// Pages run concurrently only when nothing observable depends on the
	// order they execute in. Strict stops at the first warning, and
	// CMapResolver is caller code that need not be safe for concurrent
	// use, so those extract sequentially whatever this is set to. OCR
	// implementations are called concurrently, since OCR dominates the
	// cost of a scanned document; set Concurrency to one for an engine
	// that cannot share.
	Concurrency int
}

Options controls extraction. Its zero value preserves Extract's permissive, all-pages behavior.

type Outline added in v0.3.0

type Outline struct {
	Title       string
	Destination Destination
	Children    []Outline
}

Outline is one bookmark in the document outline tree.

type Page

type Page struct {
	Number int
	// Glyphs holds the page's text in content order. Glyphs an OCR
	// implementation supplied come last; OCRGlyphs counts them.
	Glyphs []Glyph
	// OCRGlyphs is the number of trailing Glyphs the OCR implementation
	// supplied rather than the content streams.
	OCRGlyphs int
	// Images holds the images the page paints, in content order, when
	// Options.IncludeImages is set.
	Images []Image
	// ImageCount is how many images the page paints, reported whether or
	// not their data was read — Images is empty without
	// Options.IncludeImages, and this is not.
	//
	// It is what separates the two reasons a page can yield no glyphs. A
	// page that paints images is a scan, and an OCR implementation can
	// read it; a page that paints none has had its text converted to
	// vector outlines, which needs a renderer instead, or is simply
	// blank. Nothing else in the result tells those apart.
	ImageCount  int
	MediaBox    Rect
	CropBox     Rect
	Rotation    int
	Annotations []Annotation
	Warnings    []Warning
	// contains filtered or unexported fields
}

Page holds the glyphs of one page in content order.

func (Page) GlyphsIn added in v0.3.0

func (p Page) GlyphsIn(region Rect) []Glyph

GlyphsIn returns glyphs whose quadrilateral intersects region.

func (Page) Text

func (p Page) Text() string

Text reconstructs a page's plain text using glyph baselines and the layout selected at extraction time. Rotated and vertical runs retain their reading direction, and spaces are inferred from geometric gaps.

func (Page) TextIn added in v0.3.0

func (p Page) TextIn(region Rect, layout LayoutOptions) string

TextIn reconstructs text from glyphs intersecting region.

func (Page) TextWithOptions added in v0.3.0

func (p Page) TextWithOptions(layout LayoutOptions) string

TextWithOptions reconstructs page text using layout rather than the layout selected during extraction.

type PageRange added in v0.3.0

type PageRange struct {
	First int
	Last  int
}

PageRange selects an inclusive, one-based page range. A Last value of zero means the final page.

type Point added in v0.3.0

type Point struct {
	X float64
	Y float64
}

Point is a coordinate in unrotated PDF page space.

type Quad added in v0.3.0

type Quad [4]Point

Quad describes a glyph-region perimeter. The first edge follows the baseline direction and the opposite edge returns toward its origin.

type Rect added in v0.3.0

type Rect struct {
	MinX float64
	MinY float64
	MaxX float64
	MaxY float64
}

Rect is an axis-aligned rectangle in unrotated PDF page space.

type StrictError added in v0.3.0

type StrictError struct {
	Warning Warning
}

StrictError is returned when strict extraction encounters a condition that permissive extraction would record as a Warning.

func (*StrictError) Error added in v0.3.0

func (e *StrictError) Error() string

func (*StrictError) Unwrap added in v0.3.0

func (e *StrictError) Unwrap() error

type Warning added in v0.3.0

type Warning struct {
	Page int
	Code WarningCode
	Err  error
}

Warning describes a condition that may have made an extraction incomplete. Page is one-based, or zero for a document-level warning.

func (Warning) Error added in v0.3.0

func (w Warning) Error() string

func (Warning) Unwrap added in v0.3.0

func (w Warning) Unwrap() error

type WarningCode added in v0.3.0

type WarningCode string

WarningCode identifies a recoverable extraction problem.

const (
	// WarningMalformedDocument reports malformed document-level structures
	// such as outlines or form-field trees.
	WarningMalformedDocument WarningCode = "malformed_document"
	// WarningMalformedPage reports malformed page content or page extras.
	WarningMalformedPage WarningCode = "malformed_page"
	// WarningStream reports a stream decoding or filter failure.
	WarningStream WarningCode = "stream_error"
	// WarningStreamLimit reports decoded data truncated at a configured limit.
	WarningStreamLimit WarningCode = "stream_limit"
	// WarningWorkLimit reports an operator, glyph, or nesting budget.
	WarningWorkLimit WarningCode = "work_limit"
	// WarningUnsupported reports a recoverable unsupported PDF feature.
	WarningUnsupported WarningCode = "unsupported"
	// WarningOCR reports an external OCR implementation failure.
	WarningOCR WarningCode = "ocr"
)

Directories

Path Synopsis
internal
cjk
Package cjk maps the CIDs of Adobe's Chinese, Japanese, and Korean character collections to Unicode, for fonts that give no other way to read their text: no ToUnicode map, and a font program with no cmap.
Package cjk maps the CIDs of Adobe's Chinese, Japanese, and Korean character collections to Unicode, for fonts that give no other way to read their text: no ToUnicode map, and a font program with no cmap.
cjk/internal/gen command
Command gen builds the CID→Unicode tables of package cjk from Adobe's Unicode CMaps (github.com/adobe-type-tools/cmap-resources, BSD-3-Clause):
Command gen builds the CID→Unicode tables of package cjk from Adobe's Unicode CMaps (github.com/adobe-type-tools/cmap-resources, BSD-3-Clause):
codec/ccitt
Package ccitt decodes CCITT Group 3 and Group 4 fax coding: the one-dimensional modified Huffman (MH) and two-dimensional modified READ (MR) schemes of ITU-T T.4 and the modified modified READ (MMR) scheme of ITU-T T.6.
Package ccitt decodes CCITT Group 3 and Group 4 fax coding: the one-dimensional modified Huffman (MH) and two-dimensional modified READ (MR) schemes of ITU-T T.4 and the modified modified READ (MMR) scheme of ITU-T T.6.
codec/dct
Package dct decodes the PDF DCTDecode filter's JPEG data (ISO 32000-1 §7.4.8) through image/jpeg, bridging where PDF writers and image/jpeg disagree.
Package dct decodes the PDF DCTDecode filter's JPEG data (ISO 32000-1 §7.4.8) through image/jpeg, bridging where PDF writers and image/jpeg disagree.
codec/jbig2
Package jbig2 decodes the JBIG2 bi-level images embedded in PDF files through the JBIG2Decode filter (ISO 32000-1 §7.4.7): the "embedded stream" organisation of ITU-T T.88 Annex D.3, a sequence of segments without a file header, optionally preceded by the shared segments of a /JBIG2Globals stream.
Package jbig2 decodes the JBIG2 bi-level images embedded in PDF files through the JBIG2Decode filter (ISO 32000-1 §7.4.7): the "embedded stream" organisation of ITU-T T.88 Annex D.3, a sequence of segments without a file header, optionally preceded by the shared segments of a /JBIG2Globals stream.
codec/jpx
Package jpx decodes JPEG 2000 (ITU-T T.800 | ISO/IEC 15444-1), the coding of the PDF JPXDecode filter (ISO 32000-1 §7.4.9): JP2 files and bare codestreams.
Package jpx decodes JPEG 2000 (ITU-T T.800 | ISO/IEC 15444-1), the coding of the PDF JPXDecode filter (ISO 32000-1 §7.4.9): JP2 files and bare codestreams.
codec/mq
Package mq is the MQ adaptive binary arithmetic decoder shared by JBIG2 (ITU-T T.88 Annex E) and JPEG 2000 (ITU-T T.800 Annex C): the same coder, probability table and byte-stuffing convention.
Package mq is the MQ adaptive binary arithmetic decoder shared by JBIG2 (ITU-T T.88 Annex E) and JPEG 2000 (ITU-T T.800 Annex C): the same coder, probability table and byte-stuffing convention.
crypt
Package crypt implements the PDF standard security handler (ISO 32000-1 §7.6.3 and ISO 32000-2 §7.6.4): RC4 and AES stream/string decryption with the file key derived from a supplied user or owner password.
Package crypt implements the PDF standard security handler (ISO 32000-1 §7.6.3 and ISO 32000-2 §7.6.4): RC4 and AES stream/string decryption with the file key derived from a supplied user or owner password.
encoding
Package encoding implements the simple-font character encodings of ISO 32000-1 Annex D and the Adobe Glyph List glyph-name algorithm.
Package encoding implements the simple-font character encodings of ISO 32000-1 Annex D and the Adobe Glyph List glyph-name algorithm.
filter
Package filter implements the PDF stream decode filters of ISO 32000-1 §7.4 that text extraction needs: FlateDecode, LZWDecode, ASCIIHexDecode, ASCII85Decode and RunLengthDecode, with the PNG and TIFF predictors.
Package filter implements the PDF stream decode filters of ISO 32000-1 §7.4 that text extraction needs: FlateDecode, LZWDecode, ASCIIHexDecode, ASCII85Decode and RunLengthDecode, with the PNG and TIFF predictors.
function
Package function evaluates PDF functions (ISO 32000-1 §7.10): sampled (type 0), exponential interpolation (type 2), stitching (type 3) and PostScript calculator (type 4).
Package function evaluates PDF functions (ISO 32000-1 §7.10): sampled (type 0), exponential interpolation (type 2), stitching (type 3) and PostScript calculator (type 4).
object
Package object is a native PDF object layer: a lexer and parser for the COS object syntax (ISO 32000-1 §7.2–7.3), cross-reference tables and streams (§7.5), and a Value model for navigating the resulting object graph.
Package object is a native PDF object layer: a lexer and parser for the COS object syntax (ISO 32000-1 §7.2–7.3), cross-reference tables and streams (§7.5), and a Value model for navigating the resulting object graph.
safeio
Package safeio bounds reads from untrusted streams: decompression bombs and stalled filter chains must cost bounded memory and CPU.
Package safeio bounds reads from untrusted streams: decompression bombs and stalled filter chains must cost bounded memory and CPU.
stdfont
Package stdfont holds the advance widths of the 14 standard PDF fonts, which PDF 1.4 and earlier let a document use without a /Widths array, leaving the metrics to the reader.
Package stdfont holds the advance widths of the 14 standard PDF fonts, which PDF 1.4 and earlier let a document use without a /Widths array, leaving the metrics to the reader.
stdfont/internal/gen command
Command gen builds package stdfont's width tables from the Core 14 AFM files (Adobe; see ../../NOTICE):
Command gen builds package stdfont's width tables from the Core 14 AFM files (Adobe; see ../../NOTICE):
ocr
tesseract
Package tesseract implements pdf.OCR with the Tesseract command-line program, as a reference for plugging an OCR engine into github.com/giraffesyo/pdf: it OCRs the images a page paints and places the recognized words on the page through pdf.Image.ToPage, so they flow into Page.Text and the layout modes like typeset text.
Package tesseract implements pdf.OCR with the Tesseract command-line program, as a reference for plugging an OCR engine into github.com/giraffesyo/pdf: it OCRs the images a page paints and places the recognized words on the page through pdf.Image.ToPage, so they flow into Page.Text and the layout modes like typeset text.
Package pdftest builds minimal synthetic PDF files for tests, in the spirit of net/http/httptest.
Package pdftest builds minimal synthetic PDF files for tests, in the spirit of net/http/httptest.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL