مقاله فنی

اعتبارسنجی اسناد اسکن‌شده PDF/raster در Delphi

PDF/R، استانداردشده به‌عنوان ISO 23504-1، profile برای PDF اسناد اسکن‌شده است: هر صفحه دقیقاً یک تصویر نوار حمل می‌کند و هیچ‌چیز دیگر. جزء PDFium آن را از Delphi، Lazarus و C++Builder از طریق ValidatePdfRCompliance اعتبارسنجی می‌کند، که یک stream می‌خواند و سطح انطباق به‌اضافه مجموعه‌ای از مسائل ملموس را برمی‌گرداند

profile وجود دارد چون پویشگرها و سیستم‌های ضبط سند به هدفی باریک‌تر از PDF/A نیاز داشتند. یک PDF آرشیوی ممکن است هر چیزی که بخش اجازه می‌دهد در خود داشته باشد؛ یک PDF raster عمداً فقیر است، تا هر خواننده سازگار آن را یکسان نمایش دهد و هر نویسنده سازگار آن را از یک اسکن بدون یک موتور تألیف تولید کند

PDF/R چه چیزی را ممنوع می‌کند که PDF/A اجازه می‌دهد؟

در عمل، متن. یک صفحه raster تصویر اسکن‌شده را حمل می‌کند و هیچ‌چیز دیگر، پس یک منبع فونت روی یک صفحه نقض است — به‌عنوان pvriFontForbidden تحت ISO 23504-1 §6.5.2 گزارش می‌شود. این افرادی را که یک لایه متن OCR نامرئی برای قابلیت جستجو اضافه می‌کنند غافلگیر می‌کند، که یک کار معمول و مفید در یک workflow PDF/A است و ساده PDF/R نیست

رابطه صفحه به تصویر به همان شدت است. §6.5.1 هر صفحه را دقیقاً یک تصویر نوار می‌کند، پس pvriPageImageMismatch شلیک می‌کند وقتی شمار تصویر با شمار صفحه مطابقت ندارد — صفحه‌ای با هیچ تصویر و صفحه‌ای با دو تصویر هر دو ناسازگار هستند. و pvriBadMediaBox صفحه‌ای را گزارش می‌دهد که MediaBox آن فرم [0 0 w h] ندارد (§6.5.3)، چون یک اسکن هیچ دلیلی برای نشستن در یک مبدأ offset ندارد

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 را می‌پذیرد — fax دوباینری، JPEG، JPEG 2000 و deflate بدون خطا، که میان خودشان هر خروجی پویشگری که اهمیت دارد را پوشش می‌دهند. هر چیز دیگر به‌عنوان pvriForbiddenImageFilter گزارش می‌شود، شامل /LZWDecode، /RunLengthDecode، /ASCII85Decode، /ASCIIHexDecode، /JBIG2Decode و /Crypt

دو مورد از آن رد‌ها ارزش فهمیدن دارند نه حفظ‌کردن. /JBIG2Decode اسکن‌های دوباینری را به‌شدت فشرده می‌کند و در PDF/A کاملاً قانونی است، اما بازسازی دیکشنری نمادش می‌تواند گلیف‌های به‌نظر‌مشابه را جایگزین کند — یک حالت شکست مستند برای ارقام اسکن‌شده — و profileی که کل هدفش تولید raster صادقانه است نمی‌تواند آن خطر را بپذیرد. فیلترهای ASCII به دلیل مخالف مستثنی شده‌اند: آن‌ها فایل را بدون اضافه‌کردن چیزی که یک profile raster نیاز دارد باد می‌کنند

قواعد ساختار که قبل از خوانده‌شدن هر صفحه‌ای شلیک می‌کنند

PDF/R container را نیز محدود می‌کند. pvriObjStmPresent یک stream /Type /ObjStm را گزارش می‌دهد، که profile آن را صریح ممنوع می‌کند — object streamها parse ساده و متوالی را که یک خواننده raster قرار است بتواند انجام دهد پیچیده می‌کنند. pvriBadHeader سرآینری خارج از %PDF-1.4 تا 1.7 و %PDF-2.0 را گزارش می‌دهد، و pvriEncryptVersionMismatch فایل رمزنگاری‌شده‌ای را که سرآیندش %PDF-2.0 نیست گزارش می‌دهد، طبق §6.2.3

کاتالوگ و دیکشنری Info لیست سفید هستند، نه صرفاً بررسی‌شده. pvriProhibitedCatalogEntry و pvriProhibitedInfoEntry برای entryهای خارج از مجموعه مجاز شلیک می‌کنند، و pvriInfoXmpMismatch شلیک می‌کند وقتی یک entry Info با معادل XMP خود مخالف است. یک stream /Metadata کاتالوگ مفقود، یک /ID trailer مفقود و یک نشانگر پاصفحه %PDF-raster-1.0 غایب هر کدام مسئله خودشان را دارند

چرا رکورد گزینه‌های ذخیره Title و Author را حذف می‌کند

TPdfRSaveOptions Creator، Producer، CreationDate، ModDate، DocumentId و InstanceId را حمل می‌کند، و عمداً هیچ فیلدی برای Title، Author، Subject یا Keywords ندارد. آن چهار entryهایی هستند §6.4.3 ممنوع می‌کند، پس رکوردی که آن‌ها را افشا می‌کرد فراخواننده‌ها را به نوشتن فایل ناسازگار از طریق API سازگار دعوت می‌کرد

دو گزینه boolean پاک‌سازی هنگام تبدیل یک PDF موجود را کنترل می‌کنند. StripInfoOptionalEntries پیش‌فرض True و Title، Author، Subject، Keywords و Trapped را از دیکشنری Info منبع حذف می‌کند. StripCatalogOptionalEntries نیز پیش‌فرض True و Names، Outlines، StructTreeRoot، OutputIntents، Lang و بقیه را حذف می‌کند، و فقط لیست سفید §6.3 را باقی می‌گذارد. هر یک را روی False تنظیم کنید و entryها را نگه می‌دارید — و انطباق را از دست می‌دهید، که گاهی همان چیزی است یک فراخواننده واقعاً برای یک فایل داخلی می‌خواهد

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;

توجه کنید تزریق marker چه کار نمی‌کند: فراداده و شناسایی اضافه می‌کند، و نمی‌تواند محتوای صفحه فراهم کند. یک صفحه منبع که هیچ تصویر نوار حمل نمی‌کند هنوز پس از تزریق pvriPageImageMismatch شکست می‌خورد، چون تصویر مفقود هرگز یک مسئله فراداده نبود

PDF/R در یک pipeline ضبط کجا جای می‌گیرد

از آن جایی استفاده کنید که deliverable خود اسکن است و وفاداری کل قرارداد است — تصویربرداری شواهدی، ضبط چک و واریز، آرشیو نقشه‌های مهندتی از یک پویشگر فرمت بزرگ. به‌جای آن از PDF/A لحظه‌ای که سند به متن قابل‌جستجو، نشانه‌گذاری، پیوست‌های جاسازی‌شده یا هر چیز دیگری که profile raster حذف می‌کند نیاز دارد استفاده کنید

ترتیبی رایج و کارآمد تولید هر دو است: یک PDF/R اصلی که هرگز تغییر نمی‌کند، و یک مشتق PDF/A با یک لایه OCR برای بازیابی. اعتبارسنج‌ها مستقل‌اند، پس همان کار دسته‌ای می‌تواند هر artifact را در برابر profileی که واقعاً ادعا می‌کند بررسی کند. برای جانب آرشیوی آن جفت، یادداشت‌های انطباق آرشیوی PDF/A و اعتبارسنجی preflight برای PDF/A را ببینید، و برای خروجی چاپ‌محور مرور اعتبارسنجی اسناد آماده چاپ PDF/X

جزء PDFium موتور PDFium را به Delphi، C++Builder و Lazarus با یک API VCL و اعتبارسنج‌های انطباق برای PDF/A، PDF/X، PDF/E، PDF/UA و PDF/R می‌آورد — صفحه محصول جزء PDFium استانداردهای پشتیبانی‌شده و نسخه‌های IDE را فهرست می‌کند