SkillAgentSearch skills...

CIFilterFactory

Swift and Objective-C generated classes for built-in CIFilter types and functional interface for applying filters to an image. Type safe, auto-complete friendly and (mostly) documented.

Install / Use

/learn @dagronf/CIFilterFactory
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

CIFilterFactory

Swift and Objective-C generated classes for built-in CIFilter types. Type safe, auto-complete friendly and (mostly) documented.

Supports macOS, tvOS, iOS and mac Catalyst

<p align="center"> <img src="https://img.shields.io/github/v/tag/dagronf/CIFilterFactory" /> <img src="https://img.shields.io/badge/macOS-10.11+-red" /> <img src="https://img.shields.io/badge/iOS-10+-blue" /> <img src="https://img.shields.io/badge/tvOS-11+-orange" /> <img src="https://img.shields.io/badge/mac Catalyst-supported-green" /> <img src="https://github.com/dagronf/CIFilterFactory/actions/workflows/build.yml/badge.svg" /> </p> <p align="center"> <img src="https://img.shields.io/badge/Swift-5.4-orange.svg" /> <img src="https://img.shields.io/badge/License-MIT-lightgrey" /> <a href="https://swift.org/package-manager"> <img src="https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat" alt="Swift Package Manager" /> </a> </p>

Why

I like CIFilters a lot. I've always found the CIFilter interfaces to be

  1. Hard to use due to the opaque interface (no code completion!), and
  2. Easy to make basic mistakes such as type mismatches etc. which would be very difficult to identify in a review (for example). Given that the parameters to filters are Any? values, there is no type checking around the api.
  3. Xcode's documentation for each filter is lacking for the most part.
  4. Information about the OS version in which the CIFilter appeared is buried within the opaque interface.

What is CIFilterFactory?

This package contains automatically generated type-safe and documented class wrappers for all of the built-in CIFilter types.

It also includes the scripts used to generate the classes, so that as new built-in CIFilters are added the classes can be easily (re)generated to include the new filters.

| | | |---|---| | Type safety | All filter attributes are exposed via class properties using type-safe Swift/Objective-C classes and types where possible. | | Range clamping | Filters which define valid ranges for attributes have undefined behaviour when the assigned value is outside range. These classes automatically clamp assigned values to the valid range to avoid potential crashes for invalid values. | | Auto-completion | As the filter attributes are exposed as properties, Xcode can provide autocomplete information while you code. | | Version information | The generated classes are wrapped in @available() to make sure that only the filters your deployment target defines are available. | | Documention | All classes and attributes are documented such that Xcode can provide <br/>• meaningful inline documentation. <br/>• meaningful documentation in the Xcode quick-help inspector. <br/>• With Xcode 13, you can compile a docarchive and have the full documentation for all filters available within the Xcode documentation viewer |

TL;DR Show me something!

Before

let filter = CIFilter(name: "CICheckerboardGenerator")!
filter.setValue(CIVector(x: 150.0, y: 150.0), forKey: "inputCenter")
filter.setValue(CIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0), forKey: "inputColor0")
filter.setValue(CIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0), forKey: "inputColor1")
filter.setValue(80.0, forKey: "inputWidth")
filter.setValue(1.0, forKey: "inputSharpness")
let output = filter.outputImagelet output = filter.outputImage

After

let filter = CIFF.CheckerboardGenerator()!
filter.center = CGPoint(x: 150.0, y: 150.0)
filter.color0 = CIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
filter.color1 = CIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)
filter.width = 80.0
filter.sharpness = 1.0
let output = filter.outputImage

Features

Type safety and discovery

CIFilter use string constants to define the argument parameters. Incredibly powerful and extensible but not overly discoverable without having to resort to online documentation like CIFilter.app. And forget Xcode code completion. As the parameter values are defined as String: Any?, you can spend a long time debugging an issue because you put in the wrong key string or an incorrect value type.

This library pulls out the 'soft' string-based parameters eg :-

// compiles, but filter is nil as there's a typo in CIBloom
let filter = CIFilter("CIBLoom")!

// no code completion, no type safety
filter.setValue(11.8, forKey: "inputRadius")

// These compile fine, but result in undefined behaviour during runtime.
filter.setValue(vector, forKey: "inputRadius")
filter.setValue(12.0, forKey: "inputNoodles")

and creates type-safe parameters like :-

// No chance of a poorly named filter
guard let filter = CIFF.Bloom() else { fatalError() }

// code completion support, type safe, range safe. Read documentation directly in Xcode
filter.inputRadius = 11.8

// compile time error, invalid type
filter.inputRadius = vector
filter.inputTitle = 12.0

Documentation

CIFilterFactory defines all available documentation inline within the code itself, allowing Xcode to provide useful Quick Help for all available filters and parameters.

For example :-

Filter definition

/// Accordion Fold Transition
///
/// Transitions from one image to another of a differing dimensions by unfolding.
///
/// **CIFilter Name**
/// - CIAccordionFoldTransition
///
/// **Availability**
/// - macOS 10.10, iOS 8, tvOS 8
///
/// **Categories**
/// - BuiltIn (*CICategoryBuiltIn*)
/// - HighDynamicRange (*CICategoryHighDynamicRange*)
/// - StillImage (*CICategoryStillImage*)
/// - Transition (*CICategoryTransition*)
/// - Video (*CICategoryVideo*)
///
/// **Documentation Links**
/// - [CIAccordionFoldTransition Online Documentation](http://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIAccordionFoldTransition)
/// - [CoreImage.CIFilterBuiltins Xcode documentation](https://developer.apple.com/documentation/coreimage/ciaccordionfoldtransition)   /// - [CIFilter.app documentation](https://cifilter.app/CIAccordionFoldTransition/)
@available(macOS 10.10, iOS 8, tvOS 8, *)
@objc(CIFFAccordionFoldTransition) class AccordionFoldTransition: Core {

Api parameter definition

/// The width of each bar.
///
/// CIFilter attribute information
/// - Attribute key: `inputWidth`
/// - Internal class: `NSNumber`
/// - Type: `CIAttributeTypeDistance`
/// - Minimum Value: `2.0`
/// - Default Value: `30.0`
@objc public var width: Double {
   ...
}

/// `width` range definition
public static let widthRange = PartialRangeFrom<Double>(2.0)

Value ranges

A lot of the APIs define minimum and/or maximum values for input values. Unfortunately, these values are only publicly visible from Apple's documentation or via the programmatic interface. The generated code embeds the min/max definitions into the code comments, as well as defining clamping ranges for input values to ensure correct behaviour. Range definitions for each range-appropriate parameter are also automatically generated and made available for your code to validate against if needed.

OS Dependent types

Some of the supported types (like an affine transform) use different class types depending on the platform (NSAffineTransform on macOS, CGAffineTransform wrapped in NSValue on everything else). This library defines a common AffineTransform class which wraps the os-dependent type meaning that you don't have to your code.

Functional CIImage interface

Chainable filters

Each filter that supports an inputImage generates an extension on CIImage for the filter to allow for simple chaining of filters onto a CIImage. Each call returns either the original image, or a new CIImage with the filter applied.

Each functional call also has an isActive parameter to allow you to easily enable/disable the filter within the chain.

For example, the CIBokehBlur filter generates :-

public extension CIImage {
   /// Apply the 'Bokeh Blur' filter to this image and return a new filtered image
   ///
   /// - Parameters:
   ///   - radius: The radius determines how many pixels are used to create the blur. The larger the radius, the blurrier the result. (0.0...500.0)
   ///   - ringAmount: The amount of extra emphasis at the ring of the bokeh. (0.0...1.0)
   ///   - ringSize: The size of extra emphasis at the ring of the bokeh. (0.0...0.2)
   ///   - softness: No Description (0.0...10.0)
   ///   - isActive: If true applies the filter and returns a new image, else returns this image
   /// - Returns: The filtered image, or this image if the filter is not active
   ///
   /// Smooths an image using a disc-shaped convolution kernel.
   ///
   /// **Categories**: Blur, BuiltIn, HighDynamicRange, StillImage, Video
   ///
   /// **Documentation Links**
   /// - [CIBokehBlur Online Documentation](http://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIBokehBlur)
   /// - [CoreImage.CIFilterBuiltins Xcode documentation](https://developer.apple.com/documentation/coreimage/ciqrcodegenerator?language=objc)
   /// - [CIFilter.app documentation](https://cifilter.app/CIBokehBlur/)
   @inlinable func applyingBokehBlur(
      radius: Double = CIFF.BokehBlur.radiusDefault,
      ringAmount: Double = CIFF.BokehBlur.ringAmountDefault,
      ringSize: Double = CIFF.BokehBlur.ringSizeDefault,
      softness: Double = CIFF.BokehBlur.softnessDefault,
      isActive: Bool = true
   ) -> CIImage {
      ...
   }
}

And then, you can simply chain these filters

let myImage = CIImage(...)
let filtered = myImage
   .applyingBokehBlur(radius: 100)
   .applyingSepiaTone()

Generation filters

For generation filters like CIQRCodeGenerator (these filters don't have a

View on GitHub
GitHub Stars67
CategoryDevelopment
Updated1mo ago
Forks7

Languages

Swift

Security Score

100/100

Audited on Feb 19, 2026

No findings