Ga naar inhoud
getnextpdf.com

Pro editie

Diff — Diepe referentie

Deze pagina is de referentie op contractniveau voor de NextPDF Pro diff-module, NextPDF\Pro\Diff. De module vergelijkt twee PDF-documenten en rapporteert wijzigingen in tekst, afbeeldingen en metadata. PdfDiffer levert een pagina-uitgelijnde Myers-regeldiff. StructuredDiffer voegt alineagroepering, afbeeldingsvergelijking en metadatavergelijking toe. DiffFormatter serialiseert het gestructureerde resultaat naar JSON of een HTML-fragment. Deze pagina beschrijft de publieke API, het waarneembare gedragscontract, de resourcegrenzen en de foutmodi. Taakgerichte setup en voorbeelden staan op de Diff-capaciteitspagina.

Deze capaciteit wordt geleverd in NextPDF Pro (nextpdf/pro) en activeert met een licentie-envelope op Pro-niveau. Een deployment zonder die entitlement laadt de klassen van de capaciteit niet. Vergelijk edities en vraag een licentie aan.

Geen runtime-capaciteitsflag gate’t deze module. De diff-klassen zijn bruikbaar zodra nextpdf/pro geïnstalleerd en gelicentieerd is.

SymboolParametersStandaardgedragRetourneertGooit of faalt metOpmerkingen
PdfDiffer::compare()string $sourcePdf, string $targetPdfExtraheert tekst per pagina en vergelijkt vervolgens pagina i van de bron met pagina i van het doelDiffResultInvalidArgumentException wanneer een buffer de %PDF-header mist of de optionele reader niet kan parsen; OverflowException bij een resourcegrensStatisch instappunt
PdfDiffer::compareTexts()array $sourcePages, array $targetPages (elk list<string>)Vergelijkt vooraf geëxtraheerde paginateksten en slaat extractie overDiffResultOverflowException bij een resourcegrensStatisch; gebruik dit wanneer de tekst al beschikbaar is
PdfDiffer::extractText()string $contentStreamParse’t tekstweergeefoperatoren uit één ruwe content-streamstring— (fouttolerant; onparsebare invoer levert een lege string op)Statisch
StructuredDiffer::__construct()?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = nullnull-argumenten construeren de standaard-differsConstructor-injectie voor testen
StructuredDiffer::compare()string $sourcePdf, string $targetPdfVoert tekst-, alinea-, afbeeldings- en metadatavergelijking uit en bouwt vervolgens een samenvattingStructuredDiffResultPropageert InvalidArgumentException en OverflowException vanuit het tekstpadOrchestrator over de hele module
DiffFormatter::toJson()StructuredDiffResult $resultPretty-printed JSON-documentstringJsonException wanneer encoderen mislukt
DiffFormatter::toHtml()StructuredDiffResult $resultHTML-fragment met samenvatting-, alinea- en metadatasecties; tekstwaarden worden entity-escapedstringAlleen een fragment, geen volledig document
DiffFormatter::toArray()StructuredDiffResult $resultSerialisatie-array die toJson() ondersteuntarray<string, mixed>Stabiele snake_case-sleutels
ImageDiffer::diff()string $sourcePdf, string $targetPdfHasht afbeeldings-XObjects en rapporteert toegevoegde, verwijderde en gewijzigde afbeeldingenlist<ImageDiff>— (niet-decodeerbare structuren worden fail-closed overgeslagen)Identiteit is paginabucket plus objectnummer
MetadataDiffer::diff()string $sourcePdf, string $targetPdfVergelijkt acht /Info-velden (Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate)list<MetadataChange>— (gooit nooit bij niet-conforme invoer)Waarden worden vergeleken als gedecodeerde strings
DiffEngine::diff()array $sourceLines, array $targetLines, int $pageIndex = 0, int $maxLines = 10000Myers-regeldiff over twee regellijstenlist<DiffRegion>OverflowException wanneer de gecombineerde regels $maxLines overschrijden of de edit-afstand de geheugengebonden limiet overschrijdtStatisch; de regioproducent voor alle tekstpaden
TextExtractor::fromContentStream()string $contentStreamTokeniseert de stream en draait de tekststatusmachinelist<TextBlock>Statisch
TextExtractor::fromOperations()array $operations (list<ContentStreamOp>)Draait de tekststatusmachine over vooraf geparsete operatieslist<TextBlock>Statisch
ContentStreamParser::parse()constructor neemt string $dataTokeniseert operatoren en operanden; slaat dictionaries en comments over; fouttolerantlist<ContentStreamOp>Niet-herkende bytes worden overgeslagen, nooit fataal
ContentStreamOpstring $operator, list<mixed> $operandsReadonly operatie-waardeobject; isTextOp() classificeert tekstgerelateerde operatoren
DiffResultlist<DiffRegion> $regions, int $sourcePagesCount, int $targetPagesCountVerdeelt regio’s over $added, $removed, $modified; biedt isIdentical(), hasDifferences(), totalChanges()Readonly; Unchanged-regio’s blijven alleen in $regions
StructuredDiffResulttekstdiff, alinea’s, afbeeldingen, metadatawijzigingen, samenvattingSamengesteld resultaat; hasDifferences(), isIdentical() delegeren naar de samenvattingReadonly
DiffSummarytellingen per categorie plus paginatellingenhasDifferences() en totalChanges() over tekst-, afbeeldings- en metadatatellingenReadonly
DiffRegionDiffType $type, string $text, int $pageIndex, int $lineIndex, ?string $counterpartText = nullEén wijziging op regelniveau$counterpartText blijft null in de geleverde engine
ParagraphDifftype, tekst, paginaindex, start-/eindregel, regio’sOpeenvolgende regio’s van hetzelfde type op één pagina; lineCount()Readonly
ImageDifftype, paginaindex, bronhash, doelhash, object-idEén afbeeldingswijzigingsvermeldingHashes zijn lege strings aan de afwezige kant
MetadataChangestring $field, ?string $sourceValue, ?string $targetValueEén veldwijziging; isAdded(), isRemoved(), isModified()null betekent dat het veld afwezig is
TextBlocktekst, x, y, fontnaam, fontgrootte, regelindexEén geëxtraheerde tekstrun met benaderende positieReadonly
DiffTypeenum: Added, Removed, Modified, UnchangedString-gebaseerde wijzigingsclassificatie voor tekstZie de Modified-opmerking in het gedragscontract
ImageDiffTypeenum: Added, Removed, Modified, UnchangedString-gebaseerde wijzigingsclassificatie voor afbeeldingen
public static function compare(string $sourcePdf, string $targetPdf): DiffResult
public static function compareTexts(array $sourcePages, array $targetPages): DiffResult
public static function extractText(string $contentStream): string
public function __construct(
?ImageDiffer $imageDiffer = null,
?MetadataDiffer $metadataDiffer = null,
)
public function compare(string $sourcePdf, string $targetPdf): StructuredDiffResult
public function toJson(StructuredDiffResult $result): string
public function toHtml(StructuredDiffResult $result): string
public function toArray(StructuredDiffResult $result): array
public static function diff(
array $sourceLines,
array $targetLines,
int $pageIndex = 0,
int $maxLines = self::MAX_DIFF_LINES,
): array

PdfDiffer::compare() extraheert de tekst per pagina en vergelijkt vervolgens pagina i van de bron met pagina i van het doel. Wanneer het aantal pagina’s verschilt, wordt de ontbrekende kant voor de overtollige pagina’s als lege tekst behandeld. Binnen elk paginapaar wordt de tekst op nieuwe regels gesplitst en draait er een Myers-regeldiff per pagina. De engine geeft Added-, Removed- en Unchanged-regio’s af. Een gewijzigde regel verschijnt als een Removed- plus een Added-regio; de geleverde engine geeft nooit Modified-tekstregio’s af. Het Modified-geval en de DiffResult::$modified-bucket dienen voor door de aanroeper geconstrueerde resultaten, omdat de constructor van DiffResult publiek is. totalChanges() telt toegevoegde, verwijderde en gewijzigde regio’s; ongewijzigde regio’s worden uitgesloten.

Extractie heeft twee paden:

  • Optionele Artisan-reader aanwezig. Wanneer de optionele klasse NextPDF\Parser\PdfReader geïnstalleerd is, worden content-streams van pagina’s er via gelezen voor pagina-nauwkeurige tekst. Het aantal pagina’s uit de trailer bepaalt de lus. Een pagina die niet gelezen kan worden, draagt lege tekst bij in plaats van de vergelijking af te breken.
  • Fallback. Een begrensde scanner op byteniveau lokaliseert stream/endstream-paren met strpos, pakt FlateDecode-data uit met een harde uitvoerlimiet van 50 MB, en keert een PNG-predictor terug wanneer de stream-dictionary daar via /DecodeParms om vraagt, conform ISO 32000-2:2020 §7.4.4.4. Een misvormde of niet-ondersteunde predictor laat de gedecodeerde bytes ongewijzigd. De fallback voegt alle herstelde tekst samen in één paginabucket, dus uitlijning op paginaniveau is alleen pagina-nauwkeurig op het readerpad.

Beide paden parsen de §9.4-tekstweergeefoperatoren Tj, TJ en '. De statusmachine houdt BT/ET, Tm (alleen oorsprong), Td/TD, T* en Tf bij.

StructuredDiffer::compare() draait de tekstdiff, groepeert opeenvolgende regio’s van hetzelfde type op dezelfde pagina tot alinea’s (ongewijzigde reeksen inbegrepen), draait vervolgens de afbeeldings- en metadatavergelijking en stelt een DiffSummary samen. De alineatellingen in de samenvatting dekken alleen toegevoegde, verwijderde en gewijzigde alinea’s.

Afbeeldingsvergelijking somt PDF-objecten structureel op. De omvang van een stream-body wordt bepaald door de bijbehorende /Length-entry conform §7.3.8.2, zodat binaire bytes die slechts op objectsyntaxis lijken, nooit als fantoomobjecten worden geregistreerd. Gecomprimeerde object-streams (/Type /ObjStm) worden gedecodeerd conform §7.5.7 zodat de daarin geneste afbeeldings-XObjects zichtbaar zijn. Elke gedetecteerde afbeelding wordt content-gehasht met de niet-cryptografische xxh128-functie; de identiteit is het paar van paginabucket en objectnummer. Afbeeldingen zonder eigenaarpagina in streamvolgorde worden aan pagina 0 toegewezen.

Metadatavergelijking herleidt de echte /Info-dictionary waar mogelijk via de trailer, zodat een lokkende veld-token binnen een content-stream niet wordt aangezien voor documentmetadata. Veldwaarden worden gedecodeerd als PDF-strings: de literale vorm conform §7.3.4.2 en de hexadecimale vorm conform §7.3.4.3. Zonder herleidbare trailer valt de zoekactie terug op de volledige invoer. Datums worden vergeleken als gedecodeerde strings, niet als geparsete timestamps.

DiffFormatter::toJson() retourneert pretty-printed JSON en encodeert met JSON_THROW_ON_ERROR, zodat een encoderingsfout een JsonException opgooit in plaats van false te retourneren. toHtml() retourneert een <div class="nextpdf-diff">-fragment; alineatekst en metadatawaarden gaan door HTML-entity-escaping. Er is geen visuele zij-aan-zij redline-PDF-uitvoer. Voor identieke invoer zijn de regio’s en de opgemaakte uitvoer deterministisch.

  • Pagina-uitlijning is positioneel. Een enkele ingevoegde of verwijderde pagina verschuift de uitlijning voor alle volgende pagina’s en blaast stroomafwaartse wijzigingstellingen op.
  • Op het fallback-extractiepad belandt alle tekst op paginaindex 0. Een via de reader geëxtraheerd document vergelijken met verwachtingen uit het fallbackpad levert een andere pagina-toewijzing op.
  • Een bron- of doelbuffer die niet met %PDF begint, faalt met InvalidArgumentException vóór enige vergelijking.
  • Meer dan 10,000 gecombineerde regels in één paginapaar faalt met OverflowException (regelaantalgrens).
  • Twee paginateksten die te weinig regels delen, falen met OverflowException zodra de Myers-edit-afstand de geheugengebonden limiet overschrijdt. Legitieme revisies delen de meeste regels en blijven onaangetast; vijandige invoer met weinig gemeenschappelijkheid activeert de grens.
  • Gedecomprimeerde fallback-stream-uitvoer groter dan 50 MB faalt met OverflowException (decompressiebom-grens). De scanner gebruikt strpos, geen onbegrensde regex, dus geprepareerde invoer kan geen catastrofaal backtracking veroorzaken.
  • De "-tekstweergeefoperator wordt getokeniseerd maar produceert geen tekstblok in 3.1.0; tekst die alleen via " wordt getoond, neemt niet deel aan de diff.
  • Gescande, alleen-afbeelding-PDF’s produceren weinig tot geen tekstdiff. Er draait geen OCR.
  • Detectie van afbeeldingswijzigingen is structureel, niet perceptueel. Het rasteriseert pagina’s niet, en een afbeelding die met identieke pixels opnieuw is geëncodeerd, wordt als gewijzigd gerapporteerd wanneer de bytes verschillen.
  • Een afbeelding waarvan de paginabucket of het objectnummer tussen revisies verandert, wordt gerapporteerd als een verwijderd-plus-toegevoegd-paar, niet als gewijzigd.
  • Object-streams die met andere filters dan FlateDecode zijn gecomprimeerd, worden fail-closed overgeslagen; hun onderdeel-afbeeldingen worden niet vergeleken.
  • In deze module vindt geen cryptografische bewerking plaats, dus er is geen FIPS-modusspecifiek gedrag. De afbeeldingshash is uitsluitend bedoeld voor wijzigingsdetectie en heeft geen integriteits- of bewijswaarde.
BeweringStandaardClausule
Tj- en TJ-tekstweergeefoperatoren worden geparsed voor extractieISO 32000-2:2020§9.4
Fallback-stream-data begint na de CRLF of LF die volgt op het stream-keywordISO 32000-2:2020§7.3.8.1
De omvang van gescande streams wordt bepaald door de /Length-entry van de dictionaryISO 32000-2:2020§7.3.8.2
Onderdelen van object-streams worden gelokaliseerd via de /N-paartabel en de /First-offsetISO 32000-2:2020§7.5.7
Het terugdraaien van de PNG-predictor volgt de /DecodeParms-parameter PredictorISO 32000-2:2020§7.4.4.4
Metadatawaarden decoderen de literale en hexadecimale stringvormenISO 32000-2:2020§7.3.4.2, §7.3.4.3
Visuele zij-aan-zij redline-PDF-uitvoerNiet ondersteund (alleen JSON/HTML)

Alle clausules zijn geparafraseerd; NextPDF reproduceert geen normatieve tekst. Dit zijn capaciteitsverklaringen, geen certificeringen; NextPDF bezit geen certificering en verleent er geen. Tekstherstel reconstrueert regeltekst uit tekstweergeefoperatoren. Het draait niet de volledige §9.4-tekststatusmachine, dus de diff is op contentniveau, niet op geometrieniveau.

  • Beschikbaarheid binnen het Pro-pakket: PdfDiffer, DiffEngine, TextExtractor en hun waardeobjecten sinds 1.8.0; StructuredDiffer, DiffFormatter, ImageDiffer, MetadataDiffer en die van hen sinds 2.2.0. Alle zijn actueel in nextpdf/pro 3.1.0.
  • Geef de voorkeur aan PdfDiffer::compareTexts() wanneer de paginatekst al beschikbaar is; het slaat extractie en de bijbehorende foutmodi volledig over.
  • De optionele Artisan-reader verbetert de extractienauwkeurigheid en pagina-toewijzing. Het wordt tijdens runtime gedetecteerd en is nooit vereist.
  • Vang OverflowException af bij het diffen van niet-vertrouwde invoer; de grenzen zijn bewuste fail-closed-afwijzingen, geen tijdelijke fouten.
  • DiffFormatter::toHtml() geeft klassenamen af (diff-added, diff-removed, diff-modified, diff-unchanged) maar geen stylesheet; lever je eigen CSS.
  • Construeer StructuredDiffer met stub-differs in tests om het tekstpad te isoleren van afbeeldings- en metadatascanning.

Deze pagina documenteert uitsluitend extern waarneembaar gedrag en het ondersteunde publieke API-oppervlak. Interne namespace-paden, helperklassen, mechanismetabellen, runbook-bestandsnamen en ticketprefixen vallen buiten de scope.