|
宣告 PDF 1.3+ Function Type 0 (Sampled) indirect stream object (ISO 32000-1 7.10.2)。Sampled functions 會以 M-dimensional output samples 的規則 N-dimensional grid 表達任意 input-to-output mapping;renderer 會在 grid points 之間線性插值以評估中間輸入。當 ICC profile machinery 過於繁重,但需要 hand-tuned lookup table 時可使用此方法,例如 /TransferFunction (ExtGState /TR) 的 tone curves、/Separation 或 /DeviceN 的 sampled tint transforms(取代 linear Type 2 / arithmetic Type 4 paths)、halftone threshold curves,或任何接受 Function dictionary 的其他 PDF construct
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);
說明
The function is emitted as an indirect stream with /FunctionType 0, the supplied /Domain, /Range, /Size, /BitsPerSample and /Order entries, plus the raw bit-packed sample stream. /Encode and /Decode are omitted so the spec defaults apply: /Encode maps each Domain endpoint to grid extents [0..Size[i]-1], and /Decode matches /Range (samples are unpacked to integers and linearly remapped back to the Range endpoints). For multi-input functions the sample byte order follows the PDF 1.7 rule "input coordinates increase fastest along the first input dimension", i.e. the byte offset for grid point (i_0, i_1, ..., i_{N-1}) with M outputs is ((((i_{N-1} * Size[N-2] + i_{N-2}) * ...) * Size[0] + i_0) * M * BitsPerSample / 8.
Order - optional, default 1. Accepts 1 (linear interpolation, PDF 1.7 default) or 3 (cubic-spline interpolation) per PDF 1.7 Table 38. Cubic gives smoother transitions at low sample-grid densities (e.g. 17-point ICC tone curves) but some older mobile readers silently fall back to linear when they encounter an Order value they do not implement. Available since HotPDF v2.54.0.
For ASCII-input use cases - the typical authoring path - a single 1-input / M-output function with BitsPerSample = 8 and Size = [256] gives a 256-sample LUT whose stream is exactly 256 * M bytes laid out as (o0_0, o1_0, ..., oM-1_0, o0_1, ..., oM-1_255).
Domain - 2N Single values, ordered [in0Min in0Max in1Min in1Max ...]. The function clamps incoming values to this range before interpolation. N is determined from Length(Domain) div 2.
Range - 2M 個 Single values,形狀與 M 個 output dimensions 相同;output samples 會在 decoding 後限制到此 range
Size - N 個 integers,給出每個 input axis 上的 grid-point count。Length(Size) 必須等於 N。總 grid points 是所有 Size entries 的乘積
BitsPerSample - one of 1, 2, 4, 8, 12, 16, 24, or 32 per PDF 1.7 Table 38. 8 is the ergonomic choice (raw byte stream); 16 through 32 are byte-aligned big-endian widths; 1 / 2 / 4 / 12 require MSB-first bit packing with the final byte zero-padded to a byte boundary. Any other value raises an exception.
Samples - raw bit-packed sample stream。Length 必須至少為 ceil(GridPoints * M * BitsPerSample / 8) bytes。HotPDF 會將提供的 bytes 逐字複製到 indirect stream object;bit-pack correctness 由呼叫端負責
傳回值: indirect THPDFStreamObject,讓呼叫端可將它附加到任何需要 Function dictionary 的位置(通常是將其 indirect reference 透過 AddValue 傳入另一個 dict,或傳給 shading / separation builder)。此 object 由檔案的 IndirectObjects list 擁有,並在檔案結束時釋放。當 StrictVersionLock 啟用且目前 Version 低於 PDF 1.3 時會傳回 nil;否則檔案版本會自動提升到 1.3
Code Example
// 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 篩選器支援
|