Core Image Filter Sampler Configuration

FxCore lets you create Core Image filters through the Custom Kernel and Custom Shader nodes:

Custom Kernel uses the Core Image Kernel Language, whereas Custom Shader is based on the newer Metal Shading Language for Core Image Kernels.

Regardless of the language used, any sampler argument to the kernel is populated with the contents of its corresponding image input.

Custom Sampler Options

Initially, each sampler is configured using default options picked by Core Image: values are sampled using linear interpolation, and sampling from coordinates outside the sampler region return transparent black. The default behavior also guarantees that all color values are converted to the working color space. In other words, regardless of the original color space used by your image data, all values you sample from within your kernel are expressed in terms of the working color space.

You can enable other behaviors by enabling the Customize filtering, region of interest and color space conversion option:

When that option is enabled, every sampler gets additional inputs beyond the image input:

Region of Interest

There are different techniques to specify a custom region-of-interest for each sampler:

  • Inset only: pass non-zero values to the ROI Inset X and ROI Inset Y inputs. The current tile rectangle is shrunk when insets are positive or enlarged when insets are negative.
  • Transform only: pass an affine transform to be applied to the current tile rectangle.
  • Inset + Transform: pass both insets and a non-identity transform. The current tile rectangle is first shrunk or enlarged based on insets, and then a transform is applied.
  • Rectangle: pass a 4-element vector in the ROI Rectangle input that exactly defines the region-of-interest for the corresponding sampler.

When passing a vector to the ROI Rectangle input, the ROI insets and transform are ignored. The ROI Rectangle input effectively overrides the others.

While insets and transforms are applied to the current tile rectangle, the vector you pass to the ROI Rectangle input is used as-is. This behavior makes sense for lookup tables and certain geometric distortions that cannot be made to support tiling.

Wrapping Behavior

The Wrapping input let you select between Transparent Black (the default behavior for all Core Image samplers) and Clamp to Edge.

When Transparent Black is selected, if your kernel samples any values outside the sampler region available when processing the current tile, transparent black is returned.

When Clamp to Edge is selected, if your kernel samples any values outside the sampler region available when processing the current tile, the closest available sample values are returned, i.e. the closest edge.

Filtering Behavior

The Filtering input lets you specify how color values are sampled for any given coordinates:

Linear is the default behavior for all Core Image samplers, and it samples values from up to two pixels, interpolating between them based on the distance of your sampling coordinate from the center of each pixel.

Nearest forces the sampler to only ever sample from one pixel, determined by closest distance from your sampling coordinates.

Color Management

By default, Core Image transparently converts any values in your sampler to the working color space. Unless the working color space has been customized, this corresponds to a linear RGB color space (refer to Core Image docs for more information).

Core Image defaults to a working color space based on a linear RGB color profile. This is the appropriate decision for the vast majority of effects. FxCore allows you to customize the working color space for all kernels and filters in the composition by customizing the current environment.

It may be helpful in some cases to prevent or control the color conversion process for each sampler. FxCore gives you three dynamic choices for your color space conversion:

  • Convert to working color space: this is the default Core Image behavior. All samples are converted from their color space to the working color space used by the Core Image context associated with the composition.
  • Convert to destination color space: all samples are converted to the color space of the current output device, i.e. the display where your composition is rendered. When the custom kernel/shader node is nested within a 3D Render to Texture with a custom color space, the sampler color values are converted to the destination color space specified as an input to the 3D Render to Texture container.
  • Convert to custom color space: this option tells FxCore to convert sampler color values to the color space you specify via a separate input to the node, identified by the Custom Color Space suffix. You can create a suitable input color space via the Create Color Space node.

All other options allow you to convert sampler color values to a specific color space, such as sRGB or sRGB Linear. The list of color spaces advertised by FxCore varies from one version to another, but any color space you choose will continue to be used even if it is no longer listed.

Output Color Space

The options above instruct Core Image to let you sample values from any given sampler in a specific color space, but please remember that your output is still expected to be expressed in terms of the working color space. If you wish to both sample values in a specific color space, and have your kernel output color information in the same color space, you need to customize the output color space of your kernel separately:

Setting the output color space

Setting the output color space

Addendum: Color Kernels

Core Image also supports simplified kernels that only manipulate one color value at a time. Such Color Kernels do not require any sampler options at all, since the kernel function is only given one set of RGBA values for the current pixel being rendered at its destination coordinate.

When editing a kernel based on the Core Image Kernel Language, FxCore will automatically switch to using color kernels when you replace the sampler keyword with __sample:

Notice that the __sample argument is accessed by your kernel as any other vec4 variable.