Techninis straipsnis

Skenuotų dokumentų PDF ir rastro PDF tikrinimas Delphi

PDF/R, standartizuotas kaip ISO 23504-1, yra PDF profilis skenuotiems dokumentams: kiekvienas puslapis neša lygiai vieną juostos paveikslą ir nieko daugiau. PDFium Component tikrina jį iš Delphi, Lazarus ir C++Builder per ValidatePdfRCompliance, kuris skaito srautą ir grąžina atitikties lygį plius konkretų problemų rinkinį

Profilis egzistuoja todėl, kad skaitytuvams ir dokumentų fiksavimo sistemoms reikėjo tikslo, siauresnio už PDF/A. Archyvinis PDF gali turėti bet ką, ką leidžia dalis; rastro PDF sąmoningai apverkamas, kad bet kuris atitinkamas skaitytuvas galėtų jį parodyti identiškai, o bet kuris atitinkamas rašytojas galėtų pagaminti jį iš nuskaitymo be autoravimo variklio

Ko PDF/R draudžia, ko PDF/A leidžia?

Tekstą, praktiškai. Rastro puslapis neša nuskaitytą paveikslą ir nieko daugiau, todėl šrifto išteklius puslapyje yra pažeidimas — pranešamas kaip pvriFontForbidden pagal ISO 23504-1 §6.5.2. Tai stebina žmones, kurie prideda nematomą OCR teksto sluoksnį paieškamumui, kas yra normalus ir naudingas dalykas PDF/A darbo eigoje ir tiesiog nėra PDF/R

Puslapio ir paveikslo ryšys yra lygiai toks pat griežtas. §6.5.1 padaro kiekvieną puslapį lygiai vienu juostos paveikslu, todėl pvriPageImageMismatch suveikia, kai paveikslų skaičius neatitinka puslapių skaičiaus — puslapis be paveikslo ir puslapis su dviem abu yra neatitinkantys. Ir pvriBadMediaBox praneša puslapį, kurio MediaBox neturi formos [0 0 w h] (§6.5.3), nes nuskaitymui nėra priežasties sėdėti poslinkio pradžioje

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;

Kurie paveikslų kodavimai leidžiami

Keturi, ir baltasis sąrašas trumpas dėl priežasties. §6.6 priima /CCITTFaxDecode, /DCTDecode, /JPXDecode ir /FlateDecode — dviliemenio fakso, JPEG, JPEG 2000 ir bepralaidžio glaudinimo, kurie tarp savęs padengia kiekvieną svarbų skaitytuvo išvestį. Viskas kita pranešama kaip pvriForbiddenImageFilter, įskaitant /LZWDecode, /RunLengthDecode, /ASCII85Decode, /ASCIIHexDecode, /JBIG2Decode ir /Crypt

Du iš tų atmetimų verti supratimo, o ne įsiminimo. /JBIG2Decode suspaudžia dvyliemenius nuskaitymus ypač gerai ir yra visiškai teisėtas PDF/A, bet jo simbolių žodyno rekonstrukcija gali pakeisti vizualiai panašius glyph — dokumentuotas trikties pobūdis skenuotiems skaitmenims — o profilis, kurio visas tikslas yra ištikimas rastro atvaizdavimas, negali tos rizikos pripažinti. ASCII filtrai išmetami priešinga priežastimi: jie išpūčia failą nepridėdami nieko, ko reikia rastro profiliui

Struktūros taisyklės, suveikiančios dar prieš skaitant bet kurį puslapį

PDF/R apriboja ir konteinerį. pvriObjStmPresent praneša apie /Type /ObjStm srautą, kurio profilis draudžia išvis — objektų srautai komplikuoja paprastą, nuoseklų analizę, kurią rastro skaitytuvas turi galėti atlikti. pvriBadHeader praneša antraštę už %PDF-1.4 iki 1.7 ir %PDF-2.0 ribų, o pvriEncryptVersionMismatch praneša šifruotą failą, kurio antraštė ne %PDF-2.0, pagal §6.2.3

Katalogas ir Info žodynas yra baltasis sąrašas, o ne tik tikrinami. pvriProhibitedCatalogEntry ir pvriProhibitedInfoEntry suveikia įrašams už leidžiamo rinkinio, o pvriInfoXmpMismatch suveikia, kai Info įrašas nesutampa su jo XMP atitikmeniu. Trūkstamas katalogo /Metadata srautas, trūkstamas trailer /ID ir nesamas %PDF-raster-1.0 poraštinis žymeklis kiekvienas turi savo problemą

Kodėl išsaugojimo parinkčių įrašas nepaisyklo Title ir Author

TPdfRSaveOptions neša Creator, Producer, CreationDate, ModDate, DocumentId ir InstanceId ir sąmoningai neturi lauko Title, Author, Subject ar Keywords. Tie keturi yra įrašai, kuriuos §6.4.3 draudžia, todėl įrašas, juos atskleidęs, kviestų kviesiančiuosius rašyti neatitinkantį failą per atitinkančią API

Dvi loginės parinktys valo išvalymą, kai konvertuojamas esamas PDF. StripInfoOptionalEntries numatytasis yra True ir pašalina Title, Author, Subject, Keywords ir Trapped iš šaltinio Info žodyno. StripCatalogOptionalEntries taip pat numatytasis yra True ir pašalina Names, Outlines, StructTreeRoot, OutputIntents, Lang ir likusius, palikdamas tik §6.3 baltąjį sąrašą. Nustatykite bet kurį į False ir išlaikote įrašus — ir prarandate atitiktį, kas kartais yra tai, ko kviesiantysis iš tikrųjų nori vidiniam failui

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;

Atkreipkite dėmesį, ko žymeklių injekcija nedaro: ji prideda metaduomenis ir identifikaciją, ir negali pateikti puslapio turinio. Šaltinio puslapis, nešantis be juostos paveikslo, vis tiek nepraeis pvriPageImageMismatch po injekcijos, nes trūkstamas paveikslas niekada nebuvo metaduomenų problema

Kur PDF/R tinka fiksavimo konvejeryje

Naudokite jį ten, kur pristatomasis produktas yra pats nuskaitymas ir ištikimumas yra visa sutartis — įrodymų vaizdavimas, čekių ir mokėjimų fiksavimas, inžinerijos brėžinių archyvai iš didelio formato skaitytuvo. Naudokite PDF/A vietoj to akimirksniu, kai dokumentui reikia ieškomo teksto, žymėjimo, įterptų priedų ar bet ko kito, ką rastro profilis nuplauna

Įprastas ir veikiantis sutvarkymas yra gaminti abu: PDF/R originalą, kuris niekada nesikeičia, ir PDF/A išvestinę su OCR sluoksniu paieškamumui. Validatoriai yra nepriklausomi, todėl tas pats paketinis darbas gali patikrinti kiekvieną artefaktą pagal profilį, kurį jis iš tikrųjų deklaruoja. Dėl to poros archyvinės pusės žr. PDF/A archyvinės atitikties ir PDF/A skrydžio prieš tai tikrinimo pastabas, o dėl spausdinimui orientuotos išvesties — spausdinimui paruoštų PDF/X dokumentų tikrinimo aprašymą

PDFium Component atveda PDFium variklį į Delphi, C++Builder ir Lazarus su VCL API ir atitikties validatoriais PDF/A, PDF/X, PDF/E, PDF/UA ir PDF/R — PDFium Component produkto puslapyje išvardyti palaikomi standartai ir IDE versijos