   # Working With Functions

This topic contains the following sections: Overview

PDF is not a programming language, and a PDF file is not a program. However, PDF does provide several types of function objects that represent parameterized classes of functions, including mathematical formulas and sampled representations with arbitrary resolution. Functions are used in various ways in PDF, including device-dependent rasterization information for highquality printing (halftone spot functions and transfer functions), color transform functions for certain color spaces, and specification of colors as a function of position for smooth shadings.

Functions in PDF represent static, self-contained numerical transformations. A function to add two numbers has two input values and one output value:

f(x0 , x1) = x0 + x1

Similarly, a function that computes the arithmetic and geometric mean of two numbers could be viewed as a function of two input values and two output values. In general, a function can take any number (Inputs) of input values and produce any number (Outputs) of output values:

f(x0 , ..., xinputs - 1) = y0 , youtputs - 1

In PDF functions, all the input values and all the output values are numbers, and functions have no side effects.

Each function has a Domain property, the set of legal values for the input. Some types of functions also has a Range property, the set of legal values for the output. Input values passed to the function are clipped to the domain, and output values produced by the function are clipped to the range. For example, suppose the function

f(x) = x + 2

is defined with a domain of [−1 1]. If the function is called with the input value 6, that value is replaced with the nearest value in the defined domain, 1, before the function is evaluated; the resulting output value is therefore 3. Similarly, if the function

f (x0 , x1) = 3 × x0 + x1

is defined with a range of [0 100], and if the input values −6 and 4 are passed to the function (and are within its domain), then the output value produced by the function, −14, is replaced with 0, the nearest value in the defined range.

Four types of functions are available, as indicated by the below diagram:

Open in full size All of the above classes are derived from the abstract class PdfFunction

 PdfFunctionInputs The number of input values. PdfFunctionOutputs The number of output values. PdfFunctionDomain An array of 2 × Inputs numbers. For each i from 0 to Inputs − 1, Domain2i must be less than or equal to Domain2i + 1, and the ith input value, xi, must lie in the interval Domain2i ≤ xi ≤ Domain2i + 1. Input values outside the declared domain are clipped to the nearest boundary value. PdfFunctionRange An array of 2 × Outputs numbers. For each j from 0 to Outputs − 1, Range2j must be less than or equal to Range2j + 1, and the jth output value, yj , must lie in the interval Range2j ≤ yj ≤ Range2j + 1. Output values outside the declared range are clipped to the nearest boundary value. If this property is not set, no clipping is done. Required for PdfFuncSampled and PdfFuncPostScript functions. Type 0 (Sampled) Functions

PdfFuncSampled functions use a sequence of sample values (contained in a Stream) to provide an approximation for functions whose domains and ranges are bounded. The samples are organized as an Inputs-dimensional table in which each entry has Outputs components.

Sampled functions are highly general and offer reasonably accurate representations of arbitrary analytic functions at low expense. For example, a 1-input sinusoidal function can be represented over the range [0 180] with an average error of only 1 percent, using just ten samples and linear interpolation. Two-input functions require significantly more samples but usually not a prohibitive number if the function does not have high frequency variations.

The dimensionality of a sampled function is restricted only by implementation limits. However, the number of samples required to represent functions with high dimensionality multiplies rapidly unless the sampling resolution is very low. Also, the process of multilinear interpolation becomes computationally intensive if the number of inputs is greater than 2. The multidimensional spline interpolation is even more computationally intensive.

 NumOfSamples An array of Inputs positive integers specifying the number of samples in each input dimension of the sample table. Bps The number of bits used to represent each sample. (If the function has multiple output values, each one occupies Bps bits.) Valid values are 1, 2, 4, 8, 12, 16, 24, and 32 Order The order of interpolation between samples. Valid values are 1 and 3, specifying linear and cubic spline interpolation, respectively. Default value: 1. Encode An array of 2 × Inputs numbers specifying the linear mapping of input values into the domain of the function’s sample table. Default value: [0 (NumOfSamples0 − 1) 0 (NumOfSamples1 − 1) …]. Decode An array of 2 × Outputs numbers specifying the linear mapping of sample values into the range appropriate for the function’s output values. Default value: same as the value of Range. Samples The sample table.

The Domain, Encode, and NumOfSamples properties determine how the function’s input variable values are mapped into the sample table. For example, if NumOfSamples is [21 31], the default Encode array is [0 20 0 30], which maps the entire domain into the full set of sample table entries. Other values of Encode may be used.

To explain the relationship between Domain, Encode, NumOfSamples, Decode, and Range, we use the following notation:

y = Interpolate(x, xmin , xmax , ymin , ymax) = ymin + (x - xmin) × (ymax - ymin) / (xmax - xmin)

For a given value of x, Interpolate calculates the y value on the line defined by the two points (xmin , ymin) and (xmax , ymax).

When a sampled function is called, each input value xi , for 0 ≤ i < Inputs, is clipped to the domain:

xi' = min(max(xi , Domain2i), Domain2i + 1)

That value is encoded:

ei = Interpolate(xi' , Domain2i, Domain2i + 1 , Encode2i , Encode2i + 1)

That value is clipped to the size of the sample table in that dimension:

ei' = min(max(ei , 0), NumOfSamplesi - 1)

The encoded input values are real numbers, not restricted to integers. Interpolation is used to determine output values from the nearest surrounding values in the sample table. Each output value rj, for 0 ≤ j < Outputs, is then decoded:

rj' = Interpolate(rj , 0, 2Bps - 1 , Decode2j , Decode2j + 1)

Finally, each decoded value is clipped to the range:

yj = min(max(rj' , Range2j), Range2j + 1)

Sample data int the Stream is represented as a stream of unsigned 8-bit bytes (integers in the range 0 to 255). The bytes constitute a continuous bit stream, with the high-order bit of each byte first. Each sample value is represented as a sequence of Bps bits. Successive values are adjacent in the bit stream; there is no padding at byte boundaries.

For a function with multidimensional input (more than one input variable), the sample values in the first dimension vary fastest, and the values in the last dimension vary slowest. For example, for a function f(a, b, c), where a, b, and c vary from 0 to 9 in steps of 1, the sample values would appear in this order: f(0, 0, 0), f(1, 0, 0), …, f(9, 0, 0), f(0, 1, 0), f(1, 1, 0), …, f(9, 1, 0), f(0, 2, 0), f(1, 2, 0), …, f(9, 9, 0), f(0, 0, 1), f(1, 0, 1), and so on.

For a function with multidimensional output (more than one output value), the values are stored in the same order as Range. Type 2 (Exponential Interpolation) Functions

PdfFuncExponential functions include a set of parameters that define an exponential interpolation of one input value and Outputs output values:

f(x) = y0 , ..., youtputs - 1

 ValuesAt0 An array of Outputs numbers defining the function result when x = 0.0. Default value: [0.0]. ValuesAt1 An array of Outputs numbers defining the function result when x = 1.0. Default value: [1.0]. Exponent The interpolation exponent. Each input value x will return Outputs values, given by yj = ValuesAt0j + xExponent × (ValuesAt1j − ValuesAt0j), for 0 ≤ j < Outputs.

Values of Domain must constrain x in such a way that if Exponent is not an integer, all values of x must be non-negative, and if Exponent is negative, no value of x may be zero. Typically, Domain is declared as [0.0 1.0], and Exponent is a positive number. The Range is optional and can be used to clip the output to a specified range. Note that when Exponent is 1, the function performs a linear interpolation between ValuesAt0 and ValuesAt1; therefore, the function can also be expressed as a sampled function (PdfFuncsampled). Type 3 (Stitching) Functions

PdfFuncStitching functions define a stitching of the subdomains of several 1-input functions to produce a single new 1-input function. Since the resulting stitching function is a 1-input function, the domain is given by a two-element array, [Domain0 Domain1].

 Functions An array of k 1-input functions making up the stitching function. The output dimensionality of all functions must be the same, and compatible with the value of Range if Range is present. Bounds An array of k − 1 numbers that, in combination with Domain, define the intervals to which each function from the Functions array applies. Bounds elements must be in order of increasing value, and each value must be within the domain defined by Domain. Encode An array of 2 × k numbers that, taken in pairs, map each subset of the domain defined by Domain and the Bounds array to the domain of the corresponding function.

Domain must be of size 2 (that is, Inputs = 1), and Domain0 must be strictly less than Domain1 unless k = 1. The domain is partitioned into k subdomains, as indicated by the Bounds property, which is an array of k - 1 numbers that obey the following relationships (with exceptions as noted below):

Domain0< Bounds0< Bounds1< ... < Boundsk - 2< Domain1

The Bounds array describes a series of half-open intervals, closed on the left and open on the right (except the last, which is closed on the right as well). The value of the Functions property is an array of k functions. The first function applies to x values in the first subdomain, Domain0 ≤ x < Bounds0; the second function applies to x values in the second subdomain, Bounds0 ≤ x < Bounds1; and so on.

The last function applies to x values in the last subdomain, which includes the upper bound: Boundsk − 2 ≤ x ≤ Domain1. The value of k may be 1, in which case the Bounds array is empty and the single item in the Functions array applies to all x values, Domain0 ≤ x ≤ Domain1.

The Encode array contains 2 × k numbers. A value x from the ith subdomain is encoded as follows:

x' = Interpolate(x, Boundsi - 1 , Boundsi , Encode2i , Encode2i + 1)

for 0 ≤ i < k. In this equation, Bounds-1 means Domain0, and Boundsk - 1 means Domain1. If the last bound, Boundsk - 2, is equal to Domain1, then x' is defined to be Encode2i.

The stitching function is designed to make it easy to combine several functions to be used within one shading pattern over different parts of the shading’s domain. (Shading patterns are discussed in section “Shading Patterns.”) The same effect could be achieved by creating a separate shading for each of the functions, with adjacent domains. However, since each shading would have similar parameters, and because the overall effect is one shading, it is more convenient to have a single shading with multiple function definitions. Type 4 (PostScript Calculator) Functions

A PdfFuncPostScript function, also called a PostScript calculator function, is represented as a stream containing code written in a small subset of the PostScript language. Although any function can be sampled (in a PdfFuncSampled function) and others can be described with exponential functions (PdfFuncExponential), PdfFuncPostScript functions offer greater flexibility and potentially greater accuracy. For example, a tint transformation function for a hexachrome (six-component) CsDeviceN color space with an alternate color space of CsDeviceCMYK (see “DeviceN Color Spaces”) requires a 6-in, 4-out function. If such a function were sampled with Inputs values for each input variable, the number of samples, 4 × Inputs6, could be prohibitively large. In practice, such functions are often written as short, simple PostScript functions.

PdfFuncPostScript functions also make it possible to include a wide variety of halftone spot functions without the loss of accuracy that comes from sampling, and without adding to the list of predefined spot functions. All of the predefined spot functions can be written as PdfFuncPostScript functions.

The language that can be used in a PdfFuncPostScript function contains expressions involving integers, real numbers, and boolean values only. There are no composite data structures such as strings or arrays, no procedures, and no variables or names. The below Table lists the operators that can be used in this type of function.

The operand syntax for PdfFuncPostScript functions follows PDF conventions rather than PostScript conventions. The entire code stream defining the function is enclosed in braces { }. Braces also delimit expressions that are executed conditionally by the if and ifelse operators:

boolean {expression} if
boolean {expression1} {expression2} ifelse

The Domain and Range are both required. The input variables constitute the initial operand stack; the items remaining on the operand stack after execution of the function are the output variables. It is an error for the number of remaining operands to differ from the number of output variables specified by Range property or for any of them to be objects other than numbers.

Pdfium.Net SDK provide a stack with room for 100 entries.

#### Operators in PdfFuncPostScript Functions

This section summarizes the PostScript operators that can appear in a PdfFuncPostScript function. For details on these operators, see the PostScript Language Reference.

Arithmetic Operators

operands

operator

result

description

num1 num2

sum

return num1 plus num2

num1 num2

sub

difference

return num1 minus num2

num1 num2

mul

product

return num1 times num2

num1 num2

div

quotient

return num1 divided by num2

int1 int2

idiv

quotient

return int1 divided by int2 as an integer

int1 int2

mod

remainder

return remainder after dividing int1 by int2

num1

neg

num2

return negative of num1

num1

abs

num2

return absolute value of num1

num1

ceiling

num2

return ceiling of num1

num1

floor

num2

return floor of num1

num1

round

num2

round num1 to nearest integer

num1

truncate

num2

remove fractional part of num1

num

sqrt

real

return square root of num

angle

sin

real

return sine of angle degrees

angle

cos

real

return cosine of angle degrees

num den

atan

angle

return arc tangent of num den in degrees

base exponent

exp

real

raise base to exponent power

num

ln

real

return natural logarithm (base e)

num

log

real

return common logarithm (base 10)

num

cvi

int

convert to integer

num

cvr

real

convert to real

Relational, Boolean, and Bitwise Operators

operands

operator

result

description

any1 any2

eq

bool

test equal

any1 any2

ne

bool

test not equal

num1 num2

gt

bool

test greater than

num1 num2

ge

bool

test greater than or equal

num1 num2

lt

bool

test less than

num1 num2

le

bool

test less than or equal

bool1|int1 bool2 |int2

and

bool3|int3

perform logical|bitwise and

bool1|int1 bool2 |int2

or

bool3|int3

perform logical|bitwise inclusive or

bool1|int1 bool2 |int2

xor

bool3|int3

perform logical|bitwise exclusive or

bool1|int1

not

bool2|int2

perform logical|bitwise not

int1 shift

bitshift

int2

perform bitwise shift of int1 (positive is left)

-

true

true

return boolean value true

-

false

false

return boolean value false

Conditional Operators

operands

operator

result

description

bool {expr}

if

-

execute expr if bool is true

bool {expr1} {expr2}

ifelse

-

execute expr1 if bool is true, expr2 if false

Stack Operators

operands

operator

result

description

any

pop

-

any1 any2

exch

any2 any1

exchange top two elements

any

dup

any any

duplicate top element

any1 ... anyn n

copy

any1 ... anyn any1 ... anyn

duplicate top n elements

anyn ... any0 n

index

anyn ... any0 anyn

duplicate arbitrary element

anyn-1 ... any0 n j

roll

any(j-1) mod n ... any0 anyn-1 ... anyj mod n

roll n elements up j times

#### Errors in Type 4 Functions

Any errors detected by the scanner are considered to be errors in the PDF file. See Also