{"id":18031735,"url":"https://github.com/dagronf/cifilterfactory","last_synced_at":"2026-03-16T08:33:29.360Z","repository":{"id":63907279,"uuid":"277427696","full_name":"dagronf/CIFilterFactory","owner":"dagronf","description":"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.","archived":false,"fork":false,"pushed_at":"2024-12-10T23:24:35.000Z","size":3139,"stargazers_count":58,"open_issues_count":0,"forks_count":7,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-01-01T23:22:39.145Z","etag":null,"topics":["cifilter","functional","objective-c","swift"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dagronf.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-07-06T02:50:55.000Z","updated_at":"2024-12-10T23:24:39.000Z","dependencies_parsed_at":"2024-02-05T07:45:59.796Z","dependency_job_id":"419aeac9-b764-4157-bdc7-5cc0524a2740","html_url":"https://github.com/dagronf/CIFilterFactory","commit_stats":{"total_commits":65,"total_committers":1,"mean_commits":65.0,"dds":0.0,"last_synced_commit":"94ac26f18aa7c9d9caf8f7a2208ae2721eaa9304"},"previous_names":[],"tags_count":52,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FCIFilterFactory","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FCIFilterFactory/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FCIFilterFactory/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dagronf%2FCIFilterFactory/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dagronf","download_url":"https://codeload.github.com/dagronf/CIFilterFactory/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":233347504,"owners_count":18662676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cifilter","functional","objective-c","swift"],"created_at":"2024-10-30T10:10:36.173Z","updated_at":"2026-03-16T08:33:29.354Z","avatar_url":"https://github.com/dagronf.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# CIFilterFactory\n\nSwift and Objective-C generated classes for built-in CIFilter types. Type safe, auto-complete friendly and (mostly) documented.\n\nSupports macOS, tvOS, iOS and mac Catalyst\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/v/tag/dagronf/CIFilterFactory\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/macOS-10.11+-red\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/iOS-10+-blue\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/tvOS-11+-orange\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/mac Catalyst-supported-green\" /\u003e\n    \u003cimg src=\"https://github.com/dagronf/CIFilterFactory/actions/workflows/build.yml/badge.svg\" /\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/Swift-5.4-orange.svg\" /\u003e\n    \u003cimg src=\"https://img.shields.io/badge/License-MIT-lightgrey\" /\u003e\n    \u003ca href=\"https://swift.org/package-manager\"\u003e\n        \u003cimg src=\"https://img.shields.io/badge/spm-compatible-brightgreen.svg?style=flat\" alt=\"Swift Package Manager\" /\u003e\n    \u003c/a\u003e\n\u003c/p\u003e\n\n## Why\n\nI like CIFilters a lot. I've always found the `CIFilter` interfaces to be \n\n1. Hard to use due to the opaque interface (no code completion!), and \n2. 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.\n3. Xcode's documentation for each filter is lacking for the most part.\n4. Information about the OS version in which the CIFilter appeared is buried within the opaque interface. \n\n## What is `CIFilterFactory`?\n\nThis package contains automatically generated type-safe and documented class wrappers for all of the built-in `CIFilter` types. \n\nIt 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.\n\n|   |   |\n|---|---|\n| **Type safety** | All filter attributes are exposed via class properties using type-safe Swift/Objective-C classes and types where possible. |\n| **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. |\n| **Auto-completion** | As the filter attributes are exposed as properties, Xcode can provide autocomplete information while you code. |\n| **Version information** | The generated classes are wrapped in `@available()` to make sure that only the filters your deployment target defines are available. |\n| **Documention** | All classes and attributes are documented such that Xcode can provide \u003cbr/\u003e• meaningful inline documentation. \u003cbr/\u003e• meaningful documentation in the Xcode quick-help inspector. \u003cbr/\u003e• With Xcode 13, you can compile a docarchive and have the full documentation for all filters available within the Xcode documentation viewer |\n\n## TL;DR Show me something!\n\n### Before\n\n```swift\nlet filter = CIFilter(name: \"CICheckerboardGenerator\")!\nfilter.setValue(CIVector(x: 150.0, y: 150.0), forKey: \"inputCenter\")\nfilter.setValue(CIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0), forKey: \"inputColor0\")\nfilter.setValue(CIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0), forKey: \"inputColor1\")\nfilter.setValue(80.0, forKey: \"inputWidth\")\nfilter.setValue(1.0, forKey: \"inputSharpness\")\nlet output = filter.outputImagelet output = filter.outputImage\n```\n\n### After\n\n```swift\nlet filter = CIFF.CheckerboardGenerator()!\nfilter.center = CGPoint(x: 150.0, y: 150.0)\nfilter.color0 = CIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)\nfilter.color1 = CIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0)\nfilter.width = 80.0\nfilter.sharpness = 1.0\nlet output = filter.outputImage\n```\n\n## Features\n\n### Type safety and discovery\n\n`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](https://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.\n\nThis library pulls out the 'soft' string-based parameters eg :-\n\n```swift\n// compiles, but filter is nil as there's a typo in CIBloom\nlet filter = CIFilter(\"CIBLoom\")!\n\n// no code completion, no type safety\nfilter.setValue(11.8, forKey: \"inputRadius\")\n\n// These compile fine, but result in undefined behaviour during runtime.\nfilter.setValue(vector, forKey: \"inputRadius\")\nfilter.setValue(12.0, forKey: \"inputNoodles\")\n```\n\nand creates type-safe parameters like :-\n\n```swift\n// No chance of a poorly named filter\nguard let filter = CIFF.Bloom() else { fatalError() }\n\n// code completion support, type safe, range safe. Read documentation directly in Xcode\nfilter.inputRadius = 11.8\n\n// compile time error, invalid type\nfilter.inputRadius = vector\nfilter.inputTitle = 12.0\n```\n\n### Documentation\n\nCIFilterFactory defines all available documentation inline within the code itself, allowing Xcode to provide useful \nQuick Help for all available filters and parameters.\n\nFor example :-\n\n#### Filter definition\n\n```swift\n/// Accordion Fold Transition\n///\n/// Transitions from one image to another of a differing dimensions by unfolding.\n///\n/// **CIFilter Name**\n/// - CIAccordionFoldTransition\n///\n/// **Availability**\n/// - macOS 10.10, iOS 8, tvOS 8\n///\n/// **Categories**\n/// - BuiltIn (*CICategoryBuiltIn*)\n/// - HighDynamicRange (*CICategoryHighDynamicRange*)\n/// - StillImage (*CICategoryStillImage*)\n/// - Transition (*CICategoryTransition*)\n/// - Video (*CICategoryVideo*)\n///\n/// **Documentation Links**\n/// - [CIAccordionFoldTransition Online Documentation](http://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIAccordionFoldTransition)\n/// - [CoreImage.CIFilterBuiltins Xcode documentation](https://developer.apple.com/documentation/coreimage/ciaccordionfoldtransition)   /// - [CIFilter.app documentation](https://cifilter.app/CIAccordionFoldTransition/)\n@available(macOS 10.10, iOS 8, tvOS 8, *)\n@objc(CIFFAccordionFoldTransition) class AccordionFoldTransition: Core {\n```\n\n#### Api parameter definition\n\n```swift\n/// The width of each bar.\n///\n/// CIFilter attribute information\n/// - Attribute key: `inputWidth`\n/// - Internal class: `NSNumber`\n/// - Type: `CIAttributeTypeDistance`\n/// - Minimum Value: `2.0`\n/// - Default Value: `30.0`\n@objc public var width: Double {\n   ...\n}\n\n/// `width` range definition\npublic static let widthRange = PartialRangeFrom\u003cDouble\u003e(2.0)\n```\n\n### Value ranges\n\nA lot of the APIs define minimum and/or maximum values for input values.  Unfortunately, these values are only publicly \nvisible from Apple's documentation or via the programmatic interface.  The generated code embeds the min/max definitions\ninto the code comments, as well as defining clamping ranges for input values to ensure correct behaviour.\nRange definitions for each range-appropriate parameter are also automatically generated and made available for your code\nto validate against if needed.\n\n### OS Dependent types\n\nSome of the supported types (like an affine transform) use different class types depending on the\nplatform (`NSAffineTransform` on macOS, `CGAffineTransform` wrapped in `NSValue` on everything else). This library \ndefines a common AffineTransform class which wraps the os-dependent type meaning that you don't have to your code.\n\n## Functional CIImage interface\n\n### Chainable filters\n\nEach filter that supports an `inputImage` generates an extension on `CIImage` for the filter to allow for\nsimple chaining of filters onto a `CIImage`.  Each call returns either the original image, or a new `CIImage`\nwith the filter applied.\n\nEach functional call also has an `isActive` parameter to allow you to easily enable/disable the filter within the chain.\n\nFor example, the CIBokehBlur filter generates :-\n\n```swift\npublic extension CIImage {\n   /// Apply the 'Bokeh Blur' filter to this image and return a new filtered image\n   ///\n   /// - Parameters:\n   ///   - 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)\n   ///   - ringAmount: The amount of extra emphasis at the ring of the bokeh. (0.0...1.0)\n   ///   - ringSize: The size of extra emphasis at the ring of the bokeh. (0.0...0.2)\n   ///   - softness: No Description (0.0...10.0)\n   ///   - isActive: If true applies the filter and returns a new image, else returns this image\n   /// - Returns: The filtered image, or this image if the filter is not active\n   ///\n   /// Smooths an image using a disc-shaped convolution kernel.\n   ///\n   /// **Categories**: Blur, BuiltIn, HighDynamicRange, StillImage, Video\n   ///\n   /// **Documentation Links**\n   /// - [CIBokehBlur Online Documentation](http://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIBokehBlur)\n   /// - [CoreImage.CIFilterBuiltins Xcode documentation](https://developer.apple.com/documentation/coreimage/ciqrcodegenerator?language=objc)\n   /// - [CIFilter.app documentation](https://cifilter.app/CIBokehBlur/)\n   @inlinable func applyingBokehBlur(\n      radius: Double = CIFF.BokehBlur.radiusDefault,\n      ringAmount: Double = CIFF.BokehBlur.ringAmountDefault,\n      ringSize: Double = CIFF.BokehBlur.ringSizeDefault,\n      softness: Double = CIFF.BokehBlur.softnessDefault,\n      isActive: Bool = true\n   ) -\u003e CIImage {\n      ...\n   }\n}\n```\n\nAnd then, you can simply chain these filters\n\n```swift\nlet myImage = CIImage(...)\nlet filtered = myImage\n   .applyingBokehBlur(radius: 100)\n   .applyingSepiaTone()\n```\n\n### Generation filters\n\nFor generation filters like `CIQRCodeGenerator` (these filters don't have an explicit `inputImage`), a static creator function is generated\n\n```swift\nextension CIImage {\n   /// Create a new CIImage using the 'QR Code Generator' filter\n   ///\n   /// - Parameters:\n   ///   - message: The message to encode in the QR Code\n   ///   - correctionLevel: QR Code correction level L, M, Q, or H.\n   /// - Returns: A new image by running the filter, or nil if the image could not be created\n   ///\n   /// Generate a QR Code image for message data.\n   ///\n   /// **Categories**: BuiltIn, Generator, StillImage\n   ///\n   /// **Documentation Links**\n   /// - [CIQRCodeGenerator Online Documentation](http://developer.apple.com/library/mac/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CIQRCodeGenerator)\n   /// - [CoreImage.CIFilterBuiltins Xcode documentation](https://developer.apple.com/documentation/coreimage/ciqrcodegenerator?language=objc)\n   /// - [CIFilter.app documentation](https://cifilter.app/CIQRCodeGenerator/)\n   @inlinable static func createUsingQRCodeGenerator(\n      message: Data,\n      correctionLevel: String\n   ) -\u003e CIImage? {\n      return CIFF.QRCodeGenerator(\n         message: message,\n         correctionLevel: correctionLevel\n      )?.outputImage\n   }\n}\n```\n\n## How\n\n`CIFilter` provides quite an amazing *programmatic* discovery interface, where you can ask it what filters are registered, the parameters that are accepted for a specific filter and all sorts of useful information like localized argument descriptions etc.  Very cool, but also kinda useless when you're just wanting to create a sepia filter.\n\n`CIFilterFactory` is automatically generated using a swift script file, which enumerates the available filters on the system and builds up a type-safe class structure for each of the filters.  It also uses the discovery apis to document the generated code, meaning that Xcode has the ability to fully document each of the created classes.  Not only that, but CIFilter also defines which operating systems it supports (macOS, tvOS, iOS) and when the filter became available, and the generated code takes advantage of this by wrapping generated classes in `#available` calls.\n\nUsing `CIFilterFactory`, Xcode can now :-\n\n* Check available filters for platform/os version at compile time\n* code-complete\n* type check methods and generate error(s) at compile-time\n* clamp input values to defined ranges.\n\nCool!\n\n## Example\n\n### Swift example\n\n#### Using CIFilter methods\n\n```swift\nguard let bloomFilter = CIFilter(name: \"CIBloom\") else { fatalError() }\nbloomFilter.setValue(inputImage, forKey: kCIInputImageKey)\nbloomFilter.setValue(0.3, forKey: kCIInputIntensityKey)\nbloomFilter.setValue(5, forKey: kCIInputRadiusKey)\nlet outputImage = bloomFilter.outputImage\n```\n\n#### Using CIFilterFactory\n\n```swift\nguard let bloomFilter = CIFF.Bloom() else { fatalError() }\nbloomFilter.inputImage = image\nbloomFilter.intensity = 0.3\nbloomFilter.radius = 5\nlet outputImage = bloomFilter.outputImage\n```\n\nUsing the generated interface provides :-\n\n1. Avoid mistakes from incorrect parameter string identifiers\n2. Code completion\n3. Type checking\n4. Automatic range validation\n5. Automatically generate expressive Xcode documentation within the \n\n### Objective-C example\n\n```objc \nid appimage = [NSImage imageNamed:NSImageNameApplicationIcon];\nid bir = [[NSBitmapImageRep alloc] initWithData:[appimage TIFFRepresentation]];\nid image = [[CIImage alloc] initWithBitmapImageRep:bir];\n\nCIFFBloom* filter = [[CIFFBloom alloc] init];\n[filter setInputImage: image];\n[filter setRadius: 10];\n[filter setIntensity: 4];\nCIImage* output = [filter outputImage];\nassert(output != nil);\n```\n\n## What about `import CoreImage.CIFilterBuiltins`?\n\nIn more recent versions of Xcode, the SDK now comes with a pre-generated set of CIFilter classes (like `CIFilter.pixellate()`). This library was written before `CIFilterBuiltins` was available, and was also required to support Objective-C (admittedly, becoming less and less of a problem as time goes on).\n\n* only available for newer versions of Xcode.\n* No objective-c support.\n* Some filters are not available (eg. `CICrop`)\n* Basically undocumented. `CIFilterFactory` embeds ALL the documentation within the generated code so it's directly available when you need it.\n\n## Usage\n\nUse Swift Package Manager. \n\nYou can find some really simple examples for both Swift and Objective-C in the `Demo` subfolder.\n\n## Regenerating CIFilterFactory\n\nNOTE: This is only available for Xcode 13 and later\n\nThere is a project in the `tools/generator` folder, called `ciff_generator`. Open this in XCode 13 and build/run\nthe project.\n\nAdditionally, there is a script in the tools directory which will rebuild the filters and update the Xcode documentation.\n\n1. Open a terminal and navigate to the `CIFilterFactory/tools` folder\n2. run `sh regenerate.sh`\n\n## Generating a docarchive file\n\nNOTE: This is only available for Xcode 13 and later\n\n1. Open a terminal and navigate to the CIFilterFactory/tools folder\n2. run `sh make-docs.sh`\n\n## License\n\n```\nMIT License\n\nCopyright (c) 2026 Darren Ford\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fcifilterfactory","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdagronf%2Fcifilterfactory","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdagronf%2Fcifilterfactory/lists"}