我刚刚开始学习Xcode、SwiftUI等。通过创建一个学习应用程序,这也是有用的。我能够将数据导入为[UInt 16]并将其缩放为[UInt 8],以显示为灰度图像。我创建了一个CGImage,它被分配给一个状态变量,但我得到了这个错误:
2023-06-13 10:03:04.497662-0700 DisplayFM 2 Image [6160:76497] [default] CGSWindowShmemCreateWithPort在端口0失败
我在CGImage创建后有一个断点;当我在调试会话中检查图像时,图像显示!看起来我正在做正确的事情,但是当我在调试中“继续”时,错误出现了。我一直无法弄清楚错误是在哪里产生的,但认为它是在显示/视图中。我将缩放后的[UInt 8]和图像元数据保存在类TheImage的示例theImage中。
我怀疑cgImage在函数“createCGImageFromUint 8“返回后没有保留指向图像数据的指针(或类似的),或者GeometryReader中的代码不正确。
其目的是允许用户拾取包含图像数据的文件,显示数据,并让用户在工具提示处检查未缩放的数据,然后使用另一个数据集重复。
(It具有讽刺意味的是,该应用程序的早期版本可以工作,但我没有使用最佳实践-加载和缩放图像的ContentView代码可能会在每次ContentView更新时调用。)
import SwiftUI
import CoreGraphics
// Calculates a Core Graphics image as ContentView's
// State variable "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)!
// break point
print("Return from createCGImageFromUint8")
// Looking at cgImage in debug at this breakpoint
// displays the image!
}
这是我的ContentView的开始:
import SwiftUI
import CoreGraphics
var theImage = TheImage() // Image vars, file
struct ContentView: View {
@State var haveNewImage: Bool = false
@State private var cgImage: CGImage? = nil
// @State var imageDataView: (any View)? // what's this?
var body: some View {
VStack(alignment: .leading ) {
FilePickerView(cgImage: $cgImage)
.padding() // at upper left corner WORKS
// If a new file was picked: process and display it.
if theImage.isNew { // displays image etc. GOAT
Text("DEBUG New Image")
CGImageView(cgImage: $cgImage)
} else {
HStack {
Spacer()
Text("Image not yet selected.")
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 = "" // to display tooltip
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!") // do something
}
.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): // col, row
let dn = theImage.getToolTipValue(mouse: location)
dnText = "raw DN \(dn)"
print("---> location x: \(location.x)")
case .ended:
break
}
}
.padding(10)
Text("Mimimum \(minMax[0])\nMaximum \(minMax[1])\n\(dnText)")
}
}
}
1条答案
按热度按时间snz8szmq1#
在创建一个工作的最小示例时,我发现CGImage是不可变的,我有效地改变了它。我通过将CGImage与生成CGImage的代码沿着存储在我的TheImage类中来修复这个问题。
ContentView:
这个类保存缩放后的数组(并将保存原始数据)和对数据进行操作的函数。
最后,ImageView包括一点显示糖。