Pro edition
Filter
At a glance
Section titled “At a glance”NextPDF\Pro\Filter provides two focused helpers: a parser for the PDF
/DecodeParms dictionary and a reverse-filter for the PNG predictor applied
to FlateDecoded streams. It is the predictor support used by the Pro Diff and
Classifier extractors; it is not a general filter framework.
Availability & licensing
Section titled “Availability & licensing”This capability ships in NextPDF Pro (nextpdf/pro) and activates with a
Pro-tier license envelope. A deployment without that entitlement does not load the capability’s classes. Compare editions and get a license.
The Filter classes are available whenever nextpdf/pro is installed; no runtime
capability flag gates this module.
Install
Section titled “Install”composer require nextpdf/pro:^3Conceptual overview
Section titled “Conceptual overview”PDF streams may be FlateDecode-compressed and additionally pre-processed
with a predictor to improve compression. ISO 32000-2:2020 §7.4.4.4 defines
the predictor parameters (/Predictor, /Columns, /Colors,
/BitsPerComponent) and the PNG predictor family (tags 10–15).
DecodeParmsparses a/DecodeParmsdictionary fragment into an immutable value object with sane defaults (predictor 1, columns 1, colors 1, bits-per-component 8).isPngPredictor()is true for tags 10–15.PngPredictorapplies the inverse of the five PNG filter types — None, Sub, Up, Average, Paeth — plus Optimum (predictor 15, per-row tag). It validates parameters and raisesInvalidArgumentExceptionon out-of-range values or a truncated row.
This module reverses an existing predictor when reading a stream. It does not implement the full set of PDF stream filters and it does not provide filter-tuning hooks.
Why it works this way
Section titled “Why it works this way”The module reverses an existing predictor rather than offering a general
filter framework. The Pro Diff and Classifier extractors only read what a
producer already wrote, so a narrow scope is enough. That scope lets every
input be bounded before any byte is processed. DecodeParms::fromDictionary()
is the parse-time chokepoint: it rejects negative or oversized geometry and
applies the DecodeParms::__construct() defaults where a key is absent.
PngPredictor re-checks those bounds at apply time, so a hostile /DecodeParms
raises a typed error rather than a large allocation. Callers branch on
DecodeParms::isPngPredictor(), keeping the TIFF predictor out of a reverse
filter that handles only tags 10–15.
Design background: Streams and filters.
Behavior contract
Section titled “Behavior contract”DecodeParms::fromDictionary(string $raw): self— whitespace-tolerant integer matching; absent keys keep their defaults.PngPredictor::inverse(string $raw, int $columns, int $colors, int $bitsPerComponent, int $predictor): string— predictor must be 10–15; columns and colors must be ≥ 1; bits-per-component must be 1, 2, 4, 8, or 16; a row shorter than the computed stride raisesInvalidArgumentException.- Determinism. Output is a pure function of the inputs.
Public API surface
Section titled “Public API surface”| Type | Kind | Key members |
|---|---|---|
NextPDF\Pro\Filter\DecodeParms | final readonly class | __construct(int $predictor = 1, int $columns = 1, int $colors = 1, int $bitsPerComponent = 8), static fromDictionary(string $raw): self, isPngPredictor(): bool |
NextPDF\Pro\Filter\PngPredictor | final class | static inverse(string $raw, int $columns, int $colors, int $bitsPerComponent, int $predictor): string |
Code sample — Quick start
Section titled “Code sample — Quick start”<?php
declare(strict_types=1);
use NextPDF\Pro\Filter\DecodeParms;use NextPDF\Pro\Filter\PngPredictor;
$parms = DecodeParms::fromDictionary('<< /Predictor 15 /Columns 640 /Colors 3 >>');
if ($parms->isPngPredictor()) { $raw = PngPredictor::inverse( $flateDecodedBytes, $parms->columns, $parms->colors, $parms->bitsPerComponent, $parms->predictor, );}Code sample — Production
Section titled “Code sample — Production”<?php
declare(strict_types=1);
use InvalidArgumentException;use NextPDF\Pro\Filter\DecodeParms;use NextPDF\Pro\Filter\PngPredictor;
function undoPredictor(string $decoded, string $dictFragment): string{ $parms = DecodeParms::fromDictionary($dictFragment);
if (! $parms->isPngPredictor()) { return $decoded; // no predictor, or TIFF predictor — return as-is }
try { return PngPredictor::inverse( $decoded, $parms->columns, $parms->colors, $parms->bitsPerComponent, $parms->predictor, ); } catch (InvalidArgumentException) { return $decoded; // malformed predictor metadata — fail safe }}Edge cases & gotchas
Section titled “Edge cases & gotchas”- TIFF predictor (tag 2) is recognized by
DecodeParmsbut is not reverse-filtered byPngPredictor(which accepts only 10–15). Callers should branch onisPngPredictor(). - A predictor row shorter than the computed stride is rejected; it is not silently truncated.
- The row stride is computed from
columns * colors * bitsPerComponent; mismatched/DecodeParmsversus actual stream layout produces a parameter or truncation error rather than corrupt output.
Performance
Section titled “Performance”PngPredictor::inverse() is linear in stream length with a small per-byte
constant. DecodeParms parsing is a few bounded regular-expression matches.
See performance_budget.
Security notes
Section titled “Security notes”Parameter ranges are validated before any byte processing, and a truncated row raises rather than reads out of bounds. Callers reversing predictors on untrusted streams should also bound the decompressed size upstream, as the Pro Diff and Classifier extractors do.
Conformance
Section titled “Conformance”| Claim | Spec clause | Status |
|---|---|---|
/DecodeParms parameters and defaults | ISO 32000-2:2020 §7.4.4.4 | Verified (unit suite) |
| PNG predictor reverse-filter, tags 10–15 | ISO 32000-2:2020 §7.4.4.4 | Verified (unit suite) |
| Full PDF stream-filter framework | — | Not supported (out of scope) |
Core fallback / alternative
Section titled “Core fallback / alternative”No Core equivalent is exposed for PNG-predictor reversal. Core’s own stream handling is internal to the engine and not part of this public surface.
Enterprise boundary note
Section titled “Enterprise boundary note”This is a narrow predictor helper. It is not a cryptographic filter, a content sanitizer, or a data-reconstruction/disarm component; those concerns are out of scope.
Publication boundary
Section titled “Publication boundary”This page documents externally observable behavior and the supported public API surface only. Internal namespace paths, helper classes, mechanism tables, runbook filenames, and ticket prefixes are out of scope.