I have data stored in a Data object as [UInt8] to be rendered as a grayscale 8-bit image. I don’t know how to get from a cgImage to an image View. The code below at least compiles up to the lack of a return value but I’m not certain that it is correct. What do I need to add to return the image as a view?
import SwiftUI
struct ImageView_2: View {
var data: Data
var body: some View {
let width = 320
let height = 240
let colorSpace = CGColorSpaceCreateDeviceGray()
let context = CGContext(data: data.castToCPointer(), width: width, height: height, bitsPerComponent: 8, bytesPerRow: width, space: colorSpace, bitmapInfo: CGImageAlphaInfo.alphaOnly.rawValue)
let imageRef = CGContext.makeImage(context!)
let imageRep = NSBitmapImageRep(cgImage: imageRef()!)
let image = imageRep.cgImage
return
// .resizable()
// .aspectRatio(contentMode: .fit)
}
}
The extension to Data:
extension Data {
func castToCPointer<T>() -> T {
return self.withUnsafeBytes { $0.pointee }
}
}
2
Answers
Your
castToCPointer
is undefined behavior and can definitely crash, particularly when optimizations are turned on. It is invalid to access the pointer from a Data outside of thewithUnsafeBytes
closure. Luckily, it’s also unnecessary.The image View in SwiftUI is
Image
, and accepts a NSImage as an input.I haven’t tested it out, but this should do what you’re looking for:
Note that the
!
usage here will crash if the data is in a bad format. You can fix that usingif-let
to check them for nil. In that case, though, you will still need to return a valid View.display CGImage to SwiftUI: