Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AVIF Support #2189

Open
lschaupp opened this issue Jan 4, 2024 · 5 comments
Open

AVIF Support #2189

lschaupp opened this issue Jan 4, 2024 · 5 comments

Comments

@lschaupp
Copy link

lschaupp commented Jan 4, 2024

Any news about AVIF support?

@freemansion
Copy link

Our project currently heavily uses Kingfisher, but we struggle loading images in AVIF format.
Any plans to introduce support of AVIF?
Does anybody found workaround?

@onevcat
Copy link
Owner

onevcat commented Apr 30, 2024

Hi,

As I tried, it seems that the default image processor is already supporting AVIF with UIImageView extension, so I guess you can just give the URL of an AVIF image to Kingfisher and it should just work. See the example in action:

截屏2024-04-30 19 30 21

As I tried under iOS 16 and iOS 17, both seems working fine.

Do you have a case (maybe any earlier iOS versions?) that it does not work?


If the default one does not work in some cases, it is still very easy to integrating any existing AVIF decoder to Kingfisher. Take the avif.swift as example, after importing, you can add these to your project to load an AVIF image:

struct KingfisherAVIFProcessor: ImageProcessor {
    var identifier: String = "KingfisherAVIF"
    
    func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
        switch item {
        case .data(let data):
            return AVIFDecoder.decode(data)
        case .image(let image):
            return image
        }
    }
}

struct KingfisherAVIFSerializer: CacheSerializer {
    func data(with image: Kingfisher.KFCrossPlatformImage, original: Data?) -> Data? {
        return try? AVIFEncoder.encode(image: image, quality: 50)
    }
    
    func image(with data: Data, options: Kingfisher.KingfisherParsedOptionsInfo) -> Kingfisher.KFCrossPlatformImage? {
        return AVIFDecoder.decode(data)
    }
}

And use it as:

imageView.kf.setImage(
  with: url, 
  options: [
    .processor(KingfisherAVIFProcessor()), 
    .cacheSerializer(KingfisherAVIFSerializer())
  ]
)

@freemansion
Copy link

hey @onevcat , thanks for the quick reply! You're right, it works fine in most cases. I forgot to mention, that it doesn't works on iOS 15. I've checked on iPhone 13 mini, iOS 15.4.
But anyway, thanks a lot sharing a workaround, much appreciated!

@onevcat
Copy link
Owner

onevcat commented Apr 30, 2024

thanks for the quick reply! You're right, it works fine in most cases. I forgot to mention, that it doesn't works on iOS 15. I've checked on iPhone 13 mini, iOS 15.4.

For that case, maybe I can recommend to apply the DefaultImageProcessor first, and then if it returns nil, use the method from AVIF specified decoder:

struct KingfisherAVIFProcessor: ImageProcessor {
    var identifier: String = "KingfisherAVIF"
    
    func process(item: ImageProcessItem, options: KingfisherParsedOptionsInfo) -> KFCrossPlatformImage? {
        switch item {
        case .data(let data):
            return DefaultImageProcessor.default.process(item: item, options: options) ?? AVIFDecoder.decode(data)
        case .image(let image):
            return image
        }
    }
}

Then it is possible for you to get the system default implementation if the system can decode the image. Otherwise if for older systems, fallback to the AVIF specified decoders.

@freemansion
Copy link

yeah, keeping default image processor make sense. thanks for sharing thoughts!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants