/* * This file is part of the SDWebImage package. * (c) Olivier Poitrey * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ #import "SDImageCodersManager.h" #import "SDImageIOCoder.h" #import "SDImageGIFCoder.h" #import "SDImageAPNGCoder.h" #import "SDImageHEICCoder.h" #import "SDInternalMacros.h" @interface SDImageCodersManager () @property (nonatomic, strong, nonnull) NSMutableArray> *imageCoders; @end @implementation SDImageCodersManager { SD_LOCK_DECLARE(_codersLock); } + (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 _imageCoders = [NSMutableArray arrayWithArray:@[[SDImageIOCoder sharedCoder], [SDImageGIFCoder sharedCoder], [SDImageAPNGCoder sharedCoder]]]; SD_LOCK_INIT(_codersLock); } return self; } - (NSArray> *)coders { SD_LOCK(_codersLock); NSArray> *coders = [_imageCoders copy]; SD_UNLOCK(_codersLock); return coders; } - (void)setCoders:(NSArray> *)coders { SD_LOCK(_codersLock); [_imageCoders removeAllObjects]; if (coders.count) { [_imageCoders addObjectsFromArray:coders]; } SD_UNLOCK(_codersLock); } #pragma mark - Coder IO operations - (void)addCoder:(nonnull id)coder { if (![coder conformsToProtocol:@protocol(SDImageCoder)]) { return; } SD_LOCK(_codersLock); [_imageCoders addObject:coder]; SD_UNLOCK(_codersLock); } - (void)removeCoder:(nonnull id)coder { if (![coder conformsToProtocol:@protocol(SDImageCoder)]) { return; } SD_LOCK(_codersLock); [_imageCoders removeObject:coder]; SD_UNLOCK(_codersLock); } #pragma mark - SDImageCoder - (BOOL)canDecodeFromData:(NSData *)data { NSArray> *coders = self.coders; for (id coder in coders.reverseObjectEnumerator) { if ([coder canDecodeFromData:data]) { return YES; } } return NO; } - (BOOL)canEncodeToFormat:(SDImageFormat)format { NSArray> *coders = self.coders; for (id coder in coders.reverseObjectEnumerator) { if ([coder canEncodeToFormat:format]) { return YES; } } return NO; } - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderOptions *)options { if (!data) { return nil; } UIImage *image; NSArray> *coders = self.coders; for (id coder in coders.reverseObjectEnumerator) { if ([coder canDecodeFromData:data]) { image = [coder decodedImageWithData:data options:options]; break; } } return image; } - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format options:(nullable SDImageCoderOptions *)options { if (!image) { return nil; } NSArray> *coders = self.coders; for (id coder in coders.reverseObjectEnumerator) { if ([coder canEncodeToFormat:format]) { return [coder encodedDataWithImage:image format:format options:options]; } } return nil; } - (NSData *)encodedDataWithFrames:(NSArray *)frames loopCount:(NSUInteger)loopCount format:(SDImageFormat)format options:(SDImageCoderOptions *)options { if (!frames || frames.count < 1) { return nil; } NSArray> *coders = self.coders; for (id coder in coders.reverseObjectEnumerator) { if ([coder canEncodeToFormat:format]) { if ([coder respondsToSelector:@selector(encodedDataWithFrames:loopCount:format:options:)]) { return [coder encodedDataWithFrames:frames loopCount:loopCount format:format options:options]; } } } return nil; } @end