【问题标题】:Downsampling Images with SwiftUI使用 SwiftUI 对图像进行下采样
【发布时间】:2020-09-09 03:16:41
【问题描述】:

我在我的应用程序中显示从网络下载的图像,但我想对它们进行下采样,这样它们就不会占用数 MB 的内存。我以前可以用 UIKit 轻松做到这一点:

func resizedImage(image: UIImage, for size: CGSize) -> UIImage? {
    let renderer = UIGraphicsImageRenderer(size: size)
    return renderer.image { (context) in
        image.draw(in: CGRect(origin: .zero, size: size))
    }
}

还有其他方法,但它们都依赖于知道图像视图的所需大小,这在 SwiftUI 中并不简单。

是否有专门用于下采样 SwiftUI 图像的良好 API/方法?

【问题讨论】:

  • 您想要的视图大小是什么?
  • 我不确定,我想我可以使用 GeometryReader?如果这就是您的意思,我想将图像的实际渲染大小缩小到任何尺寸
  • 然后你就可以使用和你一样的功能,用Image(uiImage: ...)创建图像。
  • 您可以使用 CIFilter 按比例而不是 cgsize 缩小样本

标签: swift swiftui downsampling


【解决方案1】:

此方法使用 CIFilter 缩小 UIImage

https://developer.apple.com/library/archive/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/CILanczosScaleTransform

public extension UIImage {
    func downsampled(by reductionAmount: Float) -> UIImage? {

        let image = UIKit.CIImage(image: self)
        guard let lanczosFilter = CIFilter(name: "CILanczosScaleTransform") else { return nil }
        lanczosFilter.setValue(image, forKey: kCIInputImageKey)
        lanczosFilter.setValue(NSNumber.init(value: reductionAmount), forKey: kCIInputScaleKey)

        guard let outputImage = lanczosFilter.outputImage else { return nil }
        let context = CIContext(options: [CIContextOption.useSoftwareRenderer: false])
        guard let cgImage = context.createCGImage(outputImage, from: outputImage.extent) else { return nil}
        let scaledImage = UIImage(cgImage: cgImage)

        return scaledImage
    }
}

然后就可以在 SwiftUI View 中使用了

struct ContentView: View {
    var body: some View {
        if let uiImage = UIImage(named: "sample")?.downsampled(by: 0.3) {
            Image(uiImage: uiImage)
        }
    }
}

【讨论】:

  • 我怎么知道要设置什么作为reductionAmount?通常 UIKit 下采样技术依赖于知道你想要显示的图像的 imageView 帧,以及下采样以适应该帧。我的问题是 SwiftUI 没有带有框架属性的 ImageView。
  • @bze12 当您知道缩小多少时,可以使用此方法。 1.0 是默认值,您可以设置低于 1.0 来缩小。
  • 是的,我知道,但我的意思是我不知道要缩小多少。
【解决方案2】:

我最终用几何阅读器解决了这个问题,这并不理想,因为它有点弄乱了布局。

@State var image: UIImage
var body: some View {
   GeometryReader { geo in
       Image(uiImage: self.image)
           .resizable()
           .aspectRatio(contentMode: .fit)
           .onAppear {
               let imageFrame = CGRect(x: 0, y: 0, width: geo.size.width, height: geo.size.height)
               self.downsize(frame: imageFrame) // call whatever downsizing function you want
           }
      }
}

使用几何代理来确定图像的帧,然后下采样到该帧。我希望 SwiftUI 有自己的 API。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-08-08
    • 1970-01-01
    • 2014-05-04
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 2019-05-09
    • 1970-01-01
    相关资源
    最近更新 更多