Supporting HDR images in your app

Source

Load, display, edit, and save HDR images using SwiftUI and Core Image. ​

Overview

This sample code project shows how to read, write, edit, and display HDR images using SwiftUI, UIKit, AppKit, Core Image, and Core Graphics. It loads a film strip of multiple images from on-disk or from the Photos library. Then it allows you to select, edit, and save an image in HDR. The sample uses several new APIs in various frameworks to correctly handle HDR images in a complete HDR workflow. ​

Configure the sample code project

Before you run this sample code project in Xcode, ensure you're using iOS 17 or later for the iOS target, and macOS 14 or later for the Mac target. ​

Enable HDR on image views

To turn on HDR in the SwiftUI image view, the sample uses the allowedDynamicRange modifier in the film strip to show limited HDR headroom.

FilmStrip(assets: $assets, selectedAsset: $selectedAsset)
    .allowedDynamicRange(.constrainedHigh)
    .frame(height: geometry.size.height / 10.0)

​For the UIKit main image view, the sample adds the preferredImageDynamicRange property to the UIImageView. ​

let view = UIImageView()
view.preferredImageDynamicRange = .high

​ ​For AppKit, the sample adds the property to the NSImageView.

let view = NSImageView()
view.preferredImageDynamicRange = .high

​​ ​

Edit HDR using Core Image

To ensure Core Image reads Gain Map HDR images as HDR, the sample sets the CIImageOption.expandToHDR property to true. To modify the HDR image data, it uses CIFilter filters.

let ciOptions: [CIImageOption: Any] = [.applyOrientationProperty: true, .expandToHDR: true]

​ ​The sample saves the image to disk if it's an on-disk file to begin with. The sample uses a CIContext and CGImageDestination to render a CIImage into a CGImage and write it to a 10-bit HEIC image file.

let cgImage = context.createCGImage(image,
                                    from: image.extent,
                                    format: .RGB10,
                                    colorSpace: colorspace ?? CGColorSpace(name: CGColorSpace.itur_2100_PQ)!,
                                    deferred: true)

​ ​The sample writes the edited HDR image data back to the Photos library by writing a 10-bit HEIC image to the renderedContentURL of a PHContentEditingOutput object. The sample only uses this path when an image comes from the Photos library using the PhotosPicker.

guard let outputURL = try? output.renderedContentURL(for: .heic) else {
    print("Failed to obtain HEIC output URL.")
    return nil
}