A handle to one page of a PdfElixide.Document.
A %Page{} is just its document and a zero-based :index — it holds no
native resource of its own, which is why there is no Page.close/1 and why
building one costs nothing. It stays valid exactly as long as its document
does: closing the document makes every page handle taken from it report
{:error, %PdfElixide.Error{reason: :closed}}.
Get one from PdfElixide.Document.page/2, all of them from
PdfElixide.Document.pages/1, or iterate the document directly — it
implements Enumerable over its pages:
for page <- doc, do: PdfElixide.Document.Page.text!(page)Every extractor PdfElixide.Document offers is available here for a single
page, taking the same options. Working a page at a time is also the way to
bound memory on a large document, since only one page's results are live at
once — see the "Whole-document extraction and memory" section of
PdfElixide.Document.
A page whose :index is not a page of the document — only reachable from a
hand-built or stale %Page{} — yields
%PdfElixide.Error{reason: :out_of_range} from every function here.
Summary
Functions
Reads the annotations on the page.
Same as annotations/1 but raises an error if it fails.
Extracts the characters of the page, each with its bounding box, font metadata, and typographic placement.
Same as chars/2 but raises an error if it fails.
Extracts the fonts referenced by the page.
Same as fonts/1 but raises an error if it fails.
Returns whether the page carries a text layer, as opposed to being image-only or blank.
Same as has_text_layer/1 but returns the bare boolean, raising on failure.
Returns the page's height in points.
Same as height/1 but raises an error if it fails.
Extracts the raster images of the page — photos, logos, and scanned pictures.
Same as images/1 but raises an error if it fails.
Lists the Separation and DeviceN ink names the page declares.
Same as inks/2 but raises an error if it fails.
Returns the page's logical page label (e.g. "i", "1", "A-1").
Same as label/1 but raises an error if it fails.
Extracts the straight lines of the page.
Same as lines/1 but raises an error if it fails.
Returns the page's /MediaBox — the sheet it is imposed on — as a
PdfElixide.Geometry.Rect in unrotated user space.
Same as media_box/1 but raises an error if it fails.
Extracts the vector paths of the page — lines, curves, rectangles, and shapes.
Same as paths/1 but raises an error if it fails.
Extracts the rectangles of the page.
Same as rects/1 but raises an error if it fails.
Returns the page's /Rotate — the clockwise rotation a viewer applies when
displaying it — as 0, 90, 180 or 270.
Same as rotation/1 but raises an error if it fails.
Finds every occurrence of pattern on the page.
Same as search/3 but raises an error if it fails.
Extracts the spans of the page, each a run of text sharing one text state.
Same as spans/2 but raises an error if it fails.
Detects the tables of the page.
Same as tables/2 but raises an error if it fails.
Extracts the text content of the page.
Same as text/2 but raises an error if it fails.
Extracts the text lines of the page, each with its bounding box and words.
Same as text_lines/2 but raises an error if it fails.
Converts the page to an HTML fragment.
Same as to_html/2 but raises an error if it fails.
Converts the page to Markdown.
Same as to_markdown/2 but raises an error if it fails.
Returns the page's width in points.
Same as width/1 but raises an error if it fails.
Extracts the words of the page, each with its bounding box and font metadata.
Same as words/2 but raises an error if it fails.
Types
@type rotation() :: 0 | 90 | 180 | 270
A page's clockwise display rotation in degrees — always one of these four.
@type t() :: %PdfElixide.Document.Page{ doc: PdfElixide.Document.t(), index: non_neg_integer() }
Functions
@spec annotations(t()) :: {:ok, [PdfElixide.Document.Annotation.t()]} | {:error, PdfElixide.Error.t()}
Reads the annotations on the page.
Returns {:ok, []} when the page has no annotations.
@spec annotations!(t()) :: [PdfElixide.Document.Annotation.t()]
Same as annotations/1 but raises an error if it fails.
@spec chars(t(), PdfElixide.Document.chars_opts()) :: {:ok, [PdfElixide.Document.Char.t()]} | {:error, PdfElixide.Error.t()}
Extracts the characters of the page, each with its bounding box, font metadata, and typographic placement.
See PdfElixide.Document.chars_opts/0 for the available options.
@spec chars!(t(), PdfElixide.Document.chars_opts()) :: [PdfElixide.Document.Char.t()]
Same as chars/2 but raises an error if it fails.
@spec fonts(t()) :: {:ok, [PdfElixide.Document.Font.t()]} | {:error, PdfElixide.Error.t()}
Extracts the fonts referenced by the page.
Returns {:ok, []} when the page references no fonts — and also when the page
or its /Resources could not be read, which PdfElixide.Document.fonts/2
explains.
@spec fonts!(t()) :: [PdfElixide.Document.Font.t()]
Same as fonts/1 but raises an error if it fails.
@spec has_text_layer(t()) :: {:ok, boolean()} | {:error, PdfElixide.Error.t()}
Returns whether the page carries a text layer, as opposed to being image-only or blank.
This is the signal text/1 cannot give: an empty string means "no text was
extracted", which a scanned page and a genuinely blank page produce alike.
A false here says the page has nothing to extract, so a caller can route it
to OCR instead of treating the empty result as content.
It is a static probe, not an extraction — no text is assembled and no
fonts are loaded — and it approximates towards true, so the two answers are
not equally strong:
falseis reliable. The page declares no fonts and no form XObjects, or its content stream shows no text and invokes no XObject.trueis not a promise thattext/1returns anything. A page whose only XObject holds no text still answerstrue, and so does a page whose content stream cannot be decoded — deliberately, so that extraction is attempted rather than skipped on a guess.
One asymmetry looks like a bug but is not: a page with no fonts whose sole
XObject is an image answers false, which is what makes the image-only case
answerable cheaply. Text drawn in invisible render mode (Tr 3) is not
considered either way.
Same as has_text_layer/1 but returns the bare boolean, raising on failure.
Unlike PdfElixide.Document.has_structure_tree?/1 and
PdfElixide.Document.has_xfa?/1, this degrades nothing: every error raises,
not just a failure of the handle — see the predicates list in
PdfElixide.Error.
Sweep a document with it:
Enum.reject(doc, &PdfElixide.Document.Page.has_text_layer?/1)
@spec height(t()) :: {:ok, float()} | {:error, PdfElixide.Error.t()}
Returns the page's height in points.
This is media_box/1's :height, in unrotated user space, and like width/1
it is never negative and is not swapped for a rotated page. See rotation/1.
Same as height/1 but raises an error if it fails.
@spec images(t()) :: {:ok, [PdfElixide.Document.Image.t()]} | {:error, PdfElixide.Error.t()}
Extracts the raster images of the page — photos, logos, and scanned pictures.
Returns {:ok, []} when the page has no images.
@spec images!(t()) :: [PdfElixide.Document.Image.t()]
Same as images/1 but raises an error if it fails.
@spec inks(t(), PdfElixide.Document.inks_opts()) :: {:ok, [String.t()]} | {:error, PdfElixide.Error.t()}
Lists the Separation and DeviceN ink names the page declares.
These are the values :exclude_inks accepts. By default only the page's own
/Resources is read; PdfElixide.Document.inks/3 explains what that misses,
what :deep costs, and which colorants never appear.
@spec inks!(t(), PdfElixide.Document.inks_opts()) :: [String.t()]
Same as inks/2 but raises an error if it fails.
@spec label(t()) :: {:ok, String.t()} | {:error, PdfElixide.Error.t()}
Returns the page's logical page label (e.g. "i", "1", "A-1").
This is the human-facing page number the PDF may define, independent of the zero-based physical index. Pages outside any declared label range fall back to their decimal page number.
Every call re-reads the document's label ranges, so use
PdfElixide.Document.page_labels/1 to label a whole document.
Same as label/1 but raises an error if it fails.
@spec lines(t()) :: {:ok, [PdfElixide.Document.Path.t()]} | {:error, PdfElixide.Error.t()}
Extracts the straight lines of the page.
The paths of paths/1 narrowed to those classified as single straight
segments. Returns {:ok, []} when the page draws none. See the "Rectangles
and straight lines" section of PdfElixide.Document.Path for which shapes
qualify.
@spec lines!(t()) :: [PdfElixide.Document.Path.t()]
Same as lines/1 but raises an error if it fails.
@spec media_box(t()) :: {:ok, PdfElixide.Geometry.Rect.t()} | {:error, PdfElixide.Error.t()}
Returns the page's /MediaBox — the sheet it is imposed on — as a
PdfElixide.Geometry.Rect in unrotated user space.
The rect is normalized: :x and :y are the bottom-left corner and :width
and :height are non-negative, even for a file that writes the two corners in
the reverse order. It is not turned to match rotation/1: a 90-degree
page of a 612 × 792 MediaBox still reports 612 × 792 and displays 792 points
wide.
The origin need not be {0.0, 0.0}, and when it is not, nothing this library
returns is rebased on it — a glyph at the left edge of a page whose box starts
at 10.0 reports an x near 10.0. /MediaBox is also inheritable
(ISO 32000-1 §7.7.3.4): a page without one takes the box from an ancestor
/Pages node, and where two ancestors declare one, which of them wins is not
stable. Both are covered by the "Page boxes and the coordinate origin" section
of PdfElixide.Document.
A page with no /MediaBox anywhere above it, or whose entry is not an array,
or is an array of fewer than four elements, is malformed and yields
%PdfElixide.Error{reason: :invalid_pdf} — no default page size is
substituted. One malformation is not reported: an element that is not a
number reads as 0.0, so such a page reports a smaller box rather than
failing.
@spec media_box!(t()) :: PdfElixide.Geometry.Rect.t()
Same as media_box/1 but raises an error if it fails.
@spec paths(t()) :: {:ok, [PdfElixide.Document.Path.t()]} | {:error, PdfElixide.Error.t()}
Extracts the vector paths of the page — lines, curves, rectangles, and shapes.
Returns {:ok, []} when the page has no vector graphics.
@spec paths!(t()) :: [PdfElixide.Document.Path.t()]
Same as paths/1 but raises an error if it fails.
@spec rects(t()) :: {:ok, [PdfElixide.Document.Path.t()]} | {:error, PdfElixide.Error.t()}
Extracts the rectangles of the page.
The paths of paths/1 narrowed to those classified as rectangles. Returns
{:ok, []} when the page draws none. See the "Rectangles and straight lines"
section of PdfElixide.Document.Path for which shapes qualify.
@spec rects!(t()) :: [PdfElixide.Document.Path.t()]
Same as rects/1 but raises an error if it fails.
@spec rotation(t()) :: {:ok, rotation()} | {:error, PdfElixide.Error.t()}
Returns the page's /Rotate — the clockwise rotation a viewer applies when
displaying it — as 0, 90, 180 or 270.
A page's own /Rotate wins, but the entry is inheritable (ISO 32000-1
§7.7.3.4): a page without one takes the value from an ancestor /Pages node,
and 0 when no ancestor has one either. Where two ancestors declare one,
which of them wins is not stable — see the "Page boxes and the coordinate
origin" section of PdfElixide.Document, which covers /Rotate as well.
Two normalizations are worth knowing:
- a value outside
0..359wraps, so-90reads as270; - a value that is not a multiple of 90 is invalid per §7.7.3.3 and reads
as
0— it is not rounded down, so45is0, not90.
media_box/1, and the width/1 and height/1 derived from it, are never
swapped to match: a 90-degree page of a 612 × 792 MediaBox displays 792
points wide and 612 tall. Rotation also decides which frame an extracted
bbox is expressed in — see "Rotated pages and extracted geometry" in
PdfElixide.Document.
Same as rotation/1 but raises an error if it fails.
@spec search(t(), String.t(), PdfElixide.Document.search_opts()) :: {:ok, [PdfElixide.Document.SearchMatch.t()]} | {:error, PdfElixide.Error.t()}
Finds every occurrence of pattern on the page.
The pattern is plain text unless literal: false is given. See
PdfElixide.Document.search_opts/0 for the available options.
@spec search!(t(), String.t(), PdfElixide.Document.search_opts()) :: [ PdfElixide.Document.SearchMatch.t() ]
Same as search/3 but raises an error if it fails.
@spec spans(t(), PdfElixide.Document.spans_opts()) :: {:ok, [PdfElixide.Document.Span.t()]} | {:error, PdfElixide.Error.t()}
Extracts the spans of the page, each a run of text sharing one text state.
See PdfElixide.Document.spans_opts/0 for the available options.
@spec spans!(t(), PdfElixide.Document.spans_opts()) :: [PdfElixide.Document.Span.t()]
Same as spans/2 but raises an error if it fails.
@spec tables(t(), PdfElixide.Document.tables_opts()) :: {:ok, [PdfElixide.Document.Table.t()]} | {:error, PdfElixide.Error.t()}
Detects the tables of the page.
Returns {:ok, []} when the page has no detectable table. See
PdfElixide.Document.tables_opts/0 for the available options.
@spec tables!(t(), PdfElixide.Document.tables_opts()) :: [ PdfElixide.Document.Table.t() ]
Same as tables/2 but raises an error if it fails.
@spec text(t(), PdfElixide.Document.text_opts()) :: {:ok, String.t()} | {:error, PdfElixide.Error.t()}
Extracts the text content of the page.
A page that cannot be extracted is an error here, where
PdfElixide.Document.text/1 skips it by default — :on_page_error is a
whole-document option and does nothing on this path.
See PdfElixide.Document.text_opts/0 for the available options.
@spec text!(t(), PdfElixide.Document.text_opts()) :: String.t()
Same as text/2 but raises an error if it fails.
@spec text_lines(t(), PdfElixide.Document.text_lines_opts()) :: {:ok, [PdfElixide.Document.TextLine.t()]} | {:error, PdfElixide.Error.t()}
Extracts the text lines of the page, each with its bounding box and words.
See PdfElixide.Document.text_lines_opts/0 for the available options.
@spec text_lines!(t(), PdfElixide.Document.text_lines_opts()) :: [ PdfElixide.Document.TextLine.t() ]
Same as text_lines/2 but raises an error if it fails.
@spec to_html(t(), PdfElixide.Document.html_opts()) :: {:ok, String.t()} | {:error, PdfElixide.Error.t()}
Converts the page to an HTML fragment.
See PdfElixide.Document.html_opts/0 for the available options.
@spec to_html!(t(), PdfElixide.Document.html_opts()) :: String.t()
Same as to_html/2 but raises an error if it fails.
@spec to_markdown(t(), PdfElixide.Document.markdown_opts()) :: {:ok, String.t()} | {:error, PdfElixide.Error.t()}
Converts the page to Markdown.
See PdfElixide.Document.markdown_opts/0 for the available options.
@spec to_markdown!(t(), PdfElixide.Document.markdown_opts()) :: String.t()
Same as to_markdown/2 but raises an error if it fails.
@spec width(t()) :: {:ok, float()} | {:error, PdfElixide.Error.t()}
Returns the page's width in points.
This is media_box/1's :width, in unrotated user space. Like it, the value
is never negative and is not swapped for a rotated page: a page with
rotation/1 of 90 or 270 displays as height × width. See rotation/1.
Same as width/1 but raises an error if it fails.
@spec words(t(), PdfElixide.Document.words_opts()) :: {:ok, [PdfElixide.Document.Word.t()]} | {:error, PdfElixide.Error.t()}
Extracts the words of the page, each with its bounding box and font metadata.
See PdfElixide.Document.words_opts/0 for the available options.
@spec words!(t(), PdfElixide.Document.words_opts()) :: [PdfElixide.Document.Word.t()]
Same as words/2 but raises an error if it fails.