PDF/R, стандартизиран като ISO 23504-1, е PDF профилът за сканирани документи: всяка страница носи точно едно лентово изображение и нищо друго. PDFium Component го валидира от Delphi, Lazarus и C++Builder чрез ValidatePdfRCompliance, който чете поток и връща нивото на съответствие плюс набор от конкретни проблеми
Профилът съществува, защото скенери и системи за улавяне на документи се нуждаеха от цел, по-тясна от PDF/A. Архивен PDF може да съдържа всичко, което частта разрешава; растерен PDF е умишлено обеднен, така че всеки съответстващ четец може да го покаже идентично и всеки съответстващ писател може да го произведе от сканиране без двигател за авторство
Какво PDF/R забранява, което PDF/A разрешава?
Текст, на практика. Растерна страница носи сканираното изображение и нищо друго, така че ресурс за шрифт на страница е нарушение — отчитано като pvriFontForbidden по ISO 23504-1 §6.5.2. Това изненадва хората, които добавят невидим OCR текстови слой за търсене, което е нормално и полезно нещо за правене в работен процес на PDF/A и просто не е PDF/R
Отношението страница-към-изображение е еднакво строго. §6.5.1 прави всяка страница точно едно лентово изображение, така че pvriPageImageMismatch се задейства, когато броят на изображенията не съвпада с броя на страниците — страница без изображение и страница с две са и двете несъответстващи. А pvriBadMediaBox отчита страница, чиято MediaBox няма формата [0 0 w h] (§6.5.3), защото сканиране няма причина да седи на отместващ се произход
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;
Кои кодиране на изображения са разрешени
Четири, а белият списък е кратък по причина. §6.6 допуска /CCITTFaxDecode, /DCTDecode, /JPXDecode и /FlateDecode — двустъпален факс, JPEG, JPEG 2000 и беззагубно deflate, които помежду си покриват всеки изход от скенер, който има значение. Всичко друго се отчита като pvriForbiddenImageFilter, включително /LZWDecode, /RunLengthDecode, /ASCII85Decode, /ASCIIHexDecode, /JBIG2Decode и /Crypt
Два от тези отказа си струва да се разберат, а не да се запомнят. /JBIG2Decode компресира двустъпални сканирания изключително добре и е напълно легален в PDF/A, но неговата реконструкция на речник от символи може да замества визуално подобни глифове — документиран режим на отказ за сканирани цифри — а профил, чиято цяла цел е вярно растерно възпроизвеждане, не може да допусне този риск. ASCII филтрите са изключени по противоположната причина: те надуват файла, без да добавят каквото и да е, от което растерният профил се нуждае
Структурни правила, които се задействат преди която и да е страница да е прочетена
PDF/R ограничава и контейнера. pvriObjStmPresent отчита поток /Type /ObjStm, който профилът забранява изцяло — обектни потоци усложняват простия, последователен синтактичен разбор, който растерен четец е предназначен да може да извърши. pvriBadHeader отчита заглавка извън %PDF-1.4 до 1.7 и %PDF-2.0, а pvriEncryptVersionMismatch отчита криптиран файл, чиято заглавка не е %PDF-2.0, според §6.2.3
Каталогът и Info речникът са бели списъци, а не просто проверени. pvriProhibitedCatalogEntry и pvriProhibitedInfoEntry се задействат за записи извън разрешеното множество, а pvriInfoXmpMismatch се задейства, когато Info запис не е съгласен със своя XMP еквивалент. Липсващ поток /Metadata в каталога, липсващ /ID в trailer и отсъстващ маркер за долен колонтитул %PDF-raster-1.0 всеки имат свой собствен проблем също
Защо записът с опции за запис пропуска Title и Author
TPdfRSaveOptions носи Creator, Producer, CreationDate, ModDate, DocumentId и InstanceId и умишлено няма поле за Title, Author, Subject или Keywords. Тези четири са записите, които §6.4.3 забранява, така че запис, който ги излага, би канел извикващи да пишат несъответстващ файл през съответстващ API
Две булеви опции контролират изчистване при преобразуване на съществуващ PDF. StripInfoOptionalEntries е True по подразбиране и премахва Title, Author, Subject, Keywords и Trapped от изходния Info речник. StripCatalogOptionalEntries също е True по подразбиране и премахва Names, Outlines, StructTreeRoot, OutputIntents, Lang и останалите, оставяйки само белия списък от §6.3. Задайте което и да е на False и запазвате записите — а губите съответствие, което понякога е точно това, което извикващият наистина иска за вътрешен файл
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;
Забележете какво инжектирането на маркери не прави: то добавя метаданни и идентификация и не може да достави съдържание на страница. Изходна страница, която не носи лентово изображение, все още ще се провали с pvriPageImageMismatch след инжектиране, защото липсващото изображение никога не е било проблем на метаданни
Къде PDF/R се вписва в пайплайн за улавяне
Използвайте го там, където доставяемият продукт е самото сканиране и вярността е целият договор — доказателствено визуализиране, улавяне на чекове и плащания, архиви на инженерни чертежи от голямоформатни скенери. Използвайте PDF/A вместо него в момента, в който документът се нуждае от търсим текст, маркиране, вградени прикачени файлове или каквото и да е друго, което растерният профил отстранява
Често и работимо подреждане е да се произвеждат и двете: PDF/R оригинал, който никога не се променя, и PDF/A дериватив с OCR слой за извличане. Валидаторите са независими, така че същата партидна задача може да провери всеки артефакт срещу профила, който реално претендира. За архивната страна на тази двойка вижте записките за архивно съответствие с PDF/A и PDF/A предполетна валидация, а за печатно-ориентиран изход — ръководството за валидиране на печатно-готови PDF/X документи
PDFium Component докарва двигателя PDFium до Delphi, C++Builder и Lazarus с VCL API и валидатори за съответствие за PDF/A, PDF/X, PDF/E, PDF/UA и PDF/R — страницата на продукта PDFium Component изброява поддържаните стандарти и версии на IDE