onevcat / Kingfisher

A lightweight, pure-Swift library for downloading and caching images from the web.
MIT License
23.13k stars 2.64k forks source link

使用ResizingImageProcessor Crash #2268

Open intsig171 opened 2 months ago

intsig171 commented 2 months ago
    let thumbnailProcessor = ResizingImageProcessor(referenceSize: CGSize(width: maxLength, height: maxLength), mode: .aspectFit)

    wrappedValue.kf.setImage(
        with: URL(string: urlString),
        placeholder: placeholder,
        options: [
            .processor(thumbnailProcessor),
            .scaleFactor(UIScreen.main.scale),
            .cacheOriginalImage
        ])

在列表中加载图片,崩溃在此。

image

meiyongsheng commented 2 months ago

你这是内存爆了, 如果是大图片的话不建议使用,业界的标准做法一般都是 区域解码

或者这里可以使用

guard let imageSource =  CGImageSourceCreateWithURL(URL, nil) else {
        return nil
    }

    let maxDimensionInPixels = max(pointSize.width, pointSize.height) * scale
    let downsampleOptions = [
        kCGImageSourceCreateThumbnailFromImageAlways: true,
        kCGImageSourceShouldCacheImmediately: true,
        kCGImageSourceCreateThumbnailWithTransform: true,
        kCGImageSourceThumbnailMaxPixelSize: maxDimensionInPixels] as CFDictionary
    guard let downsampledImage = CGImageSourceCreateThumbnailAtIndex(imageSource, 0, downsampleOptions) else {
        return nil
    }

的方式降采样一下 , pointSize 为你将来要降采样到的大小, 这里注意 一定不能先把URL读取出来为data在处理,

可以尝试一下 方式一, 如果还有问题建议采用区域解码

intsig171 commented 2 months ago

我的诉求也挺简单,setImage(with: URL(string: urlString), placeholder: placeholder) 大部分场景下是够用的。 但是有一些异常网络图片(宽高非常大,比如: 16000*17000),导致内存爆掉。 所以我就想做一下兼容处理,如果原始图片尺寸太大的话,就resize一下。 有两个要求: 1. 不能改变图片的原始比例(未下载时尺寸是未知的)。2. 要兼顾在列表中,不要因为异步的问题导致图片错乱。

meiyongsheng commented 2 months ago

建议还是从业务上区分一下, 最起码过滤绝大多数的场景,在集中处理小case事件,针对于超大图,目前比较常见只能是降采样或者区域解码了,不然内存消耗太大的时候容易FOOM

intsig171 commented 2 months ago

很难从业务中区分,异常的大图可能出现在任意地方(数据质量不好)。但是给setImage设置Options又会引起内存的问题。

meiyongsheng commented 2 months ago

因为KF内部的降采样也是先通过能到Data 在进行降采样的

image

你可以尝试在你本地的库中修改一下: 改为传URL进来降采样 看看效果怎样, 并且kCGImageSourceThumbnailMaxPixelSize 是一个上限值, 你根据实际的上限传一下 约束范围(避免影响正常的小图)

make1a commented 1 month ago

我有个疑问,KF 内部 做下采样的时候 是 DownsamplingImageProcessor 把 data 传到 public static func downsampledImage(data: Data, to pointSize: CGSize, scale: CGFloat) -> KFCrossPlatformImage? 方法内实现的。 这里为什么没有使用WWDC 也推荐的 let imageSource = CGImageSourceCreateWithURL(URL, nil) 方案 来优化内存呢?

meiyongsheng commented 1 month ago

目前我们自己的工程里面都是使用 let imageSource = CGImageSourceCreateWithURL(URL, nil) 的方式来进行降采样,因为这个不用读取全部的data,比较节省空间和时间, 但是kf中处理图片在决定是是那个provider 的时候 已经通过 file来读取data,然后再传入作为后续图片的操作,改为CGImageSourceCreateWithURL 你需要看 好不好处理