SDWebImageCodersManager.m 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. * This file is part of the SDWebImage package.
  3. * (c) Olivier Poitrey <rs@dailymotion.com>
  4. *
  5. * For the full copyright and license information, please view the LICENSE
  6. * file that was distributed with this source code.
  7. */
  8. #import "SDWebImageCodersManager.h"
  9. #import "SDWebImageImageIOCoder.h"
  10. #import "SDWebImageGIFCoder.h"
  11. #ifdef SD_WEBP
  12. #import "SDWebImageWebPCoder.h"
  13. #endif
  14. #import "UIImage+MultiFormat.h"
  15. #define LOCK(lock) dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
  16. #define UNLOCK(lock) dispatch_semaphore_signal(lock);
  17. @interface SDWebImageCodersManager ()
  18. @property (nonatomic, strong, nonnull) dispatch_semaphore_t codersLock;
  19. @end
  20. @implementation SDWebImageCodersManager
  21. + (nonnull instancetype)sharedInstance {
  22. static dispatch_once_t once;
  23. static id instance;
  24. dispatch_once(&once, ^{
  25. instance = [self new];
  26. });
  27. return instance;
  28. }
  29. - (instancetype)init {
  30. if (self = [super init]) {
  31. // initialize with default coders
  32. NSMutableArray<id<SDWebImageCoder>> *mutableCoders = [@[[SDWebImageImageIOCoder sharedCoder]] mutableCopy];
  33. #ifdef SD_WEBP
  34. [mutableCoders addObject:[SDWebImageWebPCoder sharedCoder]];
  35. #endif
  36. _coders = [mutableCoders copy];
  37. _codersLock = dispatch_semaphore_create(1);
  38. }
  39. return self;
  40. }
  41. #pragma mark - Coder IO operations
  42. - (void)addCoder:(nonnull id<SDWebImageCoder>)coder {
  43. if (![coder conformsToProtocol:@protocol(SDWebImageCoder)]) {
  44. return;
  45. }
  46. LOCK(self.codersLock);
  47. NSMutableArray<id<SDWebImageCoder>> *mutableCoders = [self.coders mutableCopy];
  48. if (!mutableCoders) {
  49. mutableCoders = [NSMutableArray array];
  50. }
  51. [mutableCoders addObject:coder];
  52. self.coders = [mutableCoders copy];
  53. UNLOCK(self.codersLock);
  54. }
  55. - (void)removeCoder:(nonnull id<SDWebImageCoder>)coder {
  56. if (![coder conformsToProtocol:@protocol(SDWebImageCoder)]) {
  57. return;
  58. }
  59. LOCK(self.codersLock);
  60. NSMutableArray<id<SDWebImageCoder>> *mutableCoders = [self.coders mutableCopy];
  61. [mutableCoders removeObject:coder];
  62. self.coders = [mutableCoders copy];
  63. UNLOCK(self.codersLock);
  64. }
  65. #pragma mark - SDWebImageCoder
  66. - (BOOL)canDecodeFromData:(NSData *)data {
  67. LOCK(self.codersLock);
  68. NSArray<id<SDWebImageCoder>> *coders = self.coders;
  69. UNLOCK(self.codersLock);
  70. for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
  71. if ([coder canDecodeFromData:data]) {
  72. return YES;
  73. }
  74. }
  75. return NO;
  76. }
  77. - (BOOL)canEncodeToFormat:(SDImageFormat)format {
  78. LOCK(self.codersLock);
  79. NSArray<id<SDWebImageCoder>> *coders = self.coders;
  80. UNLOCK(self.codersLock);
  81. for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
  82. if ([coder canEncodeToFormat:format]) {
  83. return YES;
  84. }
  85. }
  86. return NO;
  87. }
  88. - (UIImage *)decodedImageWithData:(NSData *)data {
  89. LOCK(self.codersLock);
  90. NSArray<id<SDWebImageCoder>> *coders = self.coders;
  91. UNLOCK(self.codersLock);
  92. for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
  93. if ([coder canDecodeFromData:data]) {
  94. return [coder decodedImageWithData:data];
  95. }
  96. }
  97. return nil;
  98. }
  99. - (UIImage *)decompressedImageWithImage:(UIImage *)image
  100. data:(NSData *__autoreleasing _Nullable *)data
  101. options:(nullable NSDictionary<NSString*, NSObject*>*)optionsDict {
  102. if (!image) {
  103. return nil;
  104. }
  105. LOCK(self.codersLock);
  106. NSArray<id<SDWebImageCoder>> *coders = self.coders;
  107. UNLOCK(self.codersLock);
  108. for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
  109. if ([coder canDecodeFromData:*data]) {
  110. UIImage *decompressedImage = [coder decompressedImageWithImage:image data:data options:optionsDict];
  111. decompressedImage.sd_imageFormat = image.sd_imageFormat;
  112. return decompressedImage;
  113. }
  114. }
  115. return nil;
  116. }
  117. - (NSData *)encodedDataWithImage:(UIImage *)image format:(SDImageFormat)format {
  118. if (!image) {
  119. return nil;
  120. }
  121. LOCK(self.codersLock);
  122. NSArray<id<SDWebImageCoder>> *coders = self.coders;
  123. UNLOCK(self.codersLock);
  124. for (id<SDWebImageCoder> coder in coders.reverseObjectEnumerator) {
  125. if ([coder canEncodeToFormat:format]) {
  126. return [coder encodedDataWithImage:image format:format];
  127. }
  128. }
  129. return nil;
  130. }
  131. @end