THotPDF.RegisterSampledFunction 메서드

 

THotPDF.RegisterSampledFunction

THotPDF

 

Top

PDF 1.2+ Function Type 0(Sampled) indirect 스트림 객체(ISO 32000-1 7.10.2)를 선언합니다. Sampled 함수는 임의의 입력-출력 매핑을 M차원 출력 샘플로 이루어진 규칙적인 N차원 그리드로 표현하며, 렌더러는 그리드 점 사이를 보간해 중간 입력을 계산합니다. ICC 프로필 방식이 과하지만 직접 조정한 룩업 테이블이 필요할 때 사용하세요. /TransferFunction(ExtGState /TR)용 톤 커브, /Separation 또는 /DeviceN용 샘플링된 tint 변환(선형 Type 2 / 산술 Type 4 방식의 대안), 하프톤 임계값 커브, 그 밖에 Function 사전을 받는 모든 PDF 구조에 쓸 수 있습니다.

 

Delphi syntax:

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++ syntax:

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);

 

Description

함수는 /FunctionType 0, 전달된 /Domain, /Range, /Size, /BitsPerSample, /Order 항목, 그리고 비트 패킹된 raw 샘플 스트림을 갖는 indirect 스트림으로 출력됩니다. /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 Table 38에 따라 1(선형 보간, PDF 1.7 기본값) 또는 3(3차 스플라인 보간)을 받습니다. 3차 보간은 샘플 그리드 밀도가 낮을 때(예: 17점 ICC 톤 커브) 더 부드러운 전환을 주지만, 일부 오래된 모바일 리더는 구현하지 않은 Order 값을 만나면 조용히 선형으로 폴백합니다. HotPDF v2.54.0부터 사용할 수 있습니다.

일반적인 작성 경로인 ASCII 입력 용도에서는 BitsPerSample = 8, Size = [256]인 1입력 / M출력 함수 하나로 256샘플 LUT를 만들 수 있습니다. 이 LUT의 스트림은 정확히 256 * M바이트이며 (o0_0, o1_0, ..., oM-1_0, o0_1, ..., oM-1_255) 순서로 배치됩니다.

 

Domain - [in0Min in0Max in1Min in1Max ...] 순서의 Single 값 2N개입니다. 함수는 보간 전에 들어오는 값을 이 범위로 클램프합니다. N은 Length(Domain) div 2로 결정됩니다.

Range - M개의 출력 차원에 대해 같은 형태를 갖는 Single 값 2M개입니다. 출력 샘플은 디코딩 뒤 이 범위로 클램프됩니다.

Size - 각 입력 축을 따르는 그리드 점 개수를 나타내는 정수 N개입니다. Length(Size)는 N과 같아야 합니다. 전체 그리드 점 수는 모든 Size 항목의 곱입니다.

BitsPerSample - PDF 1.7 Table 38에 따라 1, 2, 4, 8, 12, 16, 24, 32 중 하나입니다. 8이 다루기 편한 선택이고(raw 바이트 스트림), 16에서 32까지는 바이트 정렬된 big-endian 폭이며, 1 / 2 / 4 / 12는 MSB 우선 비트 패킹이 필요하고 마지막 바이트를 바이트 경계까지 0으로 채웁니다. 다른 값은 예외를 발생시킵니다.

Samples - 비트 패킹된 raw 샘플 스트림입니다. 길이는 ceil(GridPoints * M * BitsPerSample / 8)바이트와 같아야 하며, 패딩은 필요한 경우 마지막 바이트에만 허용됩니다. HotPDF는 지원하는 모든 패킹 깊이를 검증하고, 전달된 바이트를 indirect 스트림 객체에 그대로 복사합니다. 비트 패킹이 올바른지는 호출자의 책임입니다.

로드된 페이지 평가는 1~4개의 입력과 출력, 명시적인 정방향 또는 역방향 /Encode, 독립적인 /Decode, 다중선형 /Order 1, 다차원 3차 /Order 3, 1차원 natural cubic spline을 지원합니다. 검증된 샘플 바이트와 보간 메타데이터는 8개 항목, 64 MiB짜리 LRU에 유지되어, 반복되는 tint, 셰이딩, soft mask, transfer function 호출에 재사용됩니다. HotPDF v2.544.0부터 사용할 수 있습니다.

 

반환 값: indirect THPDFStreamObject이며, Function 사전이 필요한 곳 어디에나 붙일 수 있습니다(보통 AddValue로 다른 사전에 indirect 참조를 넘기거나, 셰이딩 / separation 빌더에 전달합니다). 이 객체는 문서의 IndirectObjects 목록이 소유하며 문서가 끝날 때 해제됩니다. nil을 반환하는 경우는 StrictVersionLock이 켜져 있고 현재 Version이 PDF 1.2 미만일 때입니다(그렇지 않으면 문서 버전이 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;

 

See Also

RegisterAxialGradient, RegisterDeviceN, RegisterSeparation, Version, PDF Filter Support