如何将图像转换为 UIImage

nOk*_*nOk 16 image uiimage swiftui

由于 swiftUI 上的文档不是很好,但我想问一下如何将“图像”转换为“UIImage”或如何将“图像”转换为 pngData/jpgData

let image = Image(systemName: "circle.fill")
let UIImage = image as UIImage
Run Code Online (Sandbox Code Playgroud)

kon*_*iki 17

SwiftUI 不可能发生这样的事情,我敢打赌永远不会。它与整个框架概念背道而驰。但是,您可以这样做:

let uiImage = UIImage(systemName: "circle.fill")
Run Code Online (Sandbox Code Playgroud)
let image = Image(uiImage: uiImage)
Run Code Online (Sandbox Code Playgroud)

  • 如果您想从“Image”视图获取数据,则不能从“Image”本身获取数据,而是从 Image 获取数据的同一位置获取数据。例如,如果您使用 uiImage 对象加载图像,则应该转到该 uiImage 对象。如果视图从文件名获取图像,则应该从文件中获取它。您**永远**无法询问 Image 的二进制文件,这不是框架的设计方式。 (6认同)
  • @kontiki 为什么它违背了整个框架概念? (3认同)

Mah*_* BM 11

没有将 Image 转换为 UIImage 的直接方法。相反,您应该将图像视为视图,并尝试将该视图转换为 UIImage。Image符合View,所以我们已经有了我们需要的View。现在我们只需要将该视图转换为 UIImage。

我们需要 2 个组件来实现这一点。第一个函数将我们的 Image/View 更改为 UIView,第二个函数将我们创建的 UIView 更改为 UIImage。

为方便起见,这两个函数都声明为其适当类型的扩展。

extension View {
// This function changes our View to UIView, then calls another function
// to convert the newly-made UIView to a UIImage.
    public func asUIImage() -> UIImage {
        let controller = UIHostingController(rootView: self)
        
        controller.view.frame = CGRect(x: 0, y: CGFloat(Int.max), width: 1, height: 1)
        UIApplication.shared.windows.first!.rootViewController?.view.addSubview(controller.view)
        
        let size = controller.sizeThatFits(in: UIScreen.main.bounds.size)
        controller.view.bounds = CGRect(origin: .zero, size: size)
        controller.view.sizeToFit()
        
// here is the call to the function that converts UIView to UIImage: `.asUIImage()`
        let image = controller.view.asUIImage()
        controller.view.removeFromSuperview()
        return image
    }
}

extension UIView {
// This is the function to convert UIView to UIImage
    public func asUIImage() -> UIImage {
        let renderer = UIGraphicsImageRenderer(bounds: bounds)
        return renderer.image { rendererContext in
            layer.render(in: rendererContext.cgContext)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

如何使用?

let image: Image = Image("MyImageName") // Create an Image anyhow you want
let uiImage: UIImage = image.asUIImage() // Works Perfectly
Run Code Online (Sandbox Code Playgroud)

奖金

正如我所说,我们将图像视为视图。在这个过程中,我们没有使用 Image 的任何特定特性,唯一重要的是我们的 Image 是一个 View(符合 View 协议)。这意味着通过这种方法,您不仅可以将 Image 转换为 UIImage,还可以将任何 View 转换为 UIImage。

var myView: some View {
// create the view here
}
let uiImage = myView.asUIImage() // Works Perfectly
Run Code Online (Sandbox Code Playgroud)

PS:

请记住,如果您觉得这个答案有用,您可以选择Upvote。只是提醒一下,谢谢:)


小智 11

尝试在视图上添加扩展,如下所示:

extension Image {
    @MainActor
    func getUIImage(newSize: CGSize) -> UIImage? {
        let image = resizable()
            .scaledToFill()
            .frame(width: newSize.width, height: newSize.height)
            .clipped()
        return ImageRenderer(content: image).uiImage
    }
}
Run Code Online (Sandbox Code Playgroud)

你的用例将是

    let image = Image("someFromAssets")
    let size = CGSize(width: 100, height: 100)
    let uiImage = image.getUIImage(newSize: size)

Run Code Online (Sandbox Code Playgroud)


小智 5

从 iOS 16 和 MacOS 13 开始,上面的大多数答案都已过时。现在的答案是使用 ImageRenderer,它旨在将视图(包括图像)转换为 UIImage 和 CGI​​mage。

主要需要注意的是 ImageRenderer 要在主线程中运行,因此您需要使用 GCD 来转换图像。

public func convert(image: Image, callback: @escaping ((UIImage?) -> Void)) {
    DispatchQueue.main.async {
        let renderer = ImageRenderer(content: image)

        // to adjust the size, you can use this (or set a frame to get precise output size)
        // renderer.scale = 0.25
        
        // for CGImage use renderer.cgImage
        callback(renderer.uiImage)
    }
}
Run Code Online (Sandbox Code Playgroud)