|
یک شیء جریان غیرمستقیم Function Type 0 (Sampled) در PDF 1.3+ را اعلام میکند (ISO 32000-1 7.10.2). Functionهای Sampled نگاشت دلخواه ورودی به خروجی را بهصورت یک شبکهٔ N بعدی از نمونههای خروجی M بعدی بیان میکنند؛ renderer بهصورت خطی بین نقاط شبکه درونیابی میکند تا ورودیهای میانی را ارزیابی کند. از این متد وقتی استفاده کنید که machinery مربوط به ICC profile بیش از اندازه باشد اما یک lookup table تنظیمشده بهصورت دستی بخواهید - منحنیهای tone برای /TransferFunction (ExtGState /TR)، tint transformهای Sampled برای /Separation یا /DeviceN (جایگزین مسیرهای Type 2 خطی / Type 4 حسابی)، منحنیهای آستانهٔ halftone، یا هر سازهٔ PDF دیگری که دیکشنری Function میپذیرد
نحو Delphi:
function RegisterSampledFunction(const Domain: array of Single; const Range: array of Single; const Size: array of Integer; BitsPerSample: Integer; const Samples: array of byte; Order: Integer = 1): THPDFStreamObject;
نحو C++:
THPDFStreamObject* RegisterSampledFunction(const float* Domain, int DomainCount, const float* Range, int RangeCount, const int* Size, int SizeCount, int BitsPerSample, const unsigned char* Samples, int SamplesCount, int Order = 1);
توضیح
این function بهصورت یک جریان غیرمستقیم با /FunctionType 0، ورودیهای دادهشدهٔ /Domain، /Range، /Size، /BitsPerSample و /Order، بههمراه جریان خام نمونههای bit-packed صادر میشود. /Encode و /Decode حذف میشوند تا پیشفرضهای spec اعمال شوند: /Encode هر سرحد Domain را به گسترهٔ شبکهٔ [0..Size[i]-1] نگاشت میکند و /Decode با /Range منطبق میشود، یعنی نمونهها به اعداد unpack میشوند و بهصورت خطی به سرحدهای Range remap میشوند. برای functionهای چندورودی، ترتیب بایت نمونه از قاعدهٔ PDF 1.7 پیروی میکند که «مختصات ورودی در راستای نخستین بُعد ورودی سریعتر افزایش مییابند»؛ یعنی offset بایت برای نقطهٔ شبکهٔ (i_0, i_1, ..., i_{N-1}) با M خروجی برابر است با ((((i_{N-1} * Size[N-2] + i_{N-2}) * ...) * Size[0] + i_0) * M * BitsPerSample / 8
Order - اختیاری، پیشفرض 1. مقادیر 1 (درونیابی خطی، پیشفرض PDF 1.7) یا 3 (درونیابی cubic-spline) را طبق جدول 38 PDF 1.7 میپذیرد. حالت cubic در تراکمهای پایین شبکهٔ نمونه گذارهای نرمتری میدهد (مثلاً منحنیهای tone شانزدهوهفتنقطهای ICC)، اما برخی readerهای موبایلی قدیمی وقتی با مقدار Order ناشناخته روبهرو میشوند بیصدا به حالت خطی برمیگردند. از HotPDF v2.54.0 در دسترس است
برای موارد استفاده با ورودی ASCII - مسیر معمول authoring - یک function تکورودی / M-خروجی با BitsPerSample = 8 و Size = [256] یک LUT با 256 نمونه میدهد که جریان آن دقیقاً 256 * M بایت است و بهشکل (o0_0, o1_0, ..., oM-1_0, o0_1, ..., oM-1_255) چیده میشود
Domain - 2N مقدار Single، بهترتیب [in0Min in0Max in1Min in1Max ...]. function مقادیر ورودی را پیش از درونیابی در این بازه clamp میکند. N از Length(Domain) div 2 تعیین میشود
Range - 2M مقدار Single با همان قالب برای M بُعد خروجی؛ نمونههای خروجی پس از decode در این بازه clamp میشوند
Size - N عدد صحیح که شمار نقطههای شبکه را در هر محور ورودی میدهند. Length(Size) باید برابر N باشد. مجموع نقطههای شبکه حاصلضرب همهٔ ورودیهای Size است
BitsPerSample - یکی از 1، 2، 4، 8، 12، 16، 24 یا 32 طبق جدول 38 PDF 1.7. مقدار 8 انتخاب ارگونومیک است (جریان خام بایت)؛ مقادیر 16 تا 32 پهنای big-endian همتراز با بایت هستند؛ مقادیر 1 / 2 / 4 / 12 به bit packing با MSB-first نیاز دارند و بایت نهایی تا مرز بایت zero-pad میشود. هر مقدار دیگری exception ایجاد میکند
Samples - جریان خام sampleهای bit-packed. طول باید دستکم ceil(GridPoints * M * BitsPerSample / 8) بایت باشد. HotPDF بایتهای دادهشده را بدون تغییر در شیء جریان غیرمستقیم کپی میکند؛ درستی bit-pack بر عهدهٔ فراخواننده است
Return value: شیء غیرمستقیم THPDFStreamObject تا فراخواننده بتواند آن را هرجا که یک دیکشنری Function انتظار میرود وصل کند (معمولاً با پاس دادن reference غیرمستقیم آن به دیکشنری دیگر از طریق AddValue، یا به یک builder برای shading / separation). این شیء متعلق به فهرست IndirectObjects سند است و در پایان سند آزاد میشود. وقتی StrictVersionLock روشن باشد و Version فعال از PDF 1.3 پایینتر باشد، nil برمیگرداند (در غیر این صورت نسخهٔ سند بهطور خودکار به 1.3 افزایش مییابد)
نمونه کد
// 256-sample 1-input / 3-output (RGB) heatmap LUT. The LUT maps a
// scalar t in [0..1] to a blue -> green -> red gradient through the
// midpoint
uses
HPDFObjs;
var
Func: THPDFStreamObject;
Domain: array[0..1] of Single;
Range: array[0..5] of Single;
Size: array[0..0] of Integer;
Samples: array[0..767] of byte; // 256 grid points * 3 outputs
I: Integer;
T: Single;
begin
HPDF.BeginDoc;
// 1 input dim: t in [0..1]
Domain[0] := 0; Domain[1] := 1;
// 3 output dims: each in [0..1]
Range[0] := 0; Range[1] := 1;
Range[2] := 0; Range[3] := 1;
Range[4] := 0; Range[5] := 1;
// 256 sample points along the single input axis
Size[0] := 256;
for I := 0 to 255 do
begin
T := I / 255.0;
if T < 0.5 then
begin
Samples[I*3 + 0] := 0;
Samples[I*3 + 1] := byte(Round(2.0 * T * 255.0));
Samples[I*3 + 2] := byte(Round((1.0 - 2.0*T) * 255.0));
end
else
begin
Samples[I*3 + 0] := byte(Round(2.0 * (T - 0.5) * 255.0));
Samples[I*3 + 1] := byte(Round((1.0 - 2.0*(T - 0.5)) * 255.0));
Samples[I*3 + 2] := 0;
end;
end;
Func := HPDF.RegisterSampledFunction(Domain, Range, Size, 8, Samples);
// Func is now an indirect THPDFStreamObject the caller can attach
// to any PDF dict slot that accepts a Function reference
HPDF.EndDoc;
end;
همچنین ببینید
RegisterAxialGradient, RegisterDeviceN, RegisterSeparation, Version, پشتیبانی فیلترهای PDF
|