Technisch artikel

PDF/raster-gescande documenten valideren in Delphi

PDF/R, gestandaardiseerd als ISO 23504-1, is het PDF-profiel voor gescande documenten: elke pagina draagt precies één strookafbeelding en niets anders. PDFium Component valideert het vanuit Delphi, Lazarus en C++Builder via ValidatePdfRCompliance, dat een stream leest en het conformiteitsniveau retourneert plus een verzameling concrete issues

Het profiel bestaat omdat scanners en document-capture-systemen een doel nodig hadden dat smaller is dan PDF/A. Een archief-PDF mag alles bevatten wat het deel toestaat; een raster-PDF is opzettelijk verarmd, zodat elke conformerende reader het identiek kan weergeven en elke conformerende writer het vanuit een scan kan produceren zonder een ontwerp-engine

Wat verbiedt PDF/R dat PDF/A toestaat?

In de praktijk tekst. Een raster-pagina draagt de gescande afbeelding en niets anders, dus een font-resource op een pagina is een overtreding — gerapporteerd als pvriFontForbidden onder ISO 23504-1 §6.5.2. Dat verrast mensen die een onzichtbare OCR-tekstlaag toevoegen voor doorzoekbaarheid, wat in een PDF/A-workflow een normaal en nuttig ding is om te doen en simpelweg geen PDF/R is

De pagina-tot-afbeelding-relatie is even streng. §6.5.1 maakt elke pagina precies één strookafbeelding, dus pvriPageImageMismatch vuurt wanneer het afbeeldingsantal niet overeenkomt met het paginaantal — een pagina zonder afbeelding en een pagina met twee zijn beide niet-conform. En pvriBadMediaBox rapporteert een pagina waarvan de MediaBox niet de vorm [0 0 w h] heeft (§6.5.3), want een scan heeft geen reden om op een gepositioneerd nulpunt te staan

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;

Welke afbeeldingscoderingen zijn toegestaan

Vier, en de witte lijst is kort om een reden. §6.6 admitteert /CCITTFaxDecode, /DCTDecode, /JPXDecode en /FlateDecode — bilevel fax, JPEG, JPEG 2000 en lossless deflate, die samen elke scanner-uitvoer dekken die ertoe doet. Alles andere wordt gerapporteerd als pvriForbiddenImageFilter, inclusief /LZWDecode, /RunLengthDecode, /ASCII85Decode, /ASCIIHexDecode, /JBIG2Decode en /Crypt

Twee van die afwijzingen zijn de moeite waard om te begrijpen in plaats van te memoriseren. /JBIG2Decode comprimeert bilevel scans extreem goed en is volkomen legaal in PDF/A, maar zijn symboolwoordenboek-reconstructie kan visueel vergelijkbare glyphs substitueren — een gedocumenteerde faalmodus voor gescande cijfers — en een profiel waarvan het hele doel trouwe rasterreproductie is, kan dat risico niet admitteren. De ASCII-filters worden om de tegenovergestelde reden uitgesloten: ze zetten het bestand op zonder iets toe te voegen dat een rasterprofiel nodig heeft

Structuurregels die vuren vóór een pagina is gelezen

PDF/R beperkt ook de container. pvriObjStmPresent rapporteert een /Type /ObjStm-stream, die het profiel ronduit verbiedt — object-streams compliceren de eenvoudige, sequentiële parse die een raster-reader moet kunnen uitvoeren. pvriBadHeader rapporteert een header buiten %PDF-1.4 tot 1.7 en %PDF-2.0, en pvriEncryptVersionMismatch rapporteert een versleuteld bestand waarvan de header niet %PDF-2.0 is, per §6.2.3

Het catalog- en Info-dictionary worden wit-gelijst, niet slechts gecontroleerd. pvriProhibitedCatalogEntry en pvriProhibitedInfoEntry vuren voor entries buiten de toegestane verzameling, en pvriInfoXmpMismatch vuurt wanneer een Info-entry het oneens is met zijn XMP-equivalent. Een ontbrekende catalog-/Metadata-stream, een ontbrekende trailer-/ID en een afwezige %PDF-raster-1.0-voettekstmarker hebben elk hun eigen issue

Waarom de opslagopties-record Title en Author weglaat

TPdfRSaveOptions draagt Creator, Producer, CreationDate, ModDate, DocumentId en InstanceId, en heeft opzettelijk geen veld voor Title, Author, Subject of Keywords. Die vier zijn de entries die §6.4.3 verbiedt, dus een record dat ze ontsloot zou aanroepers uitnodigen een niet-conform bestand te schrijven door een conformerende API

Twee booleaanse opties besturen cleanup bij het converteren van een bestaande PDF. StripInfoOptionalEntries staat standaard op True en verwijdert Title, Author, Subject, Keywords en Trapped uit het Info-dictionary van de bron. StripCatalogOptionalEntries staat ook standaard op True en verwijdert Names, Outlines, StructTreeRoot, OutputIntents, Lang en de rest, waarbij alleen de witte lijst van §6.3 overblijft. Zet een van beide op False en je behoudt de entries — en verliest conformiteit, wat af en toe is wat een aanroeper voor een intern bestand werkelijk wil

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 op wat merker-injectie niet doet: het voegt metagegevens en identificatie toe, en het kan geen paginacontent leveren. Een bronpagina die geen strookafbeelding meedraagt, zal na injectie nog steeds falen op pvriPageImageMismatch, want de ontbrekende afbeelding was nooit een metagegevenprobleem

Waar PDF/R past in een capture-pijplijn

Gebruik het waar het leverbare de scan zelf is en fidelity het hele contract is — bewijsrechtige beeldvorming, cheques en remittance-capture, technische-tekeningarchieven vanuit een large-format-scanner. Gebruik in plaats daar PDF/A zodra het document doorzoekbare tekst, tagging, ingesloten bijlagen of iets anders nodig heeft dat het rasterprofiel weghaalt

Een algemene en werkbare regeling is om beide te produceren: een PDF/R-origineel dat nooit verandert, en een PDF/A-afgeleide met een OCR-laag voor retrieval. De validators zijn onafhankelijk, dus dezelfde batchtaak kan elk artefact controleren tegen het profiel dat het werkelijk claimt. Voor de archiefkant van dat paar, zie de notities over PDF/A-archiefconformiteit en PDF/A-preflight-validatie, en voor drukgerichte uitvoer de doorloop van drukklare PDF/X-documenten valideren

PDFium Component brengt de PDFium-engine naar Delphi, C++Builder en Lazarus met een VCL-API en conformiteitsvalidators voor PDF/A, PDF/X, PDF/E, PDF/UA en PDF/R — de PDFium Component-productpagina somt de ondersteunde standaarden en IDE-versies op