Merge pull request #2080 from dreampiggy/feature_heif_image_format

Add image format detect of HEIC (One type of HEIF which use HEVC codec). This is supported natively in iOS 11 & macOS 10.13
This commit is contained in:
Bogdan Poplauschi 2017-10-27 09:29:32 +03:00 committed by GitHub
commit 62f80e0e3a
4 changed files with 64 additions and 12 deletions

View File

@ -16,7 +16,8 @@ typedef NS_ENUM(NSInteger, SDImageFormat) {
SDImageFormatPNG,
SDImageFormatGIF,
SDImageFormatTIFF,
SDImageFormatWebP
SDImageFormatWebP,
SDImageFormatHEIC
};
@interface NSData (ImageContentType)

View File

@ -14,6 +14,11 @@
#import <MobileCoreServices/MobileCoreServices.h>
#endif
// Currently Image/IO does not support WebP
#define kSDUTTypeWebP ((__bridge CFStringRef)@"public.webp")
// AVFileTypeHEIC is defined in AVFoundation via iOS 11, we use this without import AVFoundation
#define kSDUTTypeHEIC ((__bridge CFStringRef)@"public.heic")
@implementation NSData (ImageContentType)
+ (SDImageFormat)sd_imageFormatForImageData:(nullable NSData *)data {
@ -21,6 +26,7 @@
return SDImageFormatUndefined;
}
// File signatures table: http://www.garykessler.net/library/file_sigs.html
uint8_t c;
[data getBytes:&c length:1];
switch (c) {
@ -33,16 +39,26 @@
case 0x49:
case 0x4D:
return SDImageFormatTIFF;
case 0x52:
// R as RIFF for WEBP
if (data.length < 12) {
return SDImageFormatUndefined;
case 0x52: {
if (data.length >= 12) {
//RIFF....WEBP
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return SDImageFormatWebP;
}
}
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(0, 12)] encoding:NSASCIIStringEncoding];
if ([testString hasPrefix:@"RIFF"] && [testString hasSuffix:@"WEBP"]) {
return SDImageFormatWebP;
break;
}
case 0x00: {
if (data.length >= 12) {
//....ftypheic
NSString *testString = [[NSString alloc] initWithData:[data subdataWithRange:NSMakeRange(4, 8)] encoding:NSASCIIStringEncoding];
if ([testString isEqualToString:@"ftypheic"]) {
return SDImageFormatHEIC;
}
}
break;
}
}
return SDImageFormatUndefined;
}
@ -62,6 +78,12 @@
case SDImageFormatTIFF:
UTType = kUTTypeTIFF;
break;
case SDImageFormatWebP:
UTType = kSDUTTypeWebP;
break;
case SDImageFormatHEIC:
UTType = kSDUTTypeHEIC;
break;
default:
// default is kUTTypePNG
UTType = kUTTypePNG;

View File

@ -33,10 +33,12 @@ CG_EXTERN BOOL SDCGImageRefContainsAlpha(_Nullable CGImageRef imageRef);
/**
This is the image coder protocol to provide custom image decoding/encoding.
These methods are all required to implement.
@note Pay attention that these methods are not called from main queue.
*/
@protocol SDWebImageCoder <NSObject>
@required
#pragma mark - Decoding
/**
Returns YES if this coder can decode some data. Otherwise, the data should be passed to another coder.
@ -90,10 +92,12 @@ CG_EXTERN BOOL SDCGImageRefContainsAlpha(_Nullable CGImageRef imageRef);
/**
This is the image coder protocol to provide custom progressive image decoding.
These methods are all required to implement.
@note Pay attention that these methods are not called from main queue.
*/
@protocol SDWebImageProgressiveCoder <SDWebImageCoder>
@required
/**
Returns YES if this coder can incremental decode some data. Otherwise, it should be passed to another coder.

View File

@ -66,8 +66,8 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
#pragma mark - Decode
- (BOOL)canDecodeFromData:(nullable NSData *)data {
switch ([NSData sd_imageFormatForImageData:data]) {
// Do not support WebP decoding
case SDImageFormatWebP:
// Do not support WebP decoding
return NO;
default:
return YES;
@ -76,8 +76,8 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
- (BOOL)canIncrementallyDecodeFromData:(NSData *)data {
switch ([NSData sd_imageFormatForImageData:data]) {
// Support static GIF progressive decoding
case SDImageFormatWebP:
// Do not support WebP progressive decoding
return NO;
default:
return YES;
@ -394,9 +394,12 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
#pragma mark - Encode
- (BOOL)canEncodeToFormat:(SDImageFormat)format {
switch (format) {
// Do not support WebP encoding
case SDImageFormatWebP:
// Do not support WebP encoding
return NO;
case SDImageFormatHEIC:
// Check HEIC encoding compatibility
return [[self class] canEncodeToHEICFormat];
default:
return YES;
}
@ -469,6 +472,28 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over
return YES;
}
+ (BOOL)canEncodeToHEICFormat
{
static BOOL canEncode = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
NSMutableData *imageData = [NSMutableData data];
CFStringRef imageUTType = [NSData sd_UTTypeFromSDImageFormat:SDImageFormatHEIC];
// Create an image destination.
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, 1, NULL);
if (!imageDestination) {
// Can't encode to HEIC
canEncode = NO;
} else {
// Can encode to HEIC
CFRelease(imageDestination);
canEncode = YES;
}
});
return canEncode;
}
#if SD_UIKIT || SD_WATCH
#pragma mark EXIF orientation tag converter
+ (UIImageOrientation)sd_imageOrientationFromImageData:(nonnull NSData *)imageData {