Back to Nuke

Supported Formats

Documentation/Nuke.docc/Customization/ImageFormats/supported-image-formats.md

13.0.56.2 KB
Original Source

Supported Formats

Nuke has built-in support for basic image formats like jpeg, png, and heif. It also has the infrastructure for supporting a variety of custom image formats.

Nuke is capable of driving progressive decoding, animated image rendering, progressive animated image rendering, drawing vector images directly or converting them to bitmaps, parsing thumbnails included in the image containers, and more.

Common Image Formats

All image formats natively supported by the platform are also supported by Nuke, including PNG, TIFF, JPEG, GIF, BMP, ICO, CUR, XBM, HEIF, and WebP (iOS 14+).

You can use the basic UIImageView/NSImageView/WKInterfaceImage to render the images of any of the natively supported formats.

Progressive JPEG

Decoding

ImageDecoders/Default supports progressive JPEG via CGImageSourceCreateIncremental. When ImagePipeline/Configuration-swift.struct/isProgressiveDecodingEnabled is true, the pipeline produces previews as data arrives.

By default, progressive previews are only enabled for progressive JPEGs and GIFs (ImagePipeline/PreviewPolicy). Baseline JPEGs, PNGs, and other formats produce no previews unless explicitly configured via ImagePipeline/Delegate/previewPolicy(for:pipeline:).

For progressive JPEGs with large EXIF headers where CGImageSourceCreateIncremental fails to produce incremental previews, the decoder automatically falls back to generating a thumbnail from the available data.

Encoding

None.

Rendering

To render progressive JPEG, you can use the basic UIImageView/NSImageView/WKInterfaceImage. The default image view loading extensions also support displaying progressive previews.

HEIF

Decoding

ImageDecoders/Default supports HEIF.

Encoding

ImageEncoders/Default supports HEIF but doesn't use it by default. To enable it, use ImageEncoders/Default/isHEIFPreferred.

You can use ImageEncoders/ImageIO directly:

swift
let image: UIImage
let encoder = ImageEncoders.ImageIO(type: .heif, compressionRatio: 0.8)
let data = encoder.encode(image: image)

Rendering

To render HEIF images, you can use UIImageView/NSImageView/WKInterfaceImage.

GIF

Decoding

ImageDecoders/Default automatically recognizes GIFs. It creates an image container (ImageContainer) with the first frame of the GIF as a placeholder and attaches the original image data to the container so that you can perform just-in-time decoding at rendering time.

Encoding

None.

Rendering

To render animated GIFs, please consider using one of the open-source GIF rendering engines, like Gifu, FLAnimatedImage, or other.

Gifu Example

swift
/// A custom image view that supports downloading and displaying animated images.
final class ImageView: UIView {
    private let imageView: GIFImageView
    private let spinner: UIActivityIndicatorView
    private var task: ImageTask?

    /* Initializers skipped */

    func setImage(with url: URL) {
        prepareForReuse()

        if let response = ImagePipeline.shared.cache[url] {
            imageView.display(response: response)
            if !response.isPreview {
                return 
            }
        }

        spinner.startAnimating()
        task = ImagePipeline.shared.loadImage(with: url) { [weak self] result in
            self?.spinner.stopAnimating()
            if case let .success(response) = result {
                self?.imageView.display(response: response)
            }
        }
    }
    
    private func display(response: ImageResponse) {
        if let data = response.container.data {
            animate(withGIFData: data)
        } else {
            image = response.image
        }
    }
    
    private func prepareForReuse() {
        task?.cancel()
        spinner.stopAnimating()
        imageView.prepareForReuse()
    }
}

To see this code in action, check out the demo project.

GIF is not the most efficient format for transferring and displaying animated images. Consider using short videos instead. You can find a PoC available in the demo project that uses Nuke to load, cache and display an MP4 video.

SVG

Decoding

There is currently no built-in support for SVG. Use ImageDecoders/Empty to pass the original image data to an SVG-enabled view and render it using an external mechanism.

Encoding

None.

Rendering

To render SVG, consider using SwiftSVG, SVG, or other frameworks. Here is an example of SwiftSVG rendering vector images.

swift
ImageDecoderRegistry.shared.register { context in
    // Replace this with whatever works for you. There are no magic numbers
    // for SVG like are used for other binary formats, it's just XML.
    let isSVG = context.urlResponse?.url?.absoluteString.hasSuffix(".svg") ?? false
    return isSVG ? ImageDecoders.Empty() : nil
}

let url = URL(string: "https://upload.wikimedia.org/wikipedia/commons/9/9d/Swift_logo.svg")
ImagePipeline.shared.loadImage(with: url) { [weak self] result in
    guard let self, let data = try? result.get().container.data else {
        return
    }
    // You can render an image using whatever size you want, vector!
    let targetBounds = CGRect(origin: .zero, size: CGSize(width: 300, height: 300))
    let svgView = UIView(SVGData: data) { layer in
        layer.fillColor = UIColor.orange.cgColor
        layer.resizeToFit(targetBounds)
    }
    self.view.addSubview(svgView)
    svgView.bounds = targetBounds
    svgView.center = self.view.center
}

Important: Both SwiftSVG and SVG only support a subset of SVG features.

WebP

WebP is supported natively on macOS 11+, iOS 14+, and watchOS 7+ via Image I/O. No additional plugins are required.