Content streams

In PDF, drawing operations are all performed in content streams that describe the positioning and drawing order of all graphics (including text, images and vector drawing).

pikepdf (and libqpdf) provide two tools for interpreting content streams: a parser and a token filter. The parser returns higher level information, conveniently grouping each operator with its operands. Use it when you need to know what an instruction means, whether to retrieve information, such as the position of an element, or to remove, insert and change instructions. A content stream that is parsed and then unparsed draws the same thing, but its whitespace is normalized and its comments are lost.

The token filter works at a lower level, considering each token including comments, and distinguishing different types of spaces. It passes through everything it does not change exactly as written, so it suits changes to how a content stream is spelled, such as rounding numbers. A TokenFilter must be subclassed; the specialized version describes how it should transform the stream of tokens.

See also

Choosing between the parser and a token filter, which is followed by worked examples of token filters.

Content stream parsers

pikepdf.parse_content_stream(page_or_stream, operators='')

Parse a PDF content stream into a sequence of instructions.

A PDF content stream is list of instructions that describe where to render the text and graphics in a PDF. This is the starting point for analyzing PDFs.

If the input is a page and page.Contents is an array, then the content stream is automatically treated as one coalesced stream.

Each instruction contains at least one operator and zero or more operands.

This function does not have anything to do with opening a PDF file itself or processing data from a whole PDF. It is for processing a specific object inside a PDF that is already opened.

Parameters:
  • page_or_stream (Object | Page) – A page object, or the content stream attached to another object such as a Form XObject.

  • operators (str) – A space-separated string of operators to whitelist. For example ‘q Q cm Do’ will return only operators that pertain to drawing images. Use ‘BI ID EI’ for inline images. All other operators and associated tokens are ignored. If blank, all tokens are accepted.

Return type:

list[ContentStreamInstructions]

Example

>>> with pikepdf.Pdf.open("../tests/resources/pal-1bit-trivial.pdf") as pdf:
...     page = pdf.pages[0]
...     for operands, command in pikepdf.parse_content_stream(page):
...         print(command)
q
cm
Do
Q

Changed in version 3.0: Returns a list of ContentStreamInstructions instead of a list of (operand, operator) tuples. The returned items are duck-type compatible with the previous returned items.

pikepdf.unparse_content_stream(instructions)

Convert collection of instructions to bytes suitable for storing in PDF.

Given a parsed list of instructions/operand-operators, convert to bytes suitable for embedding in a PDF. In PDF the operator always follows the operands.

Parameters:

instructions (collections.abc.Collection[UnparseableContentStreamInstructions]) – collection of instructions such as is returned by parse_content_stream()

Returns:

A binary content stream, suitable for attaching to a Pdf. To attach to a Pdf, use Pdf.make_stream()`().

Return type:

bytes

Changed in version 3.0: Now accept collections that contain any mixture of ContentStreamInstruction, ContentStreamInlineImage, and the older operand-operator tuples from pikepdf 2.x.

class pikepdf.StreamParser

A simple content stream parser, which must be subclassed to be used.

Pass an instance of a subclass to pikepdf.Page.parse_contents(), which calls handle_object() once per object parsed from the content stream. Because objects are handled one at a time, the content stream is never materialized as a list of instructions, so memory use stays bounded regardless of stream length.

In practice, the performance of this class may be quite poor on long content streams because it creates objects and involves multiple function calls for every object in a content stream, some of which may be only a single byte long.

Consider instead using pikepdf.parse_content_stream().

abstractmethod handle_eof()

An abstract method that may be overloaded in a subclass.

Called at the end of a content stream.

Return type:

None

abstractmethod handle_object(obj, offset, length)

An abstract method that must be overloaded in a subclass.

This function will be called back once for each object that is parsed in the content stream.

Parameters:
  • obj (Object)

  • offset (int)

  • length (int)

Return type:

None

class pikepdf.models.ctm.MatrixStack(initial_matrix=None)

Tracks the CTM (current transformation matrix) in a PDF content stream.

The CTM starts as the initial matrix and can be changed via the ‘cm’ (concatenate matrix) operator –> CTM = CTM x CM (with CTM and CM being 3x3 matrixes). Initial matrix is the identity matrix unless overridden.

Furthermore can the CTM be stored to the stack via the ‘q’ operator. This save the CTM and subsequent ‘cm’ operators change a copy of that CTM –> ‘q 1 0 0 1 0 0 cm’ –> Copy CTM onto the stack and change the copy via ‘cm’

With the ‘Q’ operator the current CTM is replaced with the previous one from the stack.

Error handling: 1. Popping from an empty stack results in CTM being set to the initial matrix 2. Multiplying with invalid operands sets the CTM to invalid 3. Multiplying an invalid CTM with a valid CM results in an invalid CTM 4. Stacking an invalid CTM results in a copy of that invalid CTM onto the stack –> All operations with an invalid CTM result in an invalid CTM –> The CTM is valid again when all invalid CTMs are popped off the stack

Parameters:

initial_matrix (Matrix | None)

pikepdf.models.ctm.get_objects_with_ctm(page, initial_matrix=None)

Determines the current transformation matrix (CTM) for each drawn object.

Filters objects with an invalid CTM.

Parameters:
Return type:

list[tuple[str, Matrix]]

Content stream token filters

class pikepdf.Token(arg0, arg1, /)
Parameters:
property error_msg: str

If the token is an error, this returns the error message.

Return type:

str

property raw_value: bytes

The binary representation of a token.

Return type:

bytes

property type_: TokenType

Returns the type of token.

Return type:

TokenType

property value: str

Interprets the token as a string.

Return type:

str

class pikepdf.TokenType(*args, **kwds)

Type of a token that appeared in a PDF content stream.

When filtering content streams, each token is labeled according to the role in plays.

array_close: ...

The token data represents the end of an array.

array_open: ...

The token data represents the start of an array.

bad: ...

An invalid token.

bool: ...

The token data represents an integer, real number, null or boolean, respectively.

brace_close: ...

The token data represents the end of a brace.

brace_open: ...

The token data represents the start of a brace.

comment: ...

Signifies a comment that appears in the content stream.

dict_close: ...

The token data represents the end of a dictionary.

dict_open: ...

The token data represents the start of a dictionary.

eof: ...

Denotes the end of the tokens in this content stream.

inline_image: ...

An inline image in the content stream. The whole inline image is represented by the single token.

integer: ...

The token data represents an integer.

name_: ...

The token is the name (pikepdf.Name) of an object. In practice, these are among the most interesting tokens.

Changed in version 3.0: In versions older than 3.0, .name was used instead. This interfered with semantics of the Enum object, so this was fixed.

null: ...

The token data represents a null.

real: ...

The token data represents a real number.

space: ...

Whitespace within the content stream.

string: ...

The token data represents a string. The encoding is unclear and situational.

word: ...

Otherwise uncategorized bytes are returned as word tokens. PDF operators are words.

class pikepdf.TokenFilter
handle_token(token=...)

Handle a pikepdf.Token.

This is an abstract method that must be defined in a subclass of TokenFilter. The method will be called for each token. The implementation may return either None to discard the token, the original token to include it, a new token, or an iterable containing zero or more tokens. An implementation may also buffer tokens and release them in groups (for example, it could collect an entire PDF command with all of its operands, and then return all of it).

The final token will always be a token of type TokenType.eof, (unless an exception is raised).

If this method raises an exception, filtering stops and the exception propagates to the caller that triggered it. For a filter attached with pikepdf.Page.add_content_token_filter(), that is whatever next reads the content stream, usually pikepdf.Pdf.save().

See Choosing between the parser and a token filter for worked examples.

Parameters:

token (Token)

Return type:

None | Token | collections.abc.Iterable[Token]