Write Custom Filters

Easily create your own filters with Photoshop, Lightroom presets, 3D LUT files, or your favorite photo editing application. An RGB lookup image is used to remap the colors in photos and videos. This is the same method used by common social media apps. For more complex filters you can chain GPUImage3 operations e.g. LookupFilter –> Saturation –> Sharpen.

Step 1: Open any test image of your choosing in your photo editor.

Step 2: Apply filters and changes to the test image until you are satisfied with the end result.

Step 3: Download the original lookup.png image from the repository and open it in your photo editor.

Step 4: Apply the same changes you made on your test image to the lookup.png image and save the result to a new image lookup_example.png. Do not downsize the lookup image, reduce its quality or change its format. In some photo editors you can simply copy your adjustment layers from your test image to the lookup image.

Note: Each pixel color must be independent of other pixels (e.g. sharpen will not work). If you need a more complex filter you can chain GPUImage3 operations e.g. LookupFilter –> Sharpen –> Saturation. An example of chaining operations is also included in the Xcode sample project.

Step 5: Use the below code to create your own SessionFilter subclass that utilizes a LookupFilter operation and your newly created lookup_example.png image. Be sure to add your lookup_example.png image to your Xcode project.

import Foundation
import PixelSDK
import GPUImage

class SessionFilterExample: SessionFilter {
    public required init() {


    public required init(from decoder: Decoder) throws {
        try super.init(from: decoder)


    public override func encode(to encoder: Encoder) throws {
        try super.encode(to: encoder)

    func commonInit() {
        self.displayName = "Example Filter"
        self.version = "1.0"
        self.cameraThumbnailImage = UIImage(named: "thumbnail_example.png")

        // self.normalizedIntensityDefault = 100 // This value gets computed
        self.normalizedIntensityRange = (0, 100)
        self.actualIntensityDefault = 1
        self.actualIntensityRange = (0, 1)

    override public func operation() -> ImageProcessingOperation {
        let lookupFilter = LookupFilter()

        do {
            lookupFilter.lookupImage = try PictureInput(image: UIImage(named: "lookup_example.png")!)
        catch {
            print("ERROR: Unable to create PictureInput \(error)")

        return lookupFilter

    override public func operationUpdateNeeded(_ op: ImageProcessingOperation) {
        let op = op as! LookupFilter

        op.intensity = Float(self.actualIntensity)

Step 6: Include your custom filter in the list of available filters. Do this before you present the ContainerController or EditController.

PixelSDK.shared.primaryFilters = [
    SessionFilterExample(), // Your custom filter

That’s it! Enjoy your new custom filter.