Add support for built-in ImageIO WebP codec for iOS 14/tvOS 14/macOS 11/watchOS 7
This commit is contained in:
parent
f876da5031
commit
6eacb15067
|
@ -14,9 +14,8 @@
|
|||
#import <MobileCoreServices/MobileCoreServices.h>
|
||||
#endif
|
||||
#import "SDImageHEICCoderInternal.h"
|
||||
#import "SDImageAWebPCoderInternal.h"
|
||||
|
||||
// Currently Image/IO does not support WebP
|
||||
#define kSDUTTypeWebP ((__bridge CFStringRef)@"public.webp")
|
||||
#define kSVGTagEnd @"</svg>"
|
||||
|
||||
@implementation NSData (ImageContentType)
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#import "SDImageAPNGCoder.h"
|
||||
#import "SDImageHEICCoder.h"
|
||||
#import "SDImageHEICCoderInternal.h"
|
||||
#import "SDImageAWebPCoderInternal.h"
|
||||
|
||||
@implementation SDAnimatedImageRep {
|
||||
CGImageSourceRef _imageSource;
|
||||
|
@ -70,6 +71,13 @@
|
|||
[self setProperty:NSImageCurrentFrame withValue:@(0)];
|
||||
NSUInteger loopCount = [SDImageHEICCoder imageLoopCountWithSource:imageSource];
|
||||
[self setProperty:NSImageLoopCount withValue:@(loopCount)];
|
||||
} else if (CFStringCompare(type, kSDUTTypeWebP, 0) == kCFCompareEqualTo) {
|
||||
// WebP
|
||||
// Do initialize about frame count, current frame/duration and loop count
|
||||
[self setProperty:NSImageFrameCount withValue:@(frameCount)];
|
||||
[self setProperty:NSImageCurrentFrame withValue:@(0)];
|
||||
NSUInteger loopCount = [SDImageAWebPCoder imageLoopCountWithSource:imageSource];
|
||||
[self setProperty:NSImageLoopCount withValue:@(loopCount)];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
|
@ -100,6 +108,9 @@
|
|||
} else if (CFStringCompare(type, kSDUTTypeHEICS, 0) == kCFCompareEqualTo) {
|
||||
// HEIC
|
||||
frameDuration = [SDImageHEICCoder frameDurationAtIndex:index source:imageSource];
|
||||
} else if (CFStringCompare(type, kSDUTTypeWebP, 0) == kCFCompareEqualTo) {
|
||||
// WebP
|
||||
frameDuration = [SDImageAWebPCoder frameDurationAtIndex:index source:imageSource];
|
||||
}
|
||||
if (!frameDuration) {
|
||||
return;
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "SDImageIOAnimatedCoder.h"
|
||||
|
||||
/**
|
||||
This coder is used for Google WebP and Animated WebP(AWebP) image format.
|
||||
Image/IO provide the WebP support in iOS 14/macOS 11/tvOS 14/watchOS 7+.
|
||||
@note If you need to support lower firmware version for WebP, you can have a try at https://github.com/SDWebImage/SDWebImageWebPCoder
|
||||
*/
|
||||
@interface SDImageAWebPCoder : SDImageIOAnimatedCoder <SDProgressiveImageCoder, SDAnimatedImageCoder>
|
||||
|
||||
@property (nonatomic, class, readonly, nonnull) SDImageAWebPCoder *sharedCoder;
|
||||
|
||||
@end
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import "SDImageAWebPCoder.h"
|
||||
#import "SDImageAWebPCoderInternal.h"
|
||||
#import "SDImageIOAnimatedCoderInternal.h"
|
||||
|
||||
// These constants are available from iOS 14+ and Xcode 12. This raw value is used for toolchain and firmware compatibility
|
||||
static NSString * kSDCGImagePropertyWebPDictionary = @"{WebP}";
|
||||
static NSString * kSDCGImagePropertyWebPLoopCount = @"LoopCount";
|
||||
static NSString * kSDCGImagePropertyWebPDelayTime = @"DelayTime";
|
||||
static NSString * kSDCGImagePropertyWebPUnclampedDelayTime = @"UnclampedDelayTime";
|
||||
|
||||
@implementation SDImageAWebPCoder
|
||||
|
||||
+ (void)initialize {
|
||||
#if __IPHONE_14_0 || __TVOS_14_0 || __MAC_11_0 || __WATCHOS_7_0
|
||||
// Xcode 12
|
||||
if (@available(iOS 14, tvOS 14, macOS 11, watchOS 7, *)) {
|
||||
// Use SDK instead of raw value
|
||||
kSDCGImagePropertyWebPDictionary = (__bridge NSString *)kCGImagePropertyWebPDictionary;
|
||||
kSDCGImagePropertyWebPLoopCount = (__bridge NSString *)kCGImagePropertyWebPLoopCount;
|
||||
kSDCGImagePropertyWebPDelayTime = (__bridge NSString *)kCGImagePropertyWebPDelayTime;
|
||||
kSDCGImagePropertyWebPUnclampedDelayTime = (__bridge NSString *)kCGImagePropertyWebPUnclampedDelayTime;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
+ (instancetype)sharedCoder {
|
||||
static SDImageAWebPCoder *coder;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
coder = [[SDImageAWebPCoder alloc] init];
|
||||
});
|
||||
return coder;
|
||||
}
|
||||
|
||||
#pragma mark - SDImageCoder
|
||||
|
||||
- (BOOL)canDecodeFromData:(nullable NSData *)data {
|
||||
switch ([NSData sd_imageFormatForImageData:data]) {
|
||||
case SDImageFormatWebP:
|
||||
// Check WebP decoding compatibility
|
||||
return [self.class canDecodeFromWebPFormat];
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)canIncrementalDecodeFromData:(NSData *)data {
|
||||
return [self canDecodeFromData:data];
|
||||
}
|
||||
|
||||
- (BOOL)canEncodeToFormat:(SDImageFormat)format {
|
||||
switch (format) {
|
||||
case SDImageFormatWebP:
|
||||
// Check WebP encoding compatibility
|
||||
return [self.class canEncodeToWebPFormat];
|
||||
default:
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - WebP Format
|
||||
|
||||
+ (BOOL)canDecodeFromWebPFormat {
|
||||
static BOOL canDecode = NO;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
canDecode = [self canDecodeFromFormat:SDImageFormatWebP];
|
||||
});
|
||||
return canDecode;
|
||||
}
|
||||
|
||||
+ (BOOL)canEncodeToWebPFormat {
|
||||
static BOOL canEncode = NO;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
canEncode = [self canEncodeToFormat:SDImageFormatWebP];
|
||||
});
|
||||
return canEncode;
|
||||
}
|
||||
|
||||
#pragma mark - Subclass Override
|
||||
|
||||
+ (SDImageFormat)imageFormat {
|
||||
return SDImageFormatWebP;
|
||||
}
|
||||
|
||||
+ (NSString *)imageUTType {
|
||||
return (__bridge NSString *)kSDUTTypeWebP;
|
||||
}
|
||||
|
||||
+ (NSString *)dictionaryProperty {
|
||||
return kSDCGImagePropertyWebPDictionary;
|
||||
}
|
||||
|
||||
+ (NSString *)unclampedDelayTimeProperty {
|
||||
return kSDCGImagePropertyWebPUnclampedDelayTime;
|
||||
}
|
||||
|
||||
+ (NSString *)delayTimeProperty {
|
||||
return kSDCGImagePropertyWebPDelayTime;
|
||||
}
|
||||
|
||||
+ (NSString *)loopCountProperty {
|
||||
return kSDCGImagePropertyWebPLoopCount;
|
||||
}
|
||||
|
||||
+ (NSUInteger)defaultLoopCount {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@end
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#import "SDImageHEICCoder.h"
|
||||
#import "SDImageHEICCoderInternal.h"
|
||||
#import "SDImageIOAnimatedCoderInternal.h"
|
||||
|
||||
// These constants are available from iOS 13+ and Xcode 11. This raw value is used for toolchain and firmware compatibility
|
||||
static NSString * kSDCGImagePropertyHEICSDictionary = @"{HEICS}";
|
||||
|
@ -73,15 +74,6 @@ static NSString * kSDCGImagePropertyHEICSUnclampedDelayTime = @"UnclampedDelayTi
|
|||
|
||||
#pragma mark - HEIF Format
|
||||
|
||||
+ (BOOL)canDecodeFromFormat:(SDImageFormat)format {
|
||||
CFStringRef imageUTType = [NSData sd_UTTypeFromImageFormat:format];
|
||||
NSArray *imageUTTypes = (__bridge_transfer NSArray *)CGImageSourceCopyTypeIdentifiers();
|
||||
if ([imageUTTypes containsObject:(__bridge NSString *)(imageUTType)]) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)canDecodeFromHEICFormat {
|
||||
static BOOL canDecode = NO;
|
||||
static dispatch_once_t onceToken;
|
||||
|
@ -100,22 +92,6 @@ static NSString * kSDCGImagePropertyHEICSUnclampedDelayTime = @"UnclampedDelayTi
|
|||
return canDecode;
|
||||
}
|
||||
|
||||
+ (BOOL)canEncodeToFormat:(SDImageFormat)format {
|
||||
NSMutableData *imageData = [NSMutableData data];
|
||||
CFStringRef imageUTType = [NSData sd_UTTypeFromImageFormat:format];
|
||||
|
||||
// Create an image destination.
|
||||
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, 1, NULL);
|
||||
if (!imageDestination) {
|
||||
// Can't encode to HEIC
|
||||
return NO;
|
||||
} else {
|
||||
// Can encode to HEIC
|
||||
CFRelease(imageDestination);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)canEncodeToHEICFormat {
|
||||
static BOOL canEncode = NO;
|
||||
static dispatch_once_t onceToken;
|
||||
|
|
|
@ -108,6 +108,32 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
|
||||
#pragma mark - Utils
|
||||
|
||||
+ (BOOL)canDecodeFromFormat:(SDImageFormat)format {
|
||||
CFStringRef imageUTType = [NSData sd_UTTypeFromImageFormat:format];
|
||||
NSArray *imageUTTypes = (__bridge_transfer NSArray *)CGImageSourceCopyTypeIdentifiers();
|
||||
if ([imageUTTypes containsObject:(__bridge NSString *)(imageUTType)]) {
|
||||
// Can decode from target format
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (BOOL)canEncodeToFormat:(SDImageFormat)format {
|
||||
NSMutableData *imageData = [NSMutableData data];
|
||||
CFStringRef imageUTType = [NSData sd_UTTypeFromImageFormat:format];
|
||||
|
||||
// Create an image destination.
|
||||
CGImageDestinationRef imageDestination = CGImageDestinationCreateWithData((__bridge CFMutableDataRef)imageData, imageUTType, 1, NULL);
|
||||
if (!imageDestination) {
|
||||
// Can't encode to target format
|
||||
return NO;
|
||||
} else {
|
||||
// Can encode to target format
|
||||
CFRelease(imageDestination);
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSUInteger)imageLoopCountWithSource:(CGImageSourceRef)source {
|
||||
NSUInteger loopCount = self.defaultLoopCount;
|
||||
NSDictionary *imageProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(source, nil);
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
#import "NSImage+Compatibility.h"
|
||||
#import <ImageIO/ImageIO.h>
|
||||
#import "UIImage+Metadata.h"
|
||||
#import "SDImageHEICCoderInternal.h"
|
||||
#import "SDImageIOAnimatedCoderInternal.h"
|
||||
|
||||
// Specify File Size for lossy format encoding, like JPEG
|
||||
|
@ -55,19 +54,7 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
|
||||
#pragma mark - Decode
|
||||
- (BOOL)canDecodeFromData:(nullable NSData *)data {
|
||||
switch ([NSData sd_imageFormatForImageData:data]) {
|
||||
case SDImageFormatWebP:
|
||||
// Do not support WebP decoding
|
||||
return NO;
|
||||
case SDImageFormatHEIC:
|
||||
// Check HEIC decoding compatibility
|
||||
return [SDImageHEICCoder canDecodeFromHEICFormat];
|
||||
case SDImageFormatHEIF:
|
||||
// Check HEIF decoding compatibility
|
||||
return [SDImageHEICCoder canDecodeFromHEIFFormat];
|
||||
default:
|
||||
return YES;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderOptions *)options {
|
||||
|
@ -205,19 +192,7 @@ static NSString * kSDCGImageDestinationRequestedFileSize = @"kCGImageDestination
|
|||
|
||||
#pragma mark - Encode
|
||||
- (BOOL)canEncodeToFormat:(SDImageFormat)format {
|
||||
switch (format) {
|
||||
case SDImageFormatWebP:
|
||||
// Do not support WebP encoding
|
||||
return NO;
|
||||
case SDImageFormatHEIC:
|
||||
// Check HEIC encoding compatibility
|
||||
return [SDImageHEICCoder canEncodeToHEICFormat];
|
||||
case SDImageFormatHEIF:
|
||||
// Check HEIF encoding compatibility
|
||||
return [SDImageHEICCoder canEncodeToHEIFFormat];
|
||||
default:
|
||||
return YES;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format options:(nullable SDImageCoderOptions *)options {
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* This file is part of the SDWebImage package.
|
||||
* (c) Olivier Poitrey <rs@dailymotion.com>
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "SDImageAWebPCoder.h"
|
||||
|
||||
// kUTTypeWebP seems not defined in public UTI framework, Apple use the hardcode string, we define them :)
|
||||
#define kSDUTTypeWebP ((__bridge CFStringRef)@"org.webmproject.webp")
|
||||
|
||||
@interface SDImageAWebPCoder ()
|
||||
|
||||
+ (BOOL)canDecodeFromWebPFormat;
|
||||
+ (BOOL)canEncodeToWebPFormat;
|
||||
|
||||
@end
|
|
@ -14,5 +14,7 @@
|
|||
+ (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index source:(nonnull CGImageSourceRef)source;
|
||||
+ (NSUInteger)imageLoopCountWithSource:(nonnull CGImageSourceRef)source;
|
||||
+ (nullable UIImage *)createFrameAtIndex:(NSUInteger)index source:(nonnull CGImageSourceRef)source scale:(CGFloat)scale preserveAspectRatio:(BOOL)preserveAspectRatio thumbnailSize:(CGSize)thumbnailSize options:(nullable NSDictionary *)options;
|
||||
+ (BOOL)canEncodeToFormat:(SDImageFormat)format;
|
||||
+ (BOOL)canDecodeFromFormat:(SDImageFormat)format;
|
||||
|
||||
@end
|
||||
|
|
|
@ -70,6 +70,7 @@ FOUNDATION_EXPORT const unsigned char SDWebImageVersionString[];
|
|||
#import <SDWebImage/SDWebImageOptionsProcessor.h>
|
||||
#import <SDWebImage/SDImageIOAnimatedCoder.h>
|
||||
#import <SDWebImage/SDImageHEICCoder.h>
|
||||
#import <SDWebImage/SDImageAWebPCoder.h>
|
||||
|
||||
// Mac
|
||||
#if __has_include(<SDWebImage/NSImage+Compatibility.h>)
|
||||
|
|
Loading…
Reference in New Issue