Teknisk artikkel

Validering av PDF/raster-skannede dokumenter i Delphi

PDF/R, standardisert som ISO 23504-1, er PDF-profilen for skannede dokumenter: hver side bærer nøyaktig ett strimmel-bilde og ingenting annet. PDFium Component validerer den fra Delphi, Lazarus og C++Builder gjennom ValidatePdfRCompliance, som leser en strøm og returnerer konformansnivået pluss et sett konkrete problemer

Profilen finnes fordi skannere og dokument-fangst-systemer trengte et mål smalere enn PDF/A. En arkiv-PDF kan inneholde alt delen tillater; en raster-PDF er med vilje nedstrippet, slik at enhver konform leser kan vise den identisk og enhver konform forfatter kan produsere den fra en skanning uten en forfatter-motor

Hva forbyr PDF/R som PDF/A tillater?

Tekst, i praksis. En raster-side bærer det skannede bildet og ingenting annet, slik at en skrift-ressurs på en side er et brudd — rapportert som pvriFontForbidden under ISO 23504-1 §6.5.2. Det overrasker folk som legger til et usynlig OCR-tekst-lag for søkbarhet, noe som er en normal og nyttig ting å gjøre i en PDF/A-arbeidsflyt og rett og slett ikke er PDF/R

Forholdet mellom side og bilde er like strengt. §6.5.1 gjør hver side til nøyaktig ett strimmel-bilde, slik at pvriPageImageMismatch fyres når bilde-antallet ikke stemmer med side-antallet — en side uten bilde og en side med to er begge ikke-konforme. Og pvriBadMediaBox rapporterer en side hvis MediaBox ikke har formen [0 0 w h] (§6.5.3), fordi en skanning ikke har noen grunn til å sitte ved en forskyvnings-opprinnelse

uses FPdfPdfr;

var
  Src: TFileStream;
  Res: TPdfRValidationResult;
begin
  Src := TFileStream.Create('scan-batch-0142.pdf', fmOpenRead or fmShareDenyWrite);
  try
    Res := ValidatePdfRCompliance(Src);
    if Res.IsCompliant then
      Memo1.Lines.Add('PDF/R-1 conformant')
    else
    begin
      if pvriFontForbidden in Res.Issues then
        Memo1.Lines.Add('A page names a font resource; a raster page carries no text');
      if pvriPageImageMismatch in Res.Issues then
        Memo1.Lines.Add('Image count does not match page count');
      if pvriForbiddenImageFilter in Res.Issues then
        Memo1.Lines.Add('A strip image uses an encoding outside the white list');
    end;
  finally
    Src.Free;
  end;
end;

Hvilke bilde-kodinger som tillates

Fire, og den hvite listen er kort av en grunn. §6.6 innrømmer /CCITTFaxDecode, /DCTDecode, /JPXDecode og /FlateDecode — tokomma-faks, JPEG, JPEG 2000 og tapsfri deflate, som mellom dem dekker all skanner-utdata som betyr noe. Alt annet rapporteres som pvriForbiddenImageFilter, inkludert /LZWDecode, /RunLengthDecode, /ASCII85Decode, /ASCIIHexDecode, /JBIG2Decode og /Crypt

To av de avvisningene er verdt å forstå snarere enn å memorere. /JBIG2Decode komprimerer tokomma-skanninger ekstremt bra og er perfekt lovlig i PDF/A, men dens symbol-ordbok-rekonstruksjon kan erstatte visuelt like glyffer — en dokumentert feilmodus for skannede sifre — og en profil hvis hele formål er trofast raster-reproduksjon kan ikke innrømme den risikoen. ASCII-filterne ekskluderes av den motsatte grunnen: de blåser opp filen uten å legge til noe en raster-profil trenger

Strukturregler som fyres før noen som helst side leses

PDF/R begrenser også containeren. pvriObjStmPresent rapporterer en /Type /ObjStm-strøm, noe profilen forbyr utvetydig — objektstrømmer kompliserer den enkle, sekvensielle parsingen en raster-leser er ment å kunne utføre. pvriBadHeader rapporterer en header utenfor %PDF-1.4 til 1.7 og %PDF-2.0, og pvriEncryptVersionMismatch rapporterer en kryptert fil hvis header ikke er %PDF-2.0, ifølge §6.2.3

Katalogen og Info-ordboken er hvit-listet, ikke bare sjekket. pvriProhibitedCatalogEntry og pvriProhibitedInfoEntry fyres for oppføringer utenfor det tillatte settet, og pvriInfoXmpMismatch fyres når en Info-oppføring er uenig med sin XMP-ekvivalent. En manglende katalog /Metadata-strøm, en manglende trailer /ID og en fraværende %PDF-raster-1.0-bunntekst-merke har alle sitt eget problem også

Hvorfor utelater lagringsvalg-posten Title og Author

TPdfRSaveOptions bærer Creator, Producer, CreationDate, ModDate, DocumentId og InstanceId, og har med vilje ingen felt for Title, Author, Subject eller Keywords. De fire er oppføringene §6.4.3 forbyr, slik at en post som eksponerte dem ville invitere oppringere til å skrive en ikke-konform fil gjennom et konformt API

To boolske opsjoner styrer opprydding ved konvertering av en eksisterende PDF. StripInfoOptionalEntries er standardisert til True og fjerner Title, Author, Subject, Keywords og Trapped fra kilde-Info-ordboken. StripCatalogOptionalEntries er også standardisert til True og fjerner Names, Outlines, StructTreeRoot, OutputIntents, Lang og resten, og etterlater kun §6.3-hvitelisten. Sett en av dem til False og du beholder oppføringene — og taper konformans, noe som iblant er det en oppringer genuint ønsker for en intern fil

var
  Opts: TPdfRSaveOptions;
  Src, Dest: TFileStream;
begin
  Opts := TPdfRSaveOptions.Default;
  Opts.Creator := 'Capture Station 4';
  Opts.Producer := 'PDFium Component';
  Src := TFileStream.Create('scan-in.pdf', fmOpenRead or fmShareDenyWrite);
  try
    Dest := TFileStream.Create('scan-pdfr.pdf', fmCreate);
    try
      InjectPdfRMarkers(Src, Dest, Opts);   // markers + metadata, not page content
    finally
      Dest.Free;
    end;
  finally
    Src.Free;
  end;
end;

Merk hva merke-injeksjon ikke gjør: den legger til metadata og identifikasjon, og den kan ikke levere sideinnhold. En kilde-side som bærer intet strimmel-bilde vil fortsatt feile pvriPageImageMismatch etter injeksjon, fordi det manglende bildet aldri var et metadata-problem

Hvor PDF/R hører hjemme i en fangst-pipeline

Bruk det der leveransen er selve skanningen og trofasthet er hele kontrakten — bevis-avbildning, sjekk- og betalings-fangst, ingeniør-tegnings-arkiver fra en storformat-skanner. Bruk PDF/A i stedet i det øyeblikk dokumentet trenger søkbar tekst, merking, innebygde vedlegg eller noe annet raster-profilen stripper

En vanlig og brukbar ordning er å produsere begge: et PDF/R-original som aldri endres, og en PDF/A-derivat med et OCR-lag for gjenfinning. Validatorene er uavhengige, slik at den samme gruppe-jobben kan sjekke hvert artefakt mot profilen det faktisk krever. For arkivsiden av det paret, se notatene om PDF/A-arkiv-samsvar og PDF/A-preflight-validering, og for trykk-orientert utdata gjennomgangen av validering av trykk-klare PDF/X-dokumenter

PDFium Component bringer PDFium-motoren til Delphi, C++Builder og Lazarus med et VCL-API og konformans-validatorer for PDF/A, PDF/X, PDF/E, PDF/UA og PDF/R — PDFium Component-produktsiden lister de støttede standardene og IDE-versjonene