|
声明 PDF 1.2+ 的 Function Type 0(Sampled)间接流对象(ISO 32000-1 7.10.2)。采样函数把任意输入到输出的映射表达为规则的 N 维网格上的 M 维输出采样;渲染器在网格点之间插值来求值中间输入。当 ICC 配置文件机制过于笨重、但需要手工调校的查找表时使用它 — 例如 /TransferFunction(ExtGState /TR)的色调曲线、/Separation 或 /DeviceN 的采样 tint 变换(线性 Type 2 / 算术 Type 4 路径的替代)、半色调阈值曲线,或任何接受 Function 字典的 PDF 结构。
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);
说明
该函数作为间接流输出,带有 /FunctionType 0、所给的 /Domain、/Range、/Size、/BitsPerSample 和 /Order 条目,外加按位打包的原始采样流。/Encode 和 /Decode 被省略,因此采用规范默认值:/Encode 把每个 Domain 端点映射到网格范围 [0..Size[i]-1],/Decode 与 /Range 相同(采样先解包为整数,再线性映射回 Range 的端点)。对于多输入函数,采样的字节顺序遵循 PDF 1.7 的规则“输入坐标沿第一个输入维度变化最快”,即在有 M 个输出时,网格点 (i_0, i_1, ..., i_{N-1}) 的字节偏移为 ((((i_{N-1} * Size[N-2] + i_{N-2}) * ...) * Size[0] + i_0) * M * BitsPerSample / 8
Order - 可选,默认为 1。按 PDF 1.7 表 38,接受 1(线性插值,PDF 1.7 默认值)或 3(三次样条插值)。采样网格密度较低时(例如 17 点的 ICC 色调曲线),三次插值的过渡更平滑,但一些较老的移动端阅读器遇到自己未实现的 Order 值时,会悄悄回退到线性。自 HotPDF v2.54.0 起可用
对于 ASCII 输入这类典型的编写路径,单输入 / M 输出的函数取 BitsPerSample = 8 和 Size = [256],就得到一个 256 采样的 LUT,其流恰好是 256 * M 字节,排布为 (o0_0, o1_0, ..., oM-1_0, o0_1, ..., oM-1_255)
Domain - 2N 个 Single 值,顺序为 [in0Min in0Max in1Min in1Max ...]。函数在插值之前,会把传入的值钳位到该范围内。N 由 Length(Domain) div 2 确定
Range - 2M 个 Single 值,与 M 个输出维度形状相同;输出采样在解码后被钳制到此范围。
Size - N 个整数,给出每个输入轴上的网格点数。Length(Size) 必须等于 N。网格点总数是所有 Size 条目的乘积。
BitsPerSample - 按 PDF 1.7 表 38,取 1、2、4、8、12、16、24 或 32 之一。8 是最省事的选择(原始字节流);16 到 32 是字节对齐的大端宽度;1 / 2 / 4 / 12 要求 MSB 优先的位打包,最后一个字节用零补齐到字节边界。其他任何值都会抛出异常
Samples - 原始按位打包的采样流。长度必须等于 ceil(GridPoints * M * BitsPerSample / 8) 字节,只在需要时包含末字节填充。HotPDF 校验每种受支持的打包深度,并把给定字节原样拷贝进间接流对象;位打包的正确性由调用方负责。 已加载页面求值支持 1 到 4 个输入与输出、显式正向或反向 /Encode、独立的 /Decode、多线性 /Order 1、多维三次 /Order 3 以及一维自然三次样条。校验过的采样字节和插值元数据保存在一个 8 条目、64 MiB 的 LRU 中,供重复的 tint、shading、软蒙版和传递函数调用使用。自 HotPDF v2.544.0 起可用。
返回值:间接的 THPDFStreamObject,调用方可把它附加到任何期望 Function 字典的位置(通常是通过 AddValue,或交给 shading / separation 构建器)。对象由文档的 IndirectObjects 列表持有,在文档结束时释放。返回nil——当 StrictVersionLock 开启且当前 Version 低于 PDF 1.2 时(否则文档版本自动升到 1.2)。
代码示例
// 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 过滤器支持
|