|
Declara un objeto de stream indirecto Function Type 0 (Sampled) de PDF 1.2+ (ISO 32000-1 7.10.2). Las funciones muestreadas expresan un mapeo arbitrario de entrada a salida como una cuadrícula regular N-dimensional de muestras de salida M-dimensionales; el renderer interpola entre puntos de la cuadrícula para evaluar entradas intermedias. Úselo donde la maquinaria de perfiles ICC sea excesiva pero se desee una tabla de consulta ajustada a mano - curvas de tono para /TransferFunction (/TR de ExtGState), transformaciones de tinte muestreadas para /Separation o /DeviceN (alternativa a las rutas lineales Type 2 / aritméticas Type 4), curvas de umbral de halftone, o cualquier otra construcción PDF que acepte un diccionario Function.
Sintaxis 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;
Sintaxis 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);
Descripción
La función se emite como un stream indirecto con /FunctionType 0, las entradas suministradas /Domain, /Range, /Size, /BitsPerSample y /Order, más el stream crudo de muestras empaquetadas en bits. /Encode y /Decode se omiten para que se apliquen los valores por defecto de la especificación: /Encode mapea cada extremo del Domain a las extensiones de la cuadrícula [0..Size[i]-1], y /Decode coincide con el /Range (las muestras se desempaquetan a enteros y se remapean linealmente de vuelta a los extremos del Range). Para funciones de varias entradas, el orden de bytes de las muestras sigue la regla de PDF 1.7 "las coordenadas de entrada crecen más rápido a lo largo de la primera dimensión de entrada", es decir, el offset de bytes para el punto de cuadrícula (i_0, i_1, ..., i_{N-1}) con M salidas es ((((i_{N-1} * Size[N-2] + i_{N-2}) * ...) * Size[0] + i_0) * M * BitsPerSample / 8.
Order - opcional, 1 por defecto. Acepta 1 (interpolación lineal, valor por defecto de PDF 1.7) o 3 (interpolación spline cúbica) según la Tabla 38 de PDF 1.7. La cúbica da transiciones más suaves a densidades bajas de cuadrícula de muestras (p. ej. curvas de tono ICC de 17 puntos), pero algunos lectores móviles antiguos caen silenciosamente a lineal cuando encuentran un valor de Order que no implementan. Disponible desde HotPDF v2.54.0.
Para casos de uso de entrada ASCII - la ruta típica de autoría - una única función de 1 entrada / M salidas con BitsPerSample = 8 y Size = [256] da una LUT de 256 muestras cuyo stream es exactamente 256 * M bytes dispuestos como (o0_0, o1_0, ..., oM-1_0, o0_1, ..., oM-1_255).
Domain - 2N valores Single, ordenados [in0Min in0Max in1Min in1Max ...]. La función acota los valores de entrada a este rango antes de interpolar. N se deduce de Length(Domain) div 2.
Range - 2M valores Single con la misma forma para las M dimensiones de salida; las muestras de salida se acotan a este rango tras decodificar.
Size - N enteros que dan el número de puntos de cuadrícula a lo largo de cada eje de entrada. Length(Size) debe ser igual a N. El total de puntos de la cuadrícula es el producto de todas las entradas Size.
BitsPerSample - uno de 1, 2, 4, 8, 12, 16, 24 o 32 según la Tabla 38 de PDF 1.7. 8 es la opción más cómoda (stream de bytes en bruto); 16 a 32 son anchos alineados a byte en big-endian; 1 / 2 / 4 / 12 requieren empaquetado de bits MSB primero, con el último byte rellenado con ceros hasta el límite de byte. Cualquier otro valor lanza una excepción.
Samples - el stream de muestras empaquetado en bits, en bruto. Su longitud debe ser igual a ceil(GridPoints * M * BitsPerSample / 8) bytes, con relleno solo en el último byte cuando sea necesario. HotPDF valida cada profundidad empaquetada admitida y copia los bytes suministrados tal cual en el objeto stream indirecto; la corrección del empaquetado de bits es responsabilidad de quien llama.
La evaluación de páginas cargadas soporta de una a cuatro entradas y salidas, /Encode explícito hacia delante o invertido, /Decode independiente, /Order 1 multilineal, /Order 3 cúbico multidimensional y splines cúbicos naturales unidimensionales. Los bytes de muestras validados y los metadatos de interpolación se retienen en una LRU de ocho entradas y 64 MiB para llamadas repetidas de tinte, sombreado, máscara suave y funciones de transferencia. Disponible desde HotPDF v2.544.0.
Valor devuelto: el THPDFStreamObject indirecto, de modo que los llamadores pueden adjuntarlo donde se espere un diccionario Function (normalmente pasando su referencia indirecta a otro dict vía AddValue, o a un builder de shading / separation). El objeto es propiedad de la lista IndirectObjects del documento y se libera al finalizar el documento. Devuelve nil cuando StrictVersionLock está activo y la Version activa es inferior a PDF 1.2 (en caso contrario la versión del documento sube automáticamente a 1.2).
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;
Véase también
RegisterAxialGradient, RegisterDeviceN, RegisterSeparation, Version, PDF Filter Support
|