Technical Article

جدول‌های 3D Color LUT در PDF با توابع نمونه‌برداری شده نوع 0

توابع PDF یکی از بخش‌های آرام‌تر مشخصات فنی هستند. بیشتر توسعه‌دهندگان یک بار با آن‌ها ملاقات می‌کنند، به عنوان چیزی که یک سایه‌روشن محوری نوع ۲ برای محو شدن بین دو رنگ نیاز دارد، و هرگز دوباره به سراغ آن نمی‌روند. این مایه تاسف است، زیرا مکانیزم توابع یک ارزیاب کوچک عمومی است که فرمت مجدداً برای سایه‌روشن‌ها، توابع انتقال، توابع ترام (halftone spot)، تینت‌های جداسازی (separation tints) و منحنی‌های انتقال ماسک نرم (soft-mask) استفاده می‌کند. از بین چهار نوع تابع، نوع ۰ قدرتمندترین و کمتر شناخته‌شده‌ترین است. این یک تابع نمونه‌برداری شده (sampled function) است: یک شبکه چندبعدی از مقادیر خروجی که خواننده بین آن‌ها درون‌یابی می‌کند. از آنجا که شبکه می‌تواند هر عددی را که در آن قرار می‌دهید نگه دارد، یک تابع نوع ۰ می‌تواند یک نگاشت غیرخطی دلخواه را بیان کند که دقیقاً شکل یک جدول جستجوی رنگ (color lookup table) است.

این مقاله دیکشنری نوع ۰ را همان‌طور که استاندارد ISO 32000-1 در بخش ۷.۱۰.۲ تعریف می‌کند بررسی می‌کند، سپس دو موردی را که در خط لوله سند بیشترین اهمیت را دارند نشان می‌دهد: یک LUT تصحیح رنگ RGB به RGB با سه ورودی و یک تبدیل تینت اسپات‌کالر (spot-color tint transform) با یک ورودی. یک سازنده تابع نمونه‌برداری شده یکسان به هر دو خدمت می‌کند و تفاوت بین آن‌ها کاملاً مربوط به تعداد ورودی‌های شبکه است.

یک تابع نمونه‌برداری شده شبکه‌ای است که خواننده درون‌یابی می‌کند

یک تابع نوع ۰ یک بردار ورودی با بعد m را به یک بردار خروجی با بعد n با ذخیره نمونه‌ها در یک شبکه منظم و درون‌یابی بین آن‌ها نگاشت می‌کند. بخش ۷.۱۰.۲ استاندارد ISO 32000-1 کلیدهایی را که این شبکه را توصیف می‌کنند لیست می‌کند. /Domain دو عدد برای هر ورودی، یعنی باند پایین و بالا برای هر محور ورودی را نگه می‌دارد. /Range دو عدد برای هر جزء خروجی نگه می‌دارد. /Size آرایه‌ای از m عدد صحیح است که تعداد نمونه‌ها را در امتداد هر محور ورودی نشان می‌دهد، بنابراین شبکه‌ای که در سه بعد دارای دوازده نمونه در هر ضلع است دارای /Size [12 12 12] است و ۱۷۲۸ نقطه شبکه را ذخیره می‌کند. /BitsPerSample دقت هر مقدار ذخیره‌شده را تعیین می‌کند؛ HotPDF مقادیر ۱، ۲، ۴، ۸، ۱۲، ۱۶، ۲۴ و ۳۲ بیت را می‌پذیرد که مطابق با مقادیری است که جدول ۳۸ مجاز می‌داند.

جریان نمونه با ترتیب ثابتی خوانده می‌شود. بعد ورودی اول سریع‌تر تغییر می‌کند، سپس بعد دوم و به همین ترتیب، و در هر نقطه شبکه، n جزء خروجی به ترتیب ذخیره می‌شوند. برای یک جدول RGB به RGB، این مقدار سه بایت در هر نقطه شبکه با دقت هشت بیت است که به صورت خروجی قرمز، خروجی سبز، خروجی آبی چیده شده و ابتدا روی ورودی قرمز حرکت می‌کند. دو کلید دیگر دنیای پیوسته را روی شبکه اعداد صحیح نگاشت می‌کنند. /Encode هر ورودی را از بازه /Domain آن به محدوده ایندکس نمونه 0 تا Size[i] - 1 نگاشت می‌کند و /Decode maps the raw stored integers back onto the /Range intervals. When you leave them at their defaults, an input spanning [0 1] lands cleanly on the full grid and a stored byte of 255 decodes to the top of its output range, which is what an [0,1]-normalized color LUT wants.

مرتبه 1 در مقابل مرتبه 3

بین نقاط شبکه، خواننده باید درون‌یابی کند و /Order نحوه انجام آن را انتخاب می‌کند. /Order 1 درون‌یابی چندخطی است: خطی در امتداد یک محور، دوخطی روی دو محور، سه‌خطی روی سه محور. این روش سریع است، دقیقاً همان کاری است که سخت‌افزار در بیشتر نمایشگرها انجام می‌دهد و برای یک تبدیل رنگی صاف معمولاً از هر چیز فانتزی‌تر غیرقابل تشخیص است. /Order 3 درون‌یابی اسپلاین مکعبی (cubic-spline) را درخواست می‌کند که منحنی صاف‌تری را با هزینه کار بیشتر و یک منطقه پشتیبانی گسترده‌تر در اطراف هر نقطه ارزیابی‌شده در میان نمونه‌ها برازش می‌دهد.

موازنه بین چگالی شبکه و صافی منحنی است. مرتبه مکعبی ارزش خود را زمانی نشان می‌دهد که شبکه درشت باشد و نگاشت دارای انحنای مرئی باشد، زیرا یک خط مستقیم بین دو نمونه دور می‌تواند یک منحنی تن رنگ را به گونه‌ای تخت کند که چشم روی گرادینت‌ها متوجه آن شود. هنگامی که شبکه چگال است، بخش‌ها به اندازه کافی کوتاه هستند که درون‌یابی خطی منحنی را از نزدیک دنبال کند و مرتبه مکعبی مزیت کمی به همراه دارد. یک قانون عملی این است که فقط با شبکه‌های کوچک یا تبدیل‌های پرشیب به سراغ /Order 3 بروید و در غیر این صورت آن را روی پیش‌فرض خطی رها کنید. توجه داشته باشید که /Order فقط برای توابع نوع ۰ اعمال می‌شود و HotPDF هر مقداری به جز ۱ یا ۳ را رد می‌کند.

جدول 3D LUT: سه ورودی، سه خروجی

یک تصحیح رنگ RGB به RGB مورد کتاب درسی برای یک شبکه با سه ورودی است، یعنی 3D LUT کلاسیک که در درجه‌بندی رنگ و تطبیق دستگاه استفاده می‌شود. هر محور مکعب یک کانال ورودی است، هر نقطه شبکه سه‌گانه RGB تصحیح‌شده را برای آن مختصات ورودی ذخیره می‌کند و خواننده به طور سه‌خطی نمونه‌های گوشه را در اطراف هر رنگ ورودی درون‌یابی می‌کند. وجود سه ورودی در اینجا اجتناب‌ناپذیر است زیرا قرمز تصحیح‌شده می‌تواند به سبز و آبی ورودی بستگی داشته باشد، نه فقط به قرمز ورودی؛ یک منحنی برای هر کانال نمی‌تواند تداخل کانال‌ها (channel crosstalk) را بیان کند، اما یک مکعب می‌تواند.

HotPDF فایل‌های نوع ۰ را از طریق RegisterSampledFunction می‌سازد که مقادیر /Domain ،/Range ،/Size ،/BitsPerSample و بایت‌های نمونه را مستقیماً می‌گیرد و شیء تابع را برمی‌گرداند. برای یک مکعب نرمال شده استاندارد، شما باندهای [0,1] را روی هر سه محور ورودی و هر سه خروجی، اندازه N x N x N و جدول نمونه تخت‌شده را پاس می‌دهید. سازنده اعتبارسنجی می‌کند که تعداد بایت‌ها با شبکه مطابقت داشته باشد: برای عمق تراز شده با بایت، انتظار دارد OutputCount x (BitsPerSample div 8) x حاصل‌ضرب اندازه‌ها را داشته باشد و در صورتی که آرایه طول اشتباهی داشته باشد خطا می‌دهد، بنابراین یک گام اشتباه محاسبه‌شده در زمان ثبت با صدای بلند شکست می‌خورد به جای اینکه بعداً به عنوان محتوای نامفهوم رندر شود.

const
  N = 17;  // 17 x 17 x 17 cube, the common ICC LUT resolution
var
  LutFn: THPDFStreamObject;
  Samples: TBytes;
begin
  // Fill Samples with N*N*N grid points, 3 bytes each (R,G,B output),
  // red input varying fastest. Build the corrected triple for each
  // grid coordinate with your ICC-managed conversion, then store it.
  SetLength(Samples, N * N * N * 3);
  BuildCorrectedCube(Samples, N);   // your color-managed fill

  LutFn := Pdf.RegisterSampledFunction(
    [0,1, 0,1, 0,1],
    [0,1, 0,1, 0,1],
    [N, N, N],
    8,
    Samples,
    1);
end;

صحت رنگ‌سنجی مکعب در نحوه پر کردن آن نهفته است، نه در تابع PDF. مسیر درست این است که هر نقطه شبکه را از طریق یک تبدیل مدیریت‌شده با ICC محاسبه کنید، همان موتوری که یک soft-proof را هدایت می‌کند، به طوری که اعداد موجود در شبکه در برابر یک پروفایل منبع و مقصد تعریف شده معنایی داشته باشند. پروفایل‌هایی را که تبدیل را محدود می‌کنند با RegisterICCProfile ثبت کنید که یک فضای رنگی مبتنی بر ICC (با ۱، ۳ یا ۴ جزء) را ثبت کرده و نام منبعی را برمی‌گرداند که می‌توانید به محتوایی که LUT تغذیه می‌کند متصل کنید. تابع نوع ۰ جدول درون‌یابی را حمل می‌کند؛ پروفایل ICC معنای نقاط انتهایی را حمل می‌کند.

مورد 1D: تبدیل تینت اسپات‌کالر

فضاهای رنگی جداسازی (Separation color spaces) برای کار کاملاً متفاوتی به همین مکانیزم تکیه می‌کنند. یک فضای جداسازی تعریف شده در ISO 32000-1 بخش ۸.۶.۶.۴، یک رنگ‌ساز واحد، مانند یک جوهر اسپات مانند Pantone یا یک لاک را با جفت کردن یک نام با یک تبدیل تینت (tint transform) نشان می‌دهد: تابعی که مقدار تینت یک‌بعدی، ۰ برای بدون جوهر تا ۱ برای جوهر کامل را روی یک فضای رنگی جایگزین که دستگاه واقعاً می‌تواند رندر کند، معمولاً CMYK، نگاشت می‌کند. آن تبدیل تینت غالباً یک تابع نوع ۰ است و اکنون شبکه دقیقاً یک محور ورودی دارد.

این تضاد واضح با 3D LUT است. یک جوهر اسپات یک درجه آزادی دارد، بنابراین تبدیل تینت آن به یک ورودی نیاز دارد و شبکه خطی از نمونه‌ها است که هر کدام مقدار CMYK (یا مقدار جایگزین دیگر) را در آن سطح تینت نگه می‌دارند. مکعب RGB به سه ورودی نیاز دارد زیرا دامنه آن سه‌بعدی است و کانال‌ها با هم تعامل دارند. نوع تابع یکسان، قوانین درون‌یابی یکسان، ابعاد متفاوت؛ مشخصات فنی از یک ارزیاب مجدداً استفاده می‌کند و اجازه می‌دهد /Size تصمیم بگیرد که آیا در حال پیمودن یک خط، یک صفحه یا یک مکعب هستید. HotPDF کل جداسازی را در RegisterSeparationLUT بسته‌بندی می‌کند که تبدیل تینت نوع ۰ با یک ورودی را به طور داخلی از یک آرایه بایت تخت می‌سازد و نام منبع فضای رنگی را برمی‌گرداند.

var
  SpotCS: AnsiString;
begin
  // Four CMYK output bytes per tint grid point, tint domain [0..1].
  // Here 0% ink -> all zero, 100% ink -> a rich spot build,
  // with two interior steps; the tint transform interpolates between.
  SpotCS := Pdf.RegisterSeparationLUT(
    'PANTONE 286 C',
    'DeviceCMYK',
    [  0,   0,   0,   0,
      90,  60,   0,   0,
     100,  80,   0,  10,
     100,  72,   0,  18]);
  // Use SpotCS with SetFillColorSpace / SetFillColor on a page.
end;

تعداد نمونه‌ها باید یک عدد کامل از نقاط شبکه باشد: مضرب مثبتی از تعداد اجزای فضای جایگزین و حداقل دو نقطه تا بخشی برای درون‌یابی وجود داشته باشد. پاس دادن سه بایت در هر نقطه در برابر یک جزء CMYK جایگزین باعث رد شدن فراخوانی می‌شود، همان اعتبارسنجی تدافعی که سازنده سه‌بعدی اعمال می‌کند، که این همان چیزی است که از تابعی می‌خواهید که در غیر این صورت در زمان چاپ به طور خاموش خراب می‌شود.

جایی که همین مکانیزم دوباره ظاهر می‌شود

هنگامی که نوع ۰ را به عنوان یک جدول درون‌یابی عمومی ببینید، دو ویژگی کنترل دستگاه دیگر شبیه به موارد خاص به نظر نمی‌رسند. یک تابع انتقال (transfer function) مقادیر جزء را در مسیر خود به دستگاه خروجی تنظیم می‌کند و این فقط یک تابع برای هر کانال است؛ HotPDF آن را به عنوان یک ExtGState از طریق RegisterTransferFunctionState ثبت می‌کند که یا یک تابع ترکیبی یا آرایه‌ای از توابع برای هر کانال را می‌پذیرد. از آنجا که آن توابع اشیاء تابع معمولی هستند، می‌توانید همان THPDFStreamObject را که RegisterSampledFunction برمی‌گرداند به آن بدهید و یک منحنی انتقال را از یک جدول نمونه‌برداری شده به جای یک فرمول هدایت کنید.

var
  ToneFn: THPDFStreamObject;
  GsName: AnsiString;
begin
  // A single-input, single-output sampled tone curve on [0,1].
  ToneFn := Pdf.RegisterSampledFunction(
    [0,1], [0,1], [256], 8, ToneCurveBytes, 1);

  // Apply it to all channels as a combined /TR2 transfer function.
  GsName := Pdf.RegisterTransferFunctionState(ToneFn, []);
  // Select GsName on the page before drawing the affected content.
end;

تولید مشکی (black generation) و حذف رنگ زیرین (undercolor removal) در همین خانواده قرار دارند. هنگامی که یک دستگاه RGB را به CMYK تبدیل می‌کند، تصمیم می‌گیرد که چه مقدار از جزء خاکستری را به عنوان جوهر مشکی حمل کند و مشخصات فنی این تصمیم را به عنوان یک تابع بیان می‌کند، ورودی‌های /BG2 و /UCR2 یک دیکشنری حالت گرافیکی، که هر کدام یک منحنی با یک ورودی از خاکستری محاسبه‌شده به مقدار مشکی است. این‌ها نیز توابع نوع ۰ هستند وقتی که منحنی اندازه‌گیری شده را به جای منحنی تحلیلی می‌خواهید، که به همان روش از طریق RegisterSampledFunction ساخته شده و در حالت گرافیکی قرار می‌گیرند. درسی که ارزش یادآوری دارد این است که تابع PDF هرگز جایی نیست که مدیریت رنگ در آن اتفاق می‌افتد؛ بلکه جدول جستجویی است که تصمیمی را که با یک موتور رنگی واقعی گرفته‌اید حمل می‌کند و نوع ۰ تنها نوع تابعی است که به اندازه کافی انعطاف‌پذیر است تا هر تصمیمی را حمل کند.

برای تصویر وسیع‌تر از نحوه صدور فونت‌ها، تصاویر و منابع رنگی به یک سند نهایی، به راهنمای ما برای خروجی گزارش با فونت‌ها و تصاویر مراجعه کنید. هنگامی که خروجی باید در بررسی preflight آرشیوی یا چاپ دوام بیاورد، قوانین فضای رنگی و قصد خروجی (output-intent) پوشش داده شده در راهنمای اعتبارسنجی PDF/A، PDF/X و PDF/UA حاکم هستند بر اینکه کدام یک از این توابع مجاز می‌باشند و رنگ دستگاه چگونه باید تگ شود. تمام این امکانات در کامپوننت HotPDF برای Delphi و C++Builder در کنار APIهای سایه‌روشن، ICC و جداسازی که بر اساس همان هسته نوع ۰ ساخته شده‌اند، ارائه می‌شود.