مقال تقني

فحص ألوان PDF/X-1a في HotPDF: كشف محتوى RGB في Delphi

حين يضبط PDFXCompliance على 'X-1a'، يتحقق HotPDF من لون المحتوى في آخر العمل تمامًا: يستدعي EndDoc ‏THotPDF.EnsurePDFX1aContentColorSpaces، التي ترفض أي محتوى DeviceRGB أو CalRGB أو RGB عبر ICCBased في أي مكان على أي صفحة وترفع استثناء يسمي المورد المخطئ. لن يكتب الملف أبدًا كمستند PDF/X-1a سيرجعه مطبعة

وهذا الجزء الأخير هو المغزى: ملف PDF/X-1a بشعار RGB شارد يبدو سليمًا تمامًا على الشاشة، ويمر مراجعة عابرة، ثم يفشل preflight عند المطبعة قبل يومين من موعد المطبعة. التقاطه في بناء Delphi الخاص بك، برسالة تخبرك أي صفحة وأي صورة، أرخص بكثير من اكتشافه من مشغل ما قبل طباعة غاضب

لماذا يرفض PDF/X-1a محتوى RGB؟

يرفض PDF/X-1a الـ RGB لأن الصيغة تعد بأن كل لون نهائي أصلًا لشرط طباعة CMYK محدد واحد. يحصر §6.2.3 من ISO 15930-1:2001 لون المحتوى في DeviceCMYK وDeviceGray ومرمزات الألوان المميزة (spot)، أي فضاءات Separation وDeviceN التي بدائلها CMYK أو Gray. ويُسمي OutputIntent ‏GTS_PDFX المضمَّن في الملف ذلك الشرط الطباعي، مثل FOGRA39 أوفست مصقول، ويحق لسير العمل المستقبل أن يرسل الأرقام مباشرة إلى الألواح دون أي تحويل لون

الـ RGB يكسر ذلك العقد: قيمة RGB تصف لونًا نسبة إلى شاشة عرض أو فضاء عمل، لا وصفة حبر، فيضطر أحد في المصب لقرر كيف يفصلها، وX-1a وجدت بالضبط لتنتزع ذلك القرار من المستقبل. ويصنف §8.6 من ISO 32000-1 فضاءات ألوان PDF في عائلات device وCIE-based وspecial، ويظهر أعضاء RGB في أكثر من عائلة: ‏DeviceRGB فضاء device، وCalRGB وICCBased ذات المركبات الثلاث CIE-based، وفضاء Indexed أو Separation يمكنه إخفاء أساس أو بديل RGB تحته. والفاحص الذي يبحث عن معامل rg فقط يفقد معظمها. كما تحفظ النسخة الأحدث PDF/X-1a:2003 (ISO 15930-4) قاعدة الألوان نفسها؛ وانتبه أن قيمة 'X-1a' في HotPDF تكتب تعريف PDF/X-1a:2001 في حزمة XMP

إن كان محتواك RGB حقًا ويجب أن يبقى كذلك، فـ X-1a هدف خاطئ. ويحصر HotPDF هذا الفحص في 'X-1a' وحدها، فلا تتأثر 'X-3' و'X-4' اللتان تسمحان بلون ICC-based ومعاير

ماذا يفحص EnsurePDFX1aContentColorSpaces فعلًا

تجمع EnsurePDFX1aContentColorSpaces وسمًا وقت الرسم مع مشية تكرارية على موارد كل صفحة، وتعمل آخرًا في بوابة PDF/X. يفرض EndDoc أولًا اشتراطات PDF/X العامة: يجب ضبط Title، ويجب أن يكون Trapped ‏'True' أو 'False' أو 'Unknown'، ويجب وجود OutputIntent ‏GTS_PDFX (‏EnsurePDFXOutputIntent)، وتحتاج كل صفحة TrimBox أو ArtBox (‏EnsurePDFXPageBoxes). وبعد اجتياز تلك فقط يعمل فحص الألوان

تسلسل بوابة PDF/X داخل EndDoc في HotPDF لـ Delphi: البيانات الوصفية وOutputIntent وصناديق الصفحات أولًا، ثم فحص لون محتوى RGB
فحص الألوان يعمل آخرًا في بوابة X-1a، ووسم وقت الرسم يعني أن RGB المرسوم قبل إسناد المطابقة لا يزال يلتقط

المسار الأول وسم على مستوى المستند: مسجلات ألوان RGB في HotPDF، وتضمين الصور النقطية، وإدخالات ألوان التعليقات، تسجل استخدام DeviceRGB وأنت ترسم، وهو ما يغطي معاملي rg وRG اللاصقين اللذين لا يظهران أبدًا في قاموس موارد. والمسار الثاني يمشي /Resources لكل صفحة ويفقدها:

  • فضاءات الألوان المسماة في /ColorSpace، بما فيها الاختصار RGB الخاص بالصور اللاصقة بوصفه مرادف DeviceRGB
  • ‏/ColorSpace لكل Image XObject
  • ‏Form XObjects وأنماط التبليط (tiling Patterns)، بالتكرار إلى /Resources المتداخلة الخاصة بها
  • أنماط التظليل وإدخالات قاموس /Shading للصفحة، عبر /ColorSpace الخاص بالتظليل
  • فضاءات أساس Indexed، وبدائل Separation وDeviceN، وفضاءات أساس Pattern، متتبعة إلى عمق تداخل 8

ثلاثة أشياء ترفض: DeviceRGB وCalRGB وفضاءات ICCBased التي يصرح profile stream الخاص بها بـ N = 3. وقواميس الموارد المتشاركة بين Form XObjects والأنماط تزور مرة واحدة، فمجموعة نماذج تشير لبعضها لا تدفع المشية في حلقة. والتابع عام على THotPDF، لكن في الاستخدام العادي لا تستدعيه بنفسك أبدًا، لأن EndDoc يفعله عنك

أين يختبئ RGB في موارد صفحات PDF: النماذج المتداخلة والأنماط والتظليلات والبدائل تقود مشية HotPDF في Delphi إلى DeviceRGB أو CalRGB أو RGB عبر ICCBased
تتتبع المشية الموارد المتداخلة إلى عمق 8 وترفض DeviceRGB وCalRGB وفضاءات ICCBased ذات N = 3 أينما ظهرت

رسم صفحة X-1a في Delphi تجتاز الفحص

مستند X-1a مطابق من HotPDF يحتاج OutputIntent ‏CMYK، وTrimBox على كل صفحة، ولونًا يضبط فقط عبر واجهات CMYK وGray والألوان المميزة. والهيكل أدناه يستخدم profile ‏FOGRA39؛ تأخذ AddPDFXOutputIntent معرف شرط الخرج، وسلسلة معلومات، وstream الـ ICC profile، وعدد مركباته، والفضاء البديل

var
  Pdf: THotPDF;
  Profile: TFileStream;
begin
  Pdf := THotPDF.Create(nil);
  try
    Pdf.FileName := 'brochure-x1a.pdf';
    Pdf.Title := 'Spring brochure, press edition';
    Pdf.Trapped := 'False';
    Pdf.PDFXCompliance := 'X-1a';
    Pdf.BeginDoc;

    Profile := TFileStream.Create('CoatedFOGRA39.icc', fmOpenRead or fmShareDenyWrite);
    try
      Pdf.AddPDFXOutputIntent('FOGRA39 (ISO 12647-2:2004)',
        'Coated FOGRA39 offset', Profile, 4, 'DeviceCMYK');
    finally
      Profile.Free;
    end;
    Pdf.CurrentPage.SetTrimBox(0, 0, 612, 792);   // إلزامي في كل صفحة

    Pdf.CurrentPage.SetCMYKFillColor(0, 0.5, 0.8, 0.1);
    Pdf.CurrentPage.Rectangle(72, 600, 468, 120);
    Pdf.CurrentPage.Fill;

    Pdf.CurrentPage.SetGrayFillColor(0.2);         // نص DeviceGray
    Pdf.CurrentPage.SetFont('Arial', [], 14);
    Pdf.CurrentPage.TextOut(72, 560, 0, 'Spring catalog, press edition');
    Pdf.EndDoc;                                    // فحص الألوان يعمل هنا
  finally
    Pdf.Free;
  end;
end;

كل استدعاء مبني على TColor مصيدة في هذا السياق: ‏SetRGBFillColor وSetRGBStrokeColor وSetRGBColor كلها تأخذ لون GDI وتصدر DeviceRGB، فروتين مساعد كتب قبل سنوات لتقارير موجهة للشاشة سيوسخ مهمة طباعة لحظة إعادة استخدامه. استخدم SetCMYKFillColor أو SetCMYKStrokeColor أو SetCMYKColor بمركبات في المدى من 0 إلى 1، أو ما يعادلها من Gray

الألوان المميزة وتدرجات CMYK

ترمزات الألوان المميزة مسموحة في X-1a ما دام بديلها CMYK أو Gray. يبني RegisterSeparation فضاء Separation ويعيد اسم موارده، ويختار RegisterAxialGradient فضاء ألوان التظليل من عدد المركبات التي تمررها، وأربعة مركبات تعني DeviceCMYK

var
  SpotCS, Ramp: AnsiString;
begin
  // حبر مميز ببناء CMYK تقريبي بديلًا له
  SpotCS := Pdf.RegisterSeparation('Corporate Red', 'DeviceCMYK',
    [0, 1, 0.8, 0.05]);
  Pdf.CurrentPage.SetFillColorSpace(SpotCS);
  Pdf.CurrentPage.SetFillColor([1.0]);           // ‏tint بنسبة 100%
  Pdf.CurrentPage.Rectangle(72, 420, 200, 80);
  Pdf.CurrentPage.Fill;

  // ‏4 مركبات لكل نقطة توقف: التظليل DeviceCMYK لا DeviceRGB
  Ramp := Pdf.RegisterAxialGradient(72, 300, 540, 300,
    [0, 0, 0, 0], [1, 0.6, 0, 0.2]);
  Pdf.CurrentPage.SetFillPattern(Ramp);
  Pdf.CurrentPage.Rectangle(72, 260, 468, 80);
  Pdf.CurrentPage.Fill;
end;

مرر ثلاثة مركبات إلى استدعاء التدرج نفسه فتحصل على تظليل DeviceRGB يرفضه امشٍ الموارد باسم نمط التظليل. والشيء نفسه يسري على Separation سجل بـ 'DeviceRGB' بديلًا له: اسم اللون المميز يبدو بريئًا، لكن المشية تتبع البديل وتجد RGB تحته. أما كيفية تركيب تلك الأحبار المميزة حين يعود viewer أو RIP إلى البديل فمغطاة في مقالة تصيير ألوان Separation وDeviceN المميزة في Delphi

الصور النقطية تحتاج الانضباط نفسه: يثبت HotPDF الصور النقطية المضغوطة بـ Flate على DeviceRGB، بينما يحفظ JPEG المضمَّن بـ icJpeg عدد مركباته، فـ JPEG ذو CMYK بأربعة مركبات أو JPEG بتدرج رمادي جيدة، وJPEG العادي ذو RGB ليس كذلك. حوّل الأعمال الفنية إلى profile المطبعة في مسار التصوير لديك قبل أن تصل إلى الـ PDF

لماذا لا ينقذ /DefaultRGB ملف PDF/X-1a؟

لا يساعد /DefaultRGB في X-1a لأن القاعدة معنية بما تستلمه المطبعة، لا بما إذا كان الـ RGB موصوفًا. وفي PDF/A يسمح HotPDF لـ RegisterDefaultColorSpace('DefaultRGB', ...) بابتلاع استخدام DeviceRGB: فحين يخط فضاء Default ألوان DeviceRGB إلى ICC profile، يصير المحتوى مستقلًا عن الجهاز ويقبله فحص اتصال PDF/A. والمطورون الذين مروا بذلك السير يميلون لتجربة الإصلاح نفسه هنا

تتجاهل EnsurePDFX1aContentColorSpaces ذلك الخطط عمدًا: قيمة RGB موصوفة ما تزال RGB، وOutputIntent الخاص بـ X-1a شرط طباعة CMYK، فيظل على أحد أن يحولها. وإن حفظت اختلافًا واحدًا بين الملفين الشخصيين للأرشفة والطباعة، فاجعله هذا: تسأل PDF/A هل اللون لا لبس فيه، وتسأل PDF/X-1a هل هو حبر أصلًا

ترتيب الرسم، وإعداد الصفحة الذي لا يحتسب

لأن الفحص يعمل عند EndDoc على محتوى كتب سلفًا، فترتيب إعدادك للأشياء لا يهم: الـ RGB المرسوم قبل إسناد PDFXCompliance، أو قبل تسجيل الـ OutputIntent، لا يزال يلتقط. وهذا مهم لكود يبني صفحات في روتينات مشتركة ويقرر profile الخرج متأخرًا، أحيانًا من إعداد مستخدم اختير بعد وجود نصف المستند

Pdf.BeginDoc;
// ... OutputIntent وTrimBox كما قبل ...
Pdf.CurrentPage.SetRGBFillColor(clRed);   // تابع قديم، يصدر DeviceRGB
Pdf.CurrentPage.Rectangle(72, 72, 200, 100);
Pdf.CurrentPage.Fill;

Pdf.PDFXCompliance := 'X-1a';             // قرر بعد الرسم
Pdf.EndDoc;                               // لا يزال يرفع: سجل DeviceRGB

لوسم وقت الرسم مصيدة واحدة تستحق المعرفة إن بنت فحصًا مشابهًا بنفسك: كل صفحة جديدة تهيأ بحالة رسومات سوداء عبر SetRGBColor(0) التي تصدر زوج 0 0 0 rg و0 0 0 RG، ولو سمح لتلك القوالب الجاهزة لإعداد الصفحة بضبط وسم DeviceRGB لبدت كل مستندات ملطخة بـ RGB، أمام هذا الفحص وفحص اتصال ألوان PDF/A معًا. يحفظ HotPDF الوسم ويعيده حول تلك التهيئة، فلا يحسب إلا اللون الذي ترسمه فعلًا

كيف تجد محتوى RGB حين يرفع EndDoc؟

اقرأ الموقع في بداية رسالة الاستثناء، فهو يخبرك أي المسارين وجد المشكلة. رسالة على شكل PDFXCompliance 'X-1a': <where> uses <what>، تتبعها إشارة ISO 15930-1 ونصيحة التحويل إلى CMYK أو Gray أو التبديل إلى X-3 أو X-4. يرفع المدقق Exception عادية عند أول مخالفة، فطابق على النص لا على صنف استثناء

تشريح استثناء RGB عند EndDoc في HotPDF على Delphi: وسم وقت الرسم يسجل الاستخدام على مستوى المستند بينما مشية الموارد تسمي الصفحة والمفتاح بالتحديد
اقرأ الموقع في بداية الرسالة — تقرير على مستوى المستند يرسلك إلى كود الرسم، واسم صفحة ومورد يشيران إلى مفتاح واحد
  • document content uses DeviceRGB (rg/RG operators, RGB images or annotation colours recorded during drawing) يعني أن وسم وقت الرسم انطلق: لا رقم صفحة، لأن الوسم على مستوى المستند ويفحص قبل المشية. ابحث في كود رسمك عن استدعاءات SetRGB* وصور نقطية مضغوطة بـ Flate وملفات RGB JPEG وألوان تعليقات TColor
  • page 3 image XObject /Im2 uses DeviceRGB content أو page 1 shading Pattern /P1 uses DeviceRGB content يأتي من مشية الموارد ويشير إلى مفتاح مورد محدد بالضبط
  • uses an ICCBased RGB colour space (N=3) بعد موقع ColorSpace /... هي النتيجة النموذجية لتسجيل profile ‏sRGB عبر RegisterICCProfile واختياره عبر SetFillColorSpace، وهو مسار لا يراه وسم وقت الرسم
  • المواقع المتداخلة تتراص سلسلة، مثل page 2 Form XObject /Fm1 ColorSpace /CS1، فتستطيع تتبع المسار من الصفحة نزولًا إلى المورد الذي يحمل فضاء RGB
try
  Pdf.EndDoc;
except
  on E: Exception do
  begin
    if Pos('X-1a', E.Message) > 0 then
      LogPrepressFailure(Pdf.FileName, E.Message);  // مسجل log الخاص بك
    raise;
  end;
end;

لأن أول مخالفة فقط تسجل، إصلاح مهمة بعدة مصادر RGB تكراري: أصلح، وأعد البناء، واقرأ الرسالة التالية. وفي المهام الدفعية يجدي تسجيل الرسالة كاملة لكل ملف وحفظ قائمة قصيرة بالمخطئين المعروفين، مثل صورة نقطية لشعار أو تابع رسوم بيانية لا يزال يأخذ TColor

موضع بوابة RGB في preflight الخاص بك

‏EnsurePDFX1aContentColorSpaces بوابة RGB موجهة تعمل داخل بنائك، وتقترن بـ preflight كامل لـ PDF/X-1a بدل استبداله. تغطي عائلات RGB، عبر مشية الموارد من /Resources لكل صفحة، وعبر وسم وقت الرسم الذي تحفظه مسجلات ألوان HotPDF لمعاملي rg وRG اللاصقين؛ وتتتبع فضاءات الألوان المتداخلة إلى عمق 8 كحارس ضد حلقات مشوهة، وتسجل أول مخالفة لكل EndDoc. وعائلات الألوان الأخرى مثل Lab أو CalGray شأن الفحص الكامل، فمرر الملف المنتهي عبر مدقق خارجي كجزء من بنائك لتحصل على حكم المطابقة الكامل. والصورة الأوسع لخرج المطابقة في دليل خرج PDF/A وPDF/X وPDF/UA مع HotPDF، وتوصيل مدقق في خط أنابيب غير مراقب مغطى في أتمتة فحوص preflight لـ PDF في Delphi

HotPDF مكوّن PDF أصلي للـ VCL لـ Delphi وC++Builder بخرج PDF/X وPDF/A وPDF/UA، وواجهات ألوان CMYK والألوان المميزة، ودعم ICC OutputIntent. والتفاصيل والترخيص وتنزيل التجربة على صفحة منتج مكوّن HotPDF لـ PDF في Delphi