jdekock/colorblinds
A Swift Package for simulating color blindness in iOS apps. Uses GPU-accelerated color transformation for real-time, full frame rate simulation.
Requirements
- iOS 17+
- Swift 5.9+
Installation
Add Colorblinds to your project via Swift Package Manager:
https://github.com/jdekock/ColorblindsOr add it to your Package.swift:
dependencies: [
.package(url: "https://github.com/jdekock/Colorblinds", from: "2.0.0")
]Example
<p align="center"> <img src="Assets/example.gif" alt="Colorblinds demo" width="250"> </p>
<table> <tr> <td width="25%"> <center>Normal</center> </td> <td width="25%"> <center>Picker</center> </td> <td width="25%"> <center>Tritanopia</center> </td> <td width="25%"> <center>Achromatopsia</center> </td> </tr> <tr> <td width="25%"> <img src="Assets/example_1.png"></img> </td> <td width="25%"> <img src="Assets/example_2.png"></img> </td> <td width="25%"> <img src="Assets/example_3.png"></img> </td> <td width="25%"> <img src="Assets/example_4.png"></img> </td> </tr> </table>
Usage
SwiftUI
Apply a specific simulation:
import Colorblinds
struct ContentView: View {
var body: some View {
MyAppView()
.colorBlindSimulation(.deuteranopia)
}
}Bind to an optional type (nil removes the filter):
@State private var selectedType: ColorBlindType?
var body: some View {
MyAppView()
.colorBlindSimulation(selectedType)
}Full simulator experience — triple-tap anywhere to open a picker sheet:
var body: some View {
MyAppView()
.colorBlindSimulator()
}Note: Apply the modifier to your content views rather than to a
NavigationStackorTabView. These container views use internal rendering (e.g. navigation bar materials) that conflicts with the Metal shader, resulting in a yellow warning screen.
UIKit
Full simulator experience — call start with your app's window, then triple-tap to open a picker:
import Colorblinds
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options: UIScene.ConnectionOptions) {
guard let windowScene = scene as? UIWindowScene,
let window = windowScene.windows.first else { return }
ColorBlindOverlay.shared.start(in: window)
}Direct control:
// Apply a specific simulation
ColorBlindOverlay.shared.simulate(.protanopia, in: window)
// Remove the simulation
ColorBlindOverlay.shared.stop()Supported Types
| Type | Description | |---|---| | deuteranomaly | Reduced green sensitivity (most common) | | deuteranopia | No green cones | | protanomaly | Reduced red sensitivity | | protanopia | No red cones | | tritanomaly | Reduced blue sensitivity | | tritanopia | No blue cones | | achromatomaly | Reduced overall color sensitivity | | achromatopsia | Complete color blindness |
How It Works
- SwiftUI — Uses a
[[stitchable]]Metal shader via.colorEffect(), running directly in SwiftUI's render pipeline. No screen capture, no overlay. Truly live at full frame rate. - UIKit — Uses
CADisplayLinkto capture the window's layer, applies aCIColorMatrixfilter on the GPU, and renders the result to anMTKViewoverlay.
License
MIT
Package Metadata
Repository: jdekock/colorblinds
Default branch: master
README: README.md