콘텐츠로 이동
getnextpdf.com

Pro 에디션

Diff — 심층 참조

이 페이지는 NextPDF Pro diff 모듈 NextPDF\Pro\Diff에 대한 계약 수준의 참조입니다. 이 모듈은 두 PDF 문서를 비교하여 텍스트, 이미지, 메타데이터 변경을 보고합니다. PdfDiffer는 페이지 정렬된 Myers 라인 diff를 생성합니다. StructuredDiffer는 단락 그룹화, 이미지 비교, 메타데이터 비교를 추가합니다. DiffFormatter는 구조화된 결과를 JSON 또는 HTML 조각으로 직렬화합니다. 이 페이지는 공개 API, 관찰 가능한 동작 계약, 리소스 한계, 그리고 실패 모드를 명시합니다. 작업 지향적인 설정과 샘플은 Diff 기능 페이지에 있습니다.

이 기능은 NextPDF Pro(nextpdf/pro)에 포함되며 Pro 등급 라이선스 봉투로 활성화됩니다. 해당 자격이 없는 배포 환경은 이 기능의 클래스를 로드하지 않습니다. 에디션 비교 및 라이선스 받기.

이 모듈을 게이트하는 런타임 기능 플래그는 없습니다. diff 클래스는 nextpdf/pro가 설치되고 라이선스가 있으면 언제든지 사용할 수 있습니다.

SymbolParametersDefault behaviorReturnsThrows or fails withNotes
PdfDiffer::compare()string $sourcePdf, string $targetPdf페이지별 텍스트를 추출한 다음, 소스의 페이지 i를 대상의 페이지 i와 diff합니다DiffResult버퍼에 %PDF 헤더가 없거나 선택적 리더가 파싱에 실패하면 InvalidArgumentException; 리소스 한계에서 OverflowException정적 진입점
PdfDiffer::compareTexts()array $sourcePages, array $targetPages (각 list<string>)추출을 건너뛰고 미리 추출된 페이지 텍스트를 diff합니다DiffResult리소스 한계에서 OverflowException정적; 텍스트가 이미 준비된 경우 사용
PdfDiffer::extractText()string $contentStream하나의 원시 콘텐츠 스트림에서 텍스트 표시 연산자를 파싱합니다string— (내결함성; 파싱 불가능한 입력은 빈 문자열을 반환)정적
StructuredDiffer::__construct()?ImageDiffer $imageDiffer = null, ?MetadataDiffer $metadataDiffer = nullnull 인수는 기본 differ를 구성합니다테스트를 위한 생성자 주입
StructuredDiffer::compare()string $sourcePdf, string $targetPdf텍스트, 단락, 이미지, 메타데이터 비교를 실행한 다음 요약을 만듭니다StructuredDiffResult텍스트 경로에서 InvalidArgumentExceptionOverflowException을 전파합니다모듈 전체의 오케스트레이터
DiffFormatter::toJson()StructuredDiffResult $result보기 좋게 출력된 JSON 문서string인코딩 실패 시 JsonException
DiffFormatter::toHtml()StructuredDiffResult $result요약, 단락, 메타데이터 섹션이 있는 HTML 조각; 텍스트 값은 엔티티로 이스케이프됩니다string완전한 문서가 아닌 조각만
DiffFormatter::toArray()StructuredDiffResult $resulttoJson()을 뒷받침하는 직렬화 배열array<string, mixed>안정적인 snake_case 키
ImageDiffer::diff()string $sourcePdf, string $targetPdf이미지 XObject를 해시하여 추가, 제거, 수정된 이미지를 보고합니다list<ImageDiff>— (디코딩할 수 없는 구조는 실패 시 닫힘으로 건너뜀)식별자는 페이지 버킷과 객체 번호
MetadataDiffer::diff()string $sourcePdf, string $targetPdf여덟 개의 /Info 필드(Title, Author, Subject, Keywords, Creator, Producer, CreationDate, ModDate)를 비교합니다list<MetadataChange>— (비준수 입력에서도 절대 던지지 않음)값은 디코딩된 문자열로 비교됩니다
DiffEngine::diff()array $sourceLines, array $targetLines, int $pageIndex = 0, int $maxLines = 10000두 라인 목록에 대한 Myers 라인 difflist<DiffRegion>결합된 라인이 $maxLines를 초과하거나 편집 거리가 메모리 한계 상한을 초과하면 OverflowException정적; 모든 텍스트 경로의 영역 생성기
TextExtractor::fromContentStream()string $contentStream스트림을 토큰화하고 텍스트 상태 머신을 실행합니다list<TextBlock>정적
TextExtractor::fromOperations()array $operations (list<ContentStreamOp>)미리 파싱된 연산에 대해 텍스트 상태 머신을 실행합니다list<TextBlock>정적
ContentStreamParser::parse()생성자가 string $data를 받음연산자와 피연산자를 토큰화하고, 딕셔너리와 주석을 건너뛰며, 내결함성이 있습니다list<ContentStreamOp>인식되지 않는 바이트는 건너뛰며 절대 치명적이지 않음
ContentStreamOpstring $operator, list<mixed> $operands읽기 전용 연산 값 객체; isTextOp()가 텍스트 관련 연산자를 분류합니다
DiffResultlist<DiffRegion> $regions, int $sourcePagesCount, int $targetPagesCount영역을 $added, $removed, $modified로 버킷화; isIdentical(), hasDifferences(), totalChanges()를 노출합니다읽기 전용; Unchanged 영역은 $regions에만 남음
StructuredDiffResult텍스트 diff, 단락, 이미지, 메타데이터 변경, 요약집계 결과; hasDifferences(), isIdentical()는 요약에 위임합니다읽기 전용
DiffSummary카테고리별 개수와 페이지 개수텍스트, 이미지, 메타데이터 개수에 대한 hasDifferences()totalChanges()읽기 전용
DiffRegionDiffType $type, string $text, int $pageIndex, int $lineIndex, ?string $counterpartText = null하나의 라인 수준 변경$counterpartText는 출시된 엔진에서 null로 유지됨
ParagraphDiff타입, 텍스트, 페이지 인덱스, 시작/끝 라인, 영역한 페이지에서 연속된 동일 타입 영역; lineCount()읽기 전용
ImageDiff타입, 페이지 인덱스, 소스 해시, 대상 해시, 객체 id하나의 이미지 변경 항목해시는 부재하는 쪽에서 빈 문자열
MetadataChangestring $field, ?string $sourceValue, ?string $targetValue하나의 필드 변경; isAdded(), isRemoved(), isModified()null은 필드가 부재함을 의미
TextBlock텍스트, x, y, 폰트 이름, 폰트 크기, 라인 인덱스근사 위치를 가진 하나의 추출된 텍스트 실행읽기 전용
DiffTypeenum: Added, Removed, Modified, Unchanged텍스트에 대한 문자열 기반 변경 분류동작 계약의 Modified 참고 사항을 참조
ImageDiffTypeenum: Added, Removed, Modified, Unchanged이미지에 대한 문자열 기반 변경 분류
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()는 페이지별 텍스트를 추출한 다음, 소스의 페이지 i를 대상의 페이지 i와 diff합니다. 페이지 수가 다르면 초과 페이지에 대해 부족한 쪽은 빈 텍스트로 취급됩니다. 각 페이지 쌍 안에서 텍스트는 줄바꿈 단위로 나뉘고 페이지마다 Myers 라인 diff가 실행됩니다. 엔진은 Added, Removed, Unchanged 영역을 방출합니다. 변경된 라인은 Removed 하나와 Added 하나로 나타나며, 출시된 엔진은 Modified 텍스트 영역을 절대 방출하지 않습니다. Modified 케이스와 DiffResult::$modified 버킷은 DiffResult 생성자가 공개되어 있으므로 호출자가 구성한 결과를 위한 것입니다. totalChanges()는 추가, 제거, 수정 영역을 세며, 변경되지 않은 영역은 제외됩니다.

추출에는 두 가지 경로가 있습니다.

  • 선택적 Artisan 리더 존재. 선택적 NextPDF\Parser\PdfReader 클래스가 설치되어 있으면, 페이지 콘텐츠 스트림은 페이지 정확도가 높은 텍스트를 위해 이를 통해 읽힙니다. 트레일러의 페이지 수가 루프를 주도합니다. 읽기에 실패한 페이지는 비교를 중단하는 대신 빈 텍스트를 기여합니다.
  • 폴백. 한계가 설정된 바이트 수준 스캐너가 strposstream/endstream 쌍을 찾고, 하드 50 MB 출력 상한으로 FlateDecode 데이터를 인플레이트하며, 스트림 딕셔너리가 /DecodeParms를 통해 요청하면 ISO 32000-2:2020 §7.4.4.4에 따라 PNG 예측기를 역필터링합니다. 잘못되었거나 지원되지 않는 예측기는 디코딩된 바이트를 변경하지 않고 남겨둡니다. 폴백은 복원된 모든 텍스트를 단일 페이지 버킷으로 연결하므로, 페이지 수준 정렬은 리더 경로에서만 페이지 정확도를 갖습니다.

두 경로 모두 §9.4 텍스트 표시 연산자 Tj, TJ, '를 파싱합니다. 상태 머신은 BT/ET, Tm(원점만), Td/TD, T*, Tf를 추적합니다.

StructuredDiffer::compare()는 텍스트 diff를 실행하고, 같은 페이지에서 연속된 동일 타입 영역을 단락으로 묶은 다음(변경되지 않은 실행 포함), 이미지와 메타데이터 비교를 실행하고 DiffSummary를 조립합니다. 요약 단락 개수는 추가, 제거, 수정된 단락만 포함합니다.

이미지 비교는 PDF 객체를 구조적으로 열거합니다. 스트림 본문의 범위는 §7.3.8.2에 따라 /Length 항목이 관장하므로, 단지 객체 구문처럼 보이는 이진 바이트는 팬텀 객체로 등록되지 않습니다. 압축된 객체 스트림(/Type /ObjStm)은 §7.5.7에 따라 디코딩되어 그 안에 중첩된 이미지 XObject가 보이도록 합니다. 감지된 각 이미지는 비암호학적 xxh128 함수로 콘텐츠 해시되며, 식별자는 페이지 버킷과 객체 번호의 쌍입니다. 스트림 순서상 소유 페이지가 없는 이미지는 페이지 0에 귀속됩니다.

메타데이터 비교는 가능한 경우 트레일러를 통해 실제 /Info 딕셔너리를 해석하므로, 콘텐츠 스트림 내부의 미끼 필드 토큰이 문서 메타데이터로 오인되지 않습니다. 필드 값은 PDF 문자열로 디코딩됩니다: §7.3.4.2에 따른 리터럴 형식과 §7.3.4.3에 따른 16진수 형식. 해석 가능한 트레일러가 없으면 검색은 전체 입력으로 폴백합니다. 날짜는 파싱된 타임스탬프가 아니라 디코딩된 문자열로 비교됩니다.

DiffFormatter::toJson()은 보기 좋게 출력된 JSON을 반환하고 JSON_THROW_ON_ERROR로 인코딩하므로, 인코딩 실패 시 false를 반환하는 대신 JsonException을 발생시킵니다. toHtml()<div class="nextpdf-diff"> 조각을 반환하며, 단락 텍스트와 메타데이터 값은 HTML 엔티티 이스케이프를 거칩니다. 좌우 나란히 보여주는 시각적 레드라인 PDF 출력은 없습니다. 동일한 입력에 대해 영역과 형식화된 출력은 결정론적입니다.

  • 페이지 정렬은 위치 기반입니다. 페이지 하나가 삽입되거나 삭제되면 이후 모든 페이지의 정렬이 어긋나고 다운스트림 변경 개수가 부풀려집니다.
  • 폴백 추출 경로에서는 모든 텍스트가 페이지 인덱스 0에 놓입니다. 리더로 추출한 문서를 폴백 경로의 기대값과 diff하면 페이지 귀속이 달라집니다.
  • %PDF로 시작하지 않는 소스 또는 대상 버퍼는 어떤 비교보다 먼저 InvalidArgumentException으로 실패합니다.
  • 하나의 페이지 쌍에서 결합된 라인이 10,000개를 초과하면 OverflowException으로 실패합니다(라인 수 한계).
  • 두 페이지 텍스트가 공유하는 라인이 너무 적으면 Myers 편집 거리가 메모리 한계 상한을 초과하는 순간 OverflowException으로 실패합니다. 정당한 개정은 대부분의 라인을 공유하므로 영향을 받지 않으며, 적대적인 저공통성 입력이 한계를 건드립니다.
  • 압축 해제된 폴백 스트림 출력이 50 MB보다 크면 OverflowException으로 실패합니다(압축 해제 폭탄 한계). 스캐너는 한계가 없는 정규식이 아니라 strpos를 사용하므로, 조작된 입력이 파국적 백트래킹을 유발할 수 없습니다.
  • " 텍스트 표시 연산자는 3.1.0에서 토큰화되지만 텍스트 블록을 생성하지 않습니다. "를 통해서만 표시된 텍스트는 diff에 참여하지 않습니다.
  • 스캔된 이미지 전용 PDF는 텍스트 diff가 거의 또는 전혀 생성되지 않습니다. OCR은 실행되지 않습니다.
  • 이미지 변경 감지는 지각적이 아니라 구조적입니다. 페이지를 래스터화하지 않으며, 동일한 픽셀로 재인코딩된 이미지도 바이트가 다르면 수정된 것으로 보고됩니다.
  • 개정 사이에 페이지 버킷이나 객체 번호가 바뀐 이미지는 수정이 아니라 제거-더하기-추가 쌍으로 보고됩니다.
  • FlateDecode 이외의 필터로 압축된 객체 스트림은 실패 시 닫힘으로 건너뛰며, 그 멤버 이미지는 비교되지 않습니다.
  • 이 모듈에서는 어떠한 암호화 연산도 발생하지 않으므로, FIPS 모드 특정 동작은 없습니다. 이미지 해시는 변경 감지만을 위한 것이며 무결성이나 증거적 가치를 지니지 않습니다.
ClaimStandardClause
TjTJ 텍스트 표시 연산자가 추출을 위해 파싱됨ISO 32000-2:2020§9.4
폴백 스트림 데이터는 stream 키워드 뒤의 CRLF 또는 LF 다음부터 시작됨ISO 32000-2:2020§7.3.8.1
이미지 스캔 스트림 범위는 딕셔너리 /Length 항목이 관장함ISO 32000-2:2020§7.3.8.2
객체 스트림 멤버는 /N 쌍 테이블과 /First 오프셋을 통해 위치가 결정됨ISO 32000-2:2020§7.5.7
PNG 예측기 역변환은 /DecodeParmsPredictor 매개변수를 따름ISO 32000-2:2020§7.4.4.4
메타데이터 값은 리터럴 및 16진수 문자열 형식을 디코딩함ISO 32000-2:2020§7.3.4.2, §7.3.4.3
좌우 나란히 보여주는 시각적 레드라인 PDF 출력지원 안 함(JSON/HTML만)

모든 조항은 의역되었으며, NextPDF는 규범 텍스트를 재현하지 않습니다. 이들은 인증이 아니라 기능 진술입니다. NextPDF는 어떠한 인증도 보유하지 않으며 어떠한 인증도 부여하지 않습니다. 텍스트 복원은 텍스트 표시 연산자로부터 라인 텍스트를 재구성합니다. 전체 §9.4 텍스트 상태 머신을 실행하지 않으므로, diff는 기하 수준이 아니라 콘텐츠 수준입니다.

  • Pro 패키지 내 가용성: PdfDiffer, DiffEngine, TextExtractor와 그 값 객체는 1.8.0부터; StructuredDiffer, DiffFormatter, ImageDiffer, MetadataDiffer와 그 값 객체는 2.2.0부터. 모두 nextpdf/pro 3.1.0에서 최신입니다.
  • 페이지 텍스트가 이미 준비된 경우 PdfDiffer::compareTexts()를 선호하세요. 추출과 그 실패 모드를 전부 건너뜁니다.
  • 선택적 Artisan 리더는 추출 정확도와 페이지 귀속을 개선합니다. 런타임에 감지되며 절대 필수는 아닙니다.
  • 신뢰할 수 없는 입력을 diff할 때 OverflowException을 잡으세요. 이 한계들은 일시적 오류가 아니라 의도적인 실패 시 닫힘 거부입니다.
  • DiffFormatter::toHtml()은 클래스 이름(diff-added, diff-removed, diff-modified, diff-unchanged)을 방출하지만 스타일시트는 방출하지 않습니다. 자체 CSS를 제공하세요.
  • 테스트에서 텍스트 경로를 이미지 및 메타데이터 스캔에서 격리하려면 스텁 differ로 StructuredDiffer를 구성하세요.

이 페이지는 외부에서 관찰 가능한 동작과 지원되는 공개 API 표면만 문서화합니다. 내부 네임스페이스 경로, 헬퍼 클래스, 메커니즘 테이블, 런북 파일명, 티켓 접두사는 범위를 벗어납니다.