Getting Started with PixelFlux
This guide walks you through installing PixelFlux and building your first GPU-accelerated image filtering app.
Installation
Using Swift Package Manager
PixelFlux is distributed as a Swift Package. Add it to your project in Xcode:
- Open your project in Xcode
- Navigate to File → Add Packages
- Enter the repository URL:
https://github.com/wailbentafat/PixelFlux.git - Select a version (e.g., main branch for latest development)
- Choose your target and click "Add Package"
CocoaPods Integration
PixelFlux is also available via CocoaPods. Add to your Podfile:
Podfile
target 'YourApp' do
pod 'PixelFlux'
end
Then run pod install.
Requirements
- Minimum iOS Version: iOS 16.0
- Swift Version: 5.9 or later
- Metal Support: A device or simulator with Metal GPU support
Your First Filter
Step 1: Import PixelFlux
Swift
import PixelFlux
import UIKit
Step 2: Create a Filter
Initialize a brightness filter with a brightness adjustment value between -1.0 and 1.0:
Creating a Brightness Filter
do {
let filter = try BrightnessFilter(brightness: 0.3)
// Filter created successfully
} catch {
print("Error creating filter:", error.localizedDescription)
}
Step 3: Apply the Filter
Apply the filter to a UIImage. The operation runs on the GPU and returns a new image:
Applying a Filter to an Image
import PixelFlux
import UIKit
class ImageViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
// Load your image
guard let originalImage = UIImage(named: "myPhoto") else {
print("Image not found")
return
}
// Apply brightness filter
do {
let brightFilter = try BrightnessFilter(brightness: 0.3)
let brightResult = try brightFilter.apply(to: originalImage)
imageView.image = brightResult
} catch {
print("Filter error:", error.localizedDescription)
}
}
}
Using the Convenience API
For simple operations, use the PixelFluxEngine.shared singleton API:
Convenience API Usage
import PixelFlux
let image = UIImage(named: "example")!
// Apply brightness using shared API
do {
let brightened = try PixelFluxEngine.shared.applyBrightness(to: image, brightness: 0.5)
imageView.image = brightened
// Or apply passthrough (identity) filter
let passthrough = try PixelFluxEngine.shared.applyPassthrough(to: image)
anotherImageView.image = passthrough
} catch {
print("Error:", error.localizedDescription)
}
Error Handling
PixelFlux defines a set of errors that may occur during filter creation or application:
PixelFluxError Cases
noCGImage- The input UIImage lacks a CGImage (may be empty or corrupted)metalLibraryNotFound- Metal shader library could not be loadedfunctionNotFound- The requested Metal compute function not found in librarycommandBufferFailed- Failed to create a Metal command bufferbufferCreationFailed- Failed to allocate GPU buffer for shader parameters
Complete Example App
Here's a complete example of a simple image filter app:
Complete ViewController
import UIKit
import PixelFlux
class FilterDemoViewController: UIViewController {
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var brightnessSlider: UISlider!
@IBOutlet weak var resultLabel: UILabel!
var originalImage: UIImage?
override func viewDidLoad() {
super.viewDidLoad()
// Load original image
originalImage = UIImage(named: "demo")
// Set up slider
brightnessSlider.minimumValue = -1.0
brightnessSlider.maximumValue = 1.0
brightnessSlider.value = 0.0
brightnessSlider.addTarget(self, action: #selector(brightnessChanged), for: .valueChanged)
// Display original
imageView.image = originalImage
}
@objc func brightnessChanged() {
guard let original = originalImage else { return }
let brightness = brightnessSlider.value
resultLabel.text = String(format: "Brightness: %.2f", brightness)
do {
let filter = try BrightnessFilter(brightness: brightness)
let result = try filter.apply(to: original)
imageView.image = result
} catch {
resultLabel.text = "Error: \(error.localizedDescription)"
}
}
}
Performance Tips
- Batch Operations: If applying multiple filters, consider creating a pipeline to avoid repeated texture uploads
- Async Processing: Dispatch filter operations to a background queue to keep the UI responsive
- Image Size: Larger images take longer to process. Consider downsampling if processing very large images
- Reuse Filters: Create filter instances once and reuse them to avoid repeated initialization overhead
Troubleshooting
Issue: "Image asset not found"
Make sure your images are added to your app's Assets.xcassets catalog and are set to the correct target membership.
Issue: "Metal library not found"
Ensure the PixelFlux package is properly linked to your target. Check your project's Build Phases → Link Binary With Libraries.
Issue: Image dimensions changed
PixelFlux preserves the image dimensions. If dimensions change, check that you're using the correct scale factor when creating test images.
Next Steps
- Explore the API Reference for detailed documentation
- Read the Architecture guide to understand how PixelFlux works internally
- Build custom filters by implementing the Filter protocol
- Check out the GitHub repository for examples