مقاله فنی

رندر گرادیان‌های PDF در دلفی: محوری و شعاعی

یک فایل PDF که هدر آن دارای یک پس‌زمینه گرادیان با استایل Word یا Excel بود، در هنگام رندر شدن به یک تصویر، با یک مستطیل سفید خالی در جایی که ترکیب رنگ باید باشد بازگردانده می‌شد. رندرکننده صفحه HotPDF اکنون از اپراتور PDF sh (سایه‌روشن) برای گرادیان‌های محوری نوع ۲ (Type 2 axial) و شعاعی نوع ۳ (Type 3 radial) پشتیبانی می‌کند: این متد تابع سایه‌روشن را در امتداد محور گرادیان ارزیابی کرده و ترکیب رنگ را رسم می‌نماید، در حالی که نسخه‌های قبلی بدون هیچ هشداری این اپراتور را نادیده می‌گرفتند و آن ناحیه را سفید باقی می‌گذاشتند. دو نوع سایه‌روشن که تقریباً تمام گرادیان‌های اسناد اداری را پوشش می‌دهند اضافه شده‌اند؛ انواع مش (mesh) پشتیبانی نمی‌شوند، و این مقاله به طور واقعی نشان می‌دهد که این مرز در کجا قرار دارد

چرا یک گرادیان PDF به عنوان یک کادر سفید رندر می‌شود؟

یک گرادیان PDF یک ساختار برداری است، نه یک بیت‌مپ که رندرکننده بتواند آن را ترسیم کند. یک دیکشنری سایه‌روشن (استاندارد ISO 32000-1 §8.7.4.5) هندسه — یک محور یا جفتی از دایره‌ها در آرایه Coords — به اضافه یک تابع رنگ را توصیف می‌کند، و اپراتور sh آن سایه‌روشن را در سراسر ناحیه برش فعلی رسم می‌نماید، یعنی همان مدل گرافیکی که HotPDF در زمان رسم مسیرها و پر کردن بوم صفحه ارائه می‌دهد. رندرکننده صفحه HotPDF جریان محتوا را اپراتور به اپراتور پیمایش می‌کند و از هر اپراتوری که مسیر کدی برای آن ندارد چشم‌پوشی می‌نماید تا بقیه صفحه همچنان رندر شود. قبل از نسخه v2.335.0, اپراتور sh در آن مجموعه نادیده گرفته‌شده قرار داشت: یک گرادیان هدر یا تمام‌صفحه هیچ کمکی به خروجی نمی‌کرد، بنابراین پس‌زمینه به صورت سفید نشان داده می‌شد. فایل هرگز خراب نبود. رندرکننده به سادگی هیچ هندلری برای آن اپراتور نداشت، و یک کادر سفید دقیقاً همان چیزی است که یک هندلر مفقود به نظر می‌رسد

زنجیره ارزیابی تابع در پس یک سایه‌روشن

یک سایه‌روشن تا زمانی که تابع آن ارزیابی نشود قابل ترسیم نیست، بنابراین آن مکانیزم باید ابتدا آماده می‌شد. سایه‌روشن‌های محوری نوع ۲ و شعاعی نوع ۳ هر دو حاوی یک /Function هستند که یک موقعیت پارامتریک در امتداد گرادیان را به یک رنگ نگاشت می‌کند (ISO 32000-1 §7.10)، و ارزیاب تابع HotPDF نوع FunctionType را حل کرده و آن را ارسال می‌نماید. درون‌یابی نمایی نوع ۲ (§7.10.3) مقدار C0 + t^N * (C1 - C0) را با محدود کردن Domain و Range محاسبه می‌کند؛ توابع نمونه‌برداری‌شده نوع ۰ (§7.10.2) شبکه‌ای از نمونه‌های ۸، ۱۶ یا ۳۲ بیتی را می‌خوانند و نزدیک‌ترین را از طریق نقشه Encode انتخاب می‌کنند، موردی که به طور دقیق در راهنمای ما درباره جستجوی رنگ نمونه‌برداری‌شده نوع ۰ پوشش داده شده است؛ توابع اتصال‌دهنده نوع ۳ (§7.10.4) یک زیرتابع را با آرایه Bounds انتخاب کرده و در آن بازگشت می‌کنند. توابع ماشین حساب پست‌اسکریپت نوع ۴ (§7.10.5) ارزیابی نمی‌شوند — آنها به جای رنگ اشتباه، با وضعیت شکست مواجه می‌گردند که با سیاست محافظه‌کارانه HotPDF در مسیر رندر مطابقت دارد. این ارزیاب در نسخه v2.334.0، یک نسخه قبل از خود اپراتور ارائه شد، زیرا رنگ‌آمیز سایه‌روشن فقط به اندازه تابع زیرین خود خوب عمل می‌کند

چگونه HotPDF یک گرادیان پیوسته را به پیکسل تبدیل می‌کند؟

ابزار HotPDF ترکیب پیوسته را با یک اجرای محدود از باندهای رنگی توپر تخمین می‌زند. رنگ‌آمیز سایه‌روشن محور گرادیان را پیمایش می‌کند، آن را به حداکثر ۶۴ باند تقسیم می‌نماید — که وقتی محور در پیکسل‌های دستگاه کوتاه باشد کمتر است — تابع را در موقعیت پارامتریک هر باند ارزیابی می‌کند، و یک مستطیل عمود بر محور را با یک قلم‌موی توپر پر می‌نماید. موازنه در اینجا بین تعداد باند و نرمی تصویر است: باندهای بیشتر ترکیب را دقیق‌تر دنبال می‌کنند اما هزینه پر کردن بیشتری دارند، و ۶۴ سقف در نظر گرفته شده است. از آنجا که تعداد باندها با طول محور در پیکسل‌های دستگاه مقیاس‌بندی می‌شود، وضوح تصویر اهمیت دارد. رندر کردن همان صفحه با DPI بالاتر محور را طولانی‌تر می‌کند، بنابراین یک گرادیان کوتاه باندهای بیشتری پیدا می‌کند و نوارهای آن نرم‌تر می‌شوند تا زمانی که به سقف ۶۴ باند برسد

// The shading discretizer uses up to 64 color bands along the gradient
// axis, but never more than the axis is long in device pixels. Rendering
// the same page at a higher DPI lengthens that axis, so a short gradient
// gains bands and the banding softens until the 64-band ceiling is hit.
Thumb := Pdf.RenderLoadedPageToBitmap(PageIndex, 96);   // coarser bands
Proof := Pdf.RenderLoadedPageToBitmap(PageIndex, 300);  // up to 64 bands

رندر کردن یک صفحه سایه‌دار به یک بیت‌مپ

نقطه ورود عمومی بدون تغییر است: RenderLoadedPageToBitmap یک ایندکس صفحه مبتنی بر صفر و یک مقدار DPI را دریافت می‌کند، یک بیت‌مپ ۲۴ بیتی متعلق به فراخوان‌کننده را برمی‌گرداند، و در صورت شکست به جای ایجاد استثنا، nil را پس می‌دهد، بنابراین پشتیبانی از سایه‌روشن برای کدهایی که از قبل دارید کاملاً شفاف است. صفحه‌ای که قبلاً هدر گرادیان آن خالی رندر می‌شد، اکنون همان بیت‌مپ را با ترکیب رنگ رسم‌شده برمی‌گرداند و نیازی به تغییر API برای دریافت آن نیست. تنها چیزی که باید به یاد داشته باشید مالکیت است: فراخوان‌کننده بیت‌مپ برگشتی را آزاد می‌کند. خط لوله رندر کامل — تفسیر جریان محتوا، گلیف‌های تعبیه‌شده و کش کردن صفحه — در راهنمای رندر صفحات PDF به بیت‌مپ در دلفی پوشش داده شده است

var
  Pdf: THotPDF;
  Bmp: TBitmap;
begin
  Pdf := THotPDF.Create(nil);
  try
    if Pdf.LoadFromFile('quarterly-report.pdf') > 0 then
    begin
      // Page 1 (zero-based) at 150 DPI. A gradient-filled header that
      // used to come back blank now carries its color blend.
      Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
      if Assigned(Bmp) then
      try
        Bmp.SaveToFile('page1.bmp');
      finally
        Bmp.Free;
      end;
    end;
  finally
    Pdf.Free;
  end;
end;

یک بررسی ساده برای جلوگیری از بازگشت به رفتار قبلی (regression guard) از همین فراخوانی به دست می‌آید. صفحه را رندر کنید، پیکسلی را که باند گرادیان به آن تعلق دارد نمونه‌برداری کنید و تأیید نمایید که دیگر رنگ سفید کاغذی نیست که رندرکننده قبلاً به آن بازمی‌گشت — یک بررسی تک‌خطی که بازگشت بی‌صدا به رفتار بدون عملیات قدیمی را شناسایی می‌کند

Bmp := Pdf.RenderLoadedPageToBitmap(0, 150);
if Assigned(Bmp) then
try
  // True when the sh operator painted; False if the region fell back to white.
  HeaderPainted := Bmp.Canvas.Pixels[Bmp.Width div 2, 8] <> clWhite;
finally
  Bmp.Free;
end;

آنچه HotPDF رسم نمی‌کند: سایه‌روشن‌های مش و لبه‌های برش

چهار نوع سایه‌روشن مش (mesh shading) خارج از محدوده هستند و یک سند باید از قبل این را بداند. شبکه‌های مثلثی گوراد شکل‌آزاد (Type 4)، شبکه‌های گوراد شبکه‌ای (Type 5)، شبکه‌های وصله کونز (Type 6)، و شبکه‌های وصله محصول تنسور (Type 7) که در استانداردهای ISO 32000-1 §8.7.4.5.5 تا §8.7.4.5.8 تعریف شده‌اند، رندر نمی‌شوند؛ صفحه‌ای که از یکی از آنها استفاده می‌کند همچنان رندر می‌شود، فقط آن ناحیه به همان صورت رها می‌گردد. دو مرز دیگر ارزش بیان صریح دارند. مستطیل‌های باند، نوار سایه‌روشن را پوشش می‌دهند تا اینکه دقیقاً به مسیر برش فعلی محدود شوند، بنابراین یک گرادیان ماسک‌شده در یک شکل گرد یا نامنظم به صورت نوار مرزی خود رسم می‌شود تا زمانی که برش دقیق ناحیه در مراحل بعدی اضافه گردد. HotPDF همچنین فرض می‌کند خروجی تابع RGB یا مقیاس خاکستری است، بنابراین سایه‌روشنی که در قالب CMYK یا فضای رنگی غیرمعمول نوشته شده باشد، به جای مدیریت رنگ، شبیه‌سازی می‌شود. برای اسنادی که اکثر تیم‌های دلفی و سی‌پلاس‌پلاس‌بیلدر واقعاً پردازش می‌کنند — گزارش‌ها، فاکتورها، صورت‌حساب‌ها و اسلایدهای صادرشده به PDF — متدهای محوری و شعاعی اساساً هر گرادیانی را که با آن مواجه شوید پوشش می‌دهند، و طرح‌های اولیه سنگین با مش مواردی هستند که باید به عنوان پیش‌نمایش در نظر گرفته شوند تا خروجی نهایی

رندرکننده صفحه HotPDF، پشتیبانی از اپراتور sh توصیف‌شده در اینجا، و ارزیاب تابع نوع Type 0/2/3 در زیر آن، به عنوان بخشی از HotPDF Component برای دلفی و سی‌پلاس‌پلاس‌بیلدر ارائه می‌شوند — یک کتابخانه بومی VCL بدون وابستگی به DLLهای خارجی، که ایجاد، ویرایش، استخراج متن و رندر صفحات را در یک بسته پوشش می‌دهد