<!--
{
  "availability" : [
    "iOS: 10.0.0 -",
    "iPadOS: 10.0.0 -",
    "macCatalyst: 13.1.0 -",
    "macOS: 10.12.0 -",
    "tvOS: 10.0.0 -",
    "visionOS: 1.0.0 -"
  ],
  "documentType" : "symbol",
  "framework" : "CoreImage",
  "identifier" : "/documentation/CoreImage/CIImageProcessorKernel",
  "metadataVersion" : "0.1.0",
  "role" : "Class",
  "symbol" : {
    "kind" : "Class",
    "modules" : [
      "Core Image"
    ],
    "preciseIdentifier" : "c:objc(cs)CIImageProcessorKernel"
  },
  "title" : "CIImageProcessorKernel"
}
-->

# CIImageProcessorKernel

The abstract class you extend to create custom image processors that can integrate with Core Image workflows.

```
class CIImageProcessorKernel
```

## Overview

Unlike the [`CIKernel`](/documentation/CoreImage/CIKernel) class and its other subclasses that allow you to create new image-processing effects with the Core Image Kernel Language, the `CIImageProcessorKernel` class provides direct access to the underlying bitmap image data for a step in the Core Image processing pipeline. As such, you can create subclasses of this class to integrate other image-processing technologies—such as Metal compute shaders, [Metal Performance Shaders](https://developer.apple.com/library/archive/releasenotes/General/WhatsNewIniOS/Articles/iOS9.html#//apple_ref/doc/uid/TP40016198-SW7), [Accelerate](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/OSX_Technology_Overview/CoreOSLayer/CoreOSLayer.html#//apple_ref/doc/uid/TP40001067-CH9-SW6) [vImage](https://developer.apple.com/library/archive/releasenotes/Performance/RN-vecLib/index.html#//apple_ref/doc/uid/TP40001049-CH2-SW2) operations, or your own CPU-based image-processing routines—with a Core Image filter chain.

Your custom image processing operation is invoked by your subclassed image processor kernel’s [`process(with:arguments:output:)`](/documentation/CoreImage/CIImageProcessorKernel/process(with:arguments:output:)) method. The method can accept zero, one or more inputs: kernels that generate imagery (such as a noise or pattern generator) need no inputs, while kernels that composite source images together require multiple inputs. The `arguments` dictionary allows the caller to pass in additional parameter values (such as the radius of a blur) and the `output` contains the destination for your image processing code to write to.

The following code shows how you can subclass `CIImageProcessorKernel` to apply the Metal Performance Shader <doc://com.apple.documentation/documentation/MetalPerformanceShaders/MPSImageThresholdBinary> kernel to a [`CIImage`](/documentation/CoreImage/CIImage):

```objc
class ThresholdImageProcessorKernel: CIImageProcessorKernel {
static let device = MTLCreateSystemDefaultDevice()        
override class func process(with inputs: [CIImageProcessorInput]?, arguments: [String : Any]?, output: CIImageProcessorOutput) throws {                
    guard            
        let device = device,            
        let commandBuffer = output.metalCommandBuffer,            
        let input = inputs?.first,            
        let sourceTexture = input.metalTexture,            
        let destinationTexture = output.metalTexture,            
        let thresholdValue = arguments?["thresholdValue"] as? Float else  {                
            return        
        }                
    
    let threshold = MPSImageThresholdBinary(
        device: device,                                                
        thresholdValue: thresholdValue,                                               
        maximumValue: 1.0,                                                
        linearGrayColorTransform: nil)                
    
    threshold.encode(
        commandBuffer: commandBuffer,                         
        sourceTexture: sourceTexture,                         
        destinationTexture: destinationTexture)    
    }
}
```

To apply to kernel to an image, the calling side invokes the image processor’s [`apply(withExtent:inputs:arguments:)`](/documentation/CoreImage/CIImageProcessorKernel/apply(withExtent:inputs:arguments:)) method. The following code generates a new [`CIImage`](/documentation/CoreImage/CIImage) object named `result` which contains a thresholded version of the source image, `inputImage`.

```objc
let result = try? ThresholdImageProcessorKernel.apply( 
    withExtent: inputImage.extent,            
    inputs: [inputImage],            
    arguments: ["thresholdValue": 0.25])
```

> Important:
> Core Image will concatenate filters in a network into as fewer kernels as possible, avoiding the creation of intermediate buffers. However, it is unable to do this with image processor kernels. To get the best performance, you should only use ``doc://com.apple.coreimage/documentation/CoreImage/CIImageProcessorKernel`` objects when your image processing algorithms can’t be expressed as Core Image Kernel Language.

### Subclassing Notes

The [`CIImageProcessorKernel`](/documentation/CoreImage/CIImageProcessorKernel) class is abstract; to create a custom image processor, you define a subclass of this class.

You do not directly create instances of a custom [`CIImageProcessorKernel`](/documentation/CoreImage/CIImageProcessorKernel) subclass. Image processors must not carry or use state specific to any single invocation of the processor, so all methods (and accessors for readonly properties) of an image processor kernel class are class methods.

Your subclass should override at least the [`process(with:arguments:output:)`](/documentation/CoreImage/CIImageProcessorKernel/process(with:arguments:output:)) method to perform its image processing.

If your image processor needs to work with a larger or smaller region of interest in the input image than each corresponding region of the output image (for example, a blur filter, which samples several input pixels for each output pixel), you should also override the [`roi(forInput:arguments:outputRect:)`](/documentation/CoreImage/CIImageProcessorKernel/roi(forInput:arguments:outputRect:)) method.

You can also override the [`formatForInput(at:)`](/documentation/CoreImage/CIImageProcessorKernel/formatForInput(at:)) method and [`outputFormat`](/documentation/CoreImage/CIImageProcessorKernel/outputFormat) property getter to customize the input and output pixel formats for your processor (for example, as part of a multi-step workflow where you extract a single channel from an RGBA image, apply an effect to that channel only, then recombine the channels).

### Using a Custom Image Processor

To apply your custom image processor class to filter one or more images, call the [`apply(withExtent:inputs:arguments:)`](/documentation/CoreImage/CIImageProcessorKernel/apply(withExtent:inputs:arguments:)) class method. (Do not override this method.)

## Topics

### Type Properties

[`outputFormat`](/documentation/CoreImage/CIImageProcessorKernel/outputFormat)

Override this class property if you want your processor’s output to be in a specific pixel format.

[`outputIsOpaque`](/documentation/CoreImage/CIImageProcessorKernel/outputIsOpaque)

Override this class property if your processor’s output stores 1.0 into the
alpha channel of all pixels within the output extent.

[`synchronizeInputs`](/documentation/CoreImage/CIImageProcessorKernel/synchronizeInputs)

Override this class property to return false if you want your processor to be given
input objects that have not been synchronized for CPU access.

### Type Methods

[`apply(withExtent:inputs:arguments:)`](/documentation/CoreImage/CIImageProcessorKernel/apply(withExtent:inputs:arguments:))

Call this method on your Core Image Processor Kernel subclass to create a new image of the specified extent.

[`formatForInput(at:)`](/documentation/CoreImage/CIImageProcessorKernel/formatForInput(at:))

Override this class method if you want your any of the inputs to be in a specific pixel format.

[`process(with:arguments:output:)`](/documentation/CoreImage/CIImageProcessorKernel/process(with:arguments:output:))

Override this class method to implement your Core Image Processor Kernel subclass.

[`roi(forInput:arguments:outputRect:)`](/documentation/CoreImage/CIImageProcessorKernel/roi(forInput:arguments:outputRect:))

Override this class method to implement your processor’s ROI callback.

[`roiTileArray(forInput:arguments:outputRect:)`](/documentation/CoreImage/CIImageProcessorKernel/roiTileArray(forInput:arguments:outputRect:))

Override this class method to implement your processor’s tiled ROI callback.



---

Copyright &copy; 2026 Apple Inc. All rights reserved. | [Terms of Use](https://www.apple.com/legal/internet-services/terms/site.html) | [Privacy Policy](https://www.apple.com/privacy/privacy-policy)