Display HDR images for PhotoKit assets

In my app I get a UIImage for a PHAsset via PHImageManager.requestImage(for:targetSize:contentMode:options:resultHandler:). I directly display that image in a UIImageView that has preferredImageDynamicRange set to .high. The problem is I do not see the high dynamic range.

I see the HDRDemo23 sample code uses PhotosPicker to get a UIImage from Data through UIImageReader whose config enables prefersHighDynamicRange.

Is there a way to support HDR when using the Photos APIs to request display images?

And is there support for PHLivePhoto displayed in PHLivePhotoView retrieved via PHImageManager.requestLivePhoto?

Post not yet marked as solved Up vote post of Jordan Down vote post of Jordan
831 views

Replies

I also have the same problem.

PHImageManager requestImageForAsset does not return an HDR image from an HDR video in the library.

Note : Similarly, AVAssetImageGenerator does not return an HDR image from an HDR AVAsset.

Have you managed to find a solution for this? I'm facing the same problem and haven't found a proper way to fetch photos without losing HDR in UIKit.

For images, use the requestImageDataAndOrientation(for:options:resultHandler:) method to obtain a photo’s data, which contains the HDR information. Then you can use CGImageSource, UIImageReader with prefersHighDynamicRange, CIImage, etc. to obtain a UIImage that will correctly display on HDR screens.

For live photos, it’s more complicated. The PHLivePhoto object obtained from requestLivePhoto(for:targetSize:contentMode:options:resultHandler:) does not contain an HDR image. You can use requestImageDataAndOrientation(for:options:resultHandler:) to obtain the HDR version of the image, as above, but displaying it in a PHLivePhotoView is not as simple. There is private API you can use, which I’ll post below, but it’s up to you to decide if that’s risky for you. All private API can be hidden, if the only thing you fear is App Store submission.

fileprivate static func fudgeLiveView(_ liveView: PHLivePhotoView, with image: UIImage?) {
	if let image {
		liveView.setValue(image, forKeyPath: "playerView.overrideImage")
	}
	
	guard let view = liveView.value(forKeyPath: "playerView.subviews.@firstObject") as? UIView else {
		return
	}
	
	for subview in view.subviews {
		if let imageView = subview as? UIImageView {
			imageView.preferredImageDynamicRange = .high
		}
	}
}

I now see that PHImageRequestOptions has the following private properties, which you can use to obtain and fine-tune HDR images using all image loading APIs:

@property (nonatomic) BOOL includeHDRGainMap;
@property (nonatomic) BOOL includeHDRGainMapInIntermediateImage;
@property (nonatomic) BOOL preferHDR;
@property (nonatomic) double targetHDRHeadroom;