Is anyone using the new CIRAWFilter API successfully? This is the one introduced in iOS 15, not the OG one. I'm able to instantiate the class and get an output image, but as soon as I try to use the same instance a second time (in any way), I get a crash.
I'm storing the CIRAWFilter in an instance variable to tweak its parameters (such as exposure
) later, but while the CIRAWFilter object is retained, it seems like it's an empty shell. It either crashes with EXC_BAD_ACCESS
or responds that it was sent an unrecognized selector.
Makes it tough to adopt this new API!
Here's a reproducible code sample for the curious (make sure to add a RAW file called example.dng
to the bundle):
import SwiftUI
import Photos
import CoreImage
import CoreImage.CIFilterBuiltins
final class FilterHolder: ObservableObject {
var rawFilter: CIRAWFilter? = nil
}
struct ContentView: View {
enum RawError: String, Error {
case noURL, noFilter, noImage, noCGImage, noAsset, noFullSizeUrl, unhandled
}
@State var image: Image?
@State var rawError: RawError? = nil
@State var ev: Float = 0.0
@StateObject var filterHolder = FilterHolder()
var body: some View {
VStack {
if let image = image {
VStack {
image.resizable()
.aspectRatio(contentMode: .fit)
.frame(maxWidth: .infinity, maxHeight: .infinity)
Slider(value: $ev, in: 0...3)
}
} else {
if let error = rawError {
Text("Error: \(error.localizedDescription)")
} else {
Text("Loading…")
}
}
}.onChange(of: ev) { newValue in
filterHolder.rawFilter?.exposure = newValue
render()
}.onAppear {
loadLocalImage()
}
}
func loadLocalImage() {
do {
guard let url = Bundle.main.url(forResource: "example", withExtension: "dng") else {
throw RawError.noURL
}
guard let filter = CIRAWFilter(imageURL: url) else {
throw RawError.noFilter
}
filter.neutralTemperature = 5600.0
filterHolder.rawFilter = filter
render()
} catch {
rawError = .unhandled
}
}
func render() {
do {
guard let output = filterHolder.rawFilter?.outputImage else {
throw RawError.noImage
}
let context = CIContext(options: nil)
guard let cgImage = context.createCGImage(output, from: output.extent) else {
throw RawError.noCGImage
}
image = Image(uiImage: UIImage(cgImage: cgImage))
} catch {
rawError = .unhandled
}
}
}
The image should load correctly once, but when the slider is adjusted, you'll see the crash.
Filed as FB9524345