SDWebImage/SDWebImage/SDWebImageCodersManager.m

130 lines
3.7 KiB
Objective-C

/*
* 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 "SDWebImageCodersManager.h"
#import "SDWebImageImageIOCoder.h"
#import "SDWebImageGIFCoder.h"
#import "SDWebImageAPNGCoder.h"
#ifdef SD_WEBP
#import "SDWebImageWebPCoder.h"
#endif
#import "NSImage+Additions.h"
#import "UIImage+WebCache.h"
@interface SDWebImageCodersManager ()
@property (strong, nonatomic, nonnull) NSMutableArray<SDWebImageCoder>* mutableCoders;
@property (strong, nonatomic, nullable) dispatch_queue_t mutableCodersAccessQueue;
@end
@implementation SDWebImageCodersManager
+ (nonnull instancetype)sharedManager {
static dispatch_once_t once;
static id instance;
dispatch_once(&once, ^{
instance = [self new];
});
return instance;
}
- (instancetype)init {
if (self = [super init]) {
// initialize with default coders
_mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder], [SDWebImageGIFCoder sharedCoder], [SDWebImageAPNGCoder sharedCoder]] mutableCopy];
#ifdef SD_WEBP
[_mutableCoders addObject:[SDWebImageWebPCoder sharedCoder]];
#endif
_mutableCodersAccessQueue = dispatch_queue_create("com.hackemist.SDWebImageCodersManager", DISPATCH_QUEUE_CONCURRENT);
}
return self;
}
#pragma mark - Coder IO operations
- (void)addCoder:(nonnull id<SDWebImageCoder>)coder {
if ([coder conformsToProtocol:@protocol(SDWebImageCoder)]) {
dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{
[self.mutableCoders addObject:coder];
});
}
}
- (void)removeCoder:(nonnull id<SDWebImageCoder>)coder {
dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{
[self.mutableCoders removeObject:coder];
});
}
- (NSArray<id<SDWebImageCoder>> *)coders {
__block NSArray<id<SDWebImageCoder>> *sortedCoders = nil;
dispatch_sync(self.mutableCodersAccessQueue, ^{
sortedCoders = (NSArray<id<SDWebImageCoder>> *)[[[self.mutableCoders copy] reverseObjectEnumerator] allObjects];
});
return sortedCoders;
}
- (void)setCoders:(NSArray<id<SDWebImageCoder>> *)coders {
dispatch_barrier_sync(self.mutableCodersAccessQueue, ^{
self.mutableCoders = [coders mutableCopy];
});
}
#pragma mark - SDWebImageCoder
- (BOOL)canDecodeFromData:(NSData *)data {
for (id<SDWebImageCoder> coder in self.coders) {
if ([coder canDecodeFromData:data]) {
return YES;
}
}
return NO;
}
- (BOOL)canEncodeToFormat:(SDImageFormat)format {
for (id<SDWebImageCoder> coder in self.coders) {
if ([coder canEncodeToFormat:format]) {
return YES;
}
}
return NO;
}
- (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDWebImageCoderOptions *)options {
if (!data) {
return nil;
}
BOOL decodeFirstFrame = [[options valueForKey:SDWebImageCoderDecodeFirstFrameOnly] boolValue];
UIImage *image;
for (id<SDWebImageCoder> coder in self.coders) {
if ([coder canDecodeFromData:data]) {
image = [coder decodedImageWithData:data options:options];
break;
}
}
if (decodeFirstFrame && image.images.count > 0) {
image = image.images.firstObject;
}
return image;
}
- (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format options:(nullable SDWebImageCoderOptions *)options {
if (!image) {
return nil;
}
for (id<SDWebImageCoder> coder in self.coders) {
if ([coder canEncodeToFormat:format]) {
return [coder encodedDataWithImage:image format:format options:nil];
}
}
return nil;
}
@end