在macOS用SwiftUI显示UInt8数组为图片时遇CGSWindowShmem错误
问题:CGImage赋值状态变量后运行报错,调试时可正常显示
我正在开发实用学习应用,学习Xcode、SwiftUI等技术。目前实现了将[UInt16]数据缩放为[UInt8]生成灰度CGImage的功能,但赋值给状态变量时出现如下错误:
2023-06-13 10:03:04.497662-0700 DisplayFM2Image[6160:76497] [default] CGSWindowShmemCreateWithPort failed on port 0
调试时CGImage能正常显示,但继续运行就触发报错。怀疑是CGImage未保留数据指针,或者GeometryReader代码存在问题。缩放后的[UInt8]数组及元数据存储在自定义类TheImage的实例theImage中。需求是实现文件选择、图片显示,以及通过工具提示查看原始数据的功能。
创建CGImage的函数
import SwiftUI import CoreGraphics // 计算Core Graphics图像并赋值给ContentView的状态变量"cgImage" func createCGImageFromUint8( _ cgImage: inout CGImage?) { let width: Int = theImage.nCols let height: Int = theImage.nRows let numBytes = theImage.scaledArray.count let numComponents = numBytes / (height * width) let colorspace = CGColorSpaceCreateDeviceGray() let grayScaleData = CFDataCreate(nil, theImage.scaledArray, numBytes) let provider = CGDataProvider(data: grayScaleData!)! cgImage = CGImage( width: width, height: height, bitsPerComponent: 8, bitsPerPixel: 8 * numComponents, bytesPerRow: width * numComponents, space: colorspace, //bitmapInfo: CGBitmapInfo(rawValue: 0), bitmapInfo: CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue), provider: provider, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)! // 断点处 print("Return from createCGImageFromUint8") // 在该断点调试时能正常显示cgImage! }
ContentView起始代码
import SwiftUI import CoreGraphics var theImage = TheImage() // 图片相关变量定义在外部文件 struct ContentView: View { @State var haveNewImage: Bool = false @State private var cgImage: CGImage? = nil // @State var imageDataView: (any View)? // 这行代码的作用是什么? var body: some View { VStack(alignment: .leading ) { FilePickerView(cgImage: $cgImage) .padding() // 位于左上角,功能正常 // 如果选择了新文件:处理并显示图片 if theImage.isNew { // 显示图片等功能正常 Text("DEBUG New Image") CGImageView(cgImage: $cgImage) } else { HStack { Spacer() Text("尚未选择图片。") Spacer() } } } }
CGImageView代码
import SwiftUI import CoreGraphics import AppKit struct CGImageView: View { @Binding var cgImage: CGImage? @State private var opacity = 0.0 @State private var minMax = theImage.minMax @State private var dnData: [UInt16] = theImage.backingArray var body: some View { var dnText = "" // 用于显示工具提示 Text(theImage.displayName) .padding(10) HStack { GeometryReader { geometry in // Image(decorative: $cgImage as! CGImage , scale: 1.0) Image(decorative: self.cgImage! , scale: 1.0) .aspectRatio(contentMode: .fit) .border(Color.red) } .frame(width: CGFloat(theImage.nCols), height: CGFloat(theImage.nRows)) .opacity(opacity) .animation(.easeInOut(duration: 1.5), value: opacity) .onAppear { opacity = 1.0 } .onDisappear { opacity = 0.0 } .onTapGesture { print("TAPPED!") // 后续实现功能 } .onHover { (hover: Bool) in if hover { // let mouseLocation = NSEvent.mouseLocation // print("Mouse location: \(mouseLocation)") NSCursor.crosshair.push() } else { NSCursor.pop() } } .onContinuousHover { phase in switch phase { case .active(let location): // 列、行坐标 let dn = theImage.getToolTipValue(mouse: location) dnText = "原始DN值 \(dn)" print("---> 位置x: \(location.x)") case .ended: break } } .padding(10) Text("最小值 \(minMax[0])\n最大值 \(minMax[1])\n\(dnText)") } } }
内容的提问来源于stack exchange,提问作者Nate Lockwood
相关产品推荐
相关产品推荐

