What's the formal way to verify if my device is capable of encoding images in HEIC format?
Asked Answered
M

2

9

I'm trying to save an image in the HEIC file format using ImageIO. The code looks something like this:

NSMutableData *imageData = [NSMutableData data];

CGImageDestinationRef destination = CGImageDestinationCreateWithData(
    (__bridge CFMutableDataRef)imageData,
    (__bridge CFStringRef)AVFileTypeHEIC, 1, NULL);
if (!destination) {
  NSLog(@"Image destination is nil");
  return;
}

// image is a CGImageRef to compress.
CGImageDestinationAddImage(destination, image, NULL);
BOOL success = CGImageDestinationFinalize(destination);
if (!success) {
  NSLog(@"Failed writing the image");
  return;
}

This works on devices with A10, but fails on older devices and on the simulator (also according to Apple), by failing to initialize the destination and the error message findWriterForType:140: unsupported file format 'public.heic'. I couldn't find any direct way to test if the hardware supports HEIC without initializing a new image destination and testing for nullability.

There are AVFoundation-based APIs for checking if photos can be saved using HEIC, for example using -[AVCapturePhotoOutput supportedPhotoCodecTypesForFileType:], but I don't want to initialize and configure a capture session just for that.

Is there a more direct way to see if the hardware supports this encoding type?

Mahratta answered 27/8, 2017 at 14:11 Comment(0)
M
6

ImageIO has a function called CGImageDestinationCopyTypeIdentifiers which returns a CFArrayRef of the supported types for CGImageDestinationRef. Therefore, the following code can be used to determine whether HEIC encoding is supported on the device:

#import <AVFoundation/AVFoundation.h>
#import <ImageIO/ImageIO.h>

BOOL SupportsHEIC() {
  NSArray<NSString *> *types = CFBridgingRelease(
      CGImageDestinationCopyTypeIdentifiers());
  return [types containsObject:AVFileTypeHEIC];
}
Mahratta answered 4/9, 2017 at 12:37 Comment(0)
L
8

Swift Version:

func supports(type: String) -> Bool {
    let supportedTypes = CGImageDestinationCopyTypeIdentifiers() as NSArray
    return supportedTypes.contains(type)
}

And then just call it with your preferred type (e.g. AVFileTypeHEIC):

if #available(iOS 11.0, *) {
    supports(type: AVFileTypeHEIC)
}
Lewak answered 20/9, 2017 at 13:38 Comment(0)
M
6

ImageIO has a function called CGImageDestinationCopyTypeIdentifiers which returns a CFArrayRef of the supported types for CGImageDestinationRef. Therefore, the following code can be used to determine whether HEIC encoding is supported on the device:

#import <AVFoundation/AVFoundation.h>
#import <ImageIO/ImageIO.h>

BOOL SupportsHEIC() {
  NSArray<NSString *> *types = CFBridgingRelease(
      CGImageDestinationCopyTypeIdentifiers());
  return [types containsObject:AVFileTypeHEIC];
}
Mahratta answered 4/9, 2017 at 12:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.