DitherCam
Real time ordered dithering camera for iOS. Built in Swift Playgrounds, no Mac required.
Camera frames land as Metal textures with no CPU copy, get dithered in a fragment shader, and go straight to the screen at 60fps. The shutter runs the same shader into an offscreen target at the same pixel dimensions as the preview, so the saved photo is identical to the viewfinder rather than a re-render.
DOWNLOAD DitherCam.swiftpm.zip13 KB · iOS 17+Install
- Download the zip on the iPhone or iPad you want to run it on.
- Unzip it in Files. You get a
DitherCam.swiftpmfolder. - Tap it. Swift Playgrounds opens it as an app project. Press Run.
Free Apple ID signing gives you seven days before the app stops launching. Open the project in Swift Playgrounds and press Run again to re-sign. A paid developer account extends that to a year.
Palettes
Bayer 2x2, 4x4 and 8x8. Adjustable pixel size, spread, contrast and brightness. Adding a palette is two lines in Palettes.swift, ceiling is 16 colors.
Source
- Package.swiftmanifest, capabilities
- DitherCamApp.swiftentry point
- ContentView.swiftcamera UI
- CameraController.swiftAVFoundation session
- DitherRenderer.swiftMetal pipeline
- MetalPreview.swiftMTKView wrapper
- Palettes.swiftpalette data
- PhotoSaver.swiftphoto library
- DitherShaders.txtfragment shader
Swift Playgrounds will not build files with a
.metal extension, so the shader ships as .txt and is compiled at launch with MTLDevice.makeLibrary(source:). In the zip it lives in a Resources subfolder. The loose copy above is flattened for browsing.Known limits
- Portrait only. Rotation angle is set once at configure time, which removes the races between capture connection, drawable size and crop math.
- Capture resolution equals preview resolution, roughly 1179 x 2556 on a recent iPhone.
- Bayer only. Floyd-Steinberg is serial and cannot run as a fragment shader.
- No flash, zoom, manual focus or exposure lock.