SDWebImageDefine.m 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  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 "SDWebImageDefine.h"
  9. #import "UIImage+Metadata.h"
  10. #import "NSImage+Compatibility.h"
  11. #import "SDAnimatedImage.h"
  12. #import "SDAssociatedObject.h"
  13. #pragma mark - Image scale
  14. static inline NSArray<NSNumber *> * _Nonnull SDImageScaleFactors(void) {
  15. return @[@2, @3];
  16. }
  17. inline CGFloat SDImageScaleFactorForKey(NSString * _Nullable key) {
  18. CGFloat scale = 1;
  19. if (!key) {
  20. return scale;
  21. }
  22. // Now all OS supports retina display scale system
  23. {
  24. // a@2x.png -> 8
  25. if (key.length >= 8) {
  26. // Fast check
  27. BOOL isURL = [key hasPrefix:@"http://"] || [key hasPrefix:@"https://"];
  28. for (NSNumber *scaleFactor in SDImageScaleFactors()) {
  29. // @2x. for file name and normal url
  30. NSString *fileScale = [NSString stringWithFormat:@"@%@x.", scaleFactor];
  31. if ([key containsString:fileScale]) {
  32. scale = scaleFactor.doubleValue;
  33. return scale;
  34. }
  35. if (isURL) {
  36. // %402x. for url encode
  37. NSString *urlScale = [NSString stringWithFormat:@"%%40%@x.", scaleFactor];
  38. if ([key containsString:urlScale]) {
  39. scale = scaleFactor.doubleValue;
  40. return scale;
  41. }
  42. }
  43. }
  44. }
  45. }
  46. return scale;
  47. }
  48. inline UIImage * _Nullable SDScaledImageForKey(NSString * _Nullable key, UIImage * _Nullable image) {
  49. if (!image) {
  50. return nil;
  51. }
  52. CGFloat scale = SDImageScaleFactorForKey(key);
  53. return SDScaledImageForScaleFactor(scale, image);
  54. }
  55. inline UIImage * _Nullable SDScaledImageForScaleFactor(CGFloat scale, UIImage * _Nullable image) {
  56. if (!image) {
  57. return nil;
  58. }
  59. if (scale <= 1) {
  60. return image;
  61. }
  62. if (scale == image.scale) {
  63. return image;
  64. }
  65. UIImage *scaledImage;
  66. // Check SDAnimatedImage support for shortcut
  67. if ([image.class conformsToProtocol:@protocol(SDAnimatedImage)]) {
  68. if ([image respondsToSelector:@selector(animatedCoder)]) {
  69. id<SDAnimatedImageCoder> coder = [(id<SDAnimatedImage>)image animatedCoder];
  70. if (coder) {
  71. scaledImage = [[image.class alloc] initWithAnimatedCoder:coder scale:scale];
  72. }
  73. } else {
  74. // Some class impl does not support `animatedCoder`, keep for compatibility
  75. NSData *data = [(id<SDAnimatedImage>)image animatedImageData];
  76. if (data) {
  77. scaledImage = [[image.class alloc] initWithData:data scale:scale];
  78. }
  79. }
  80. }
  81. if (scaledImage) {
  82. SDImageCopyAssociatedObject(image, scaledImage);
  83. return scaledImage;
  84. }
  85. if (image.sd_isAnimated) {
  86. UIImage *animatedImage;
  87. #if SD_UIKIT || SD_WATCH
  88. // `UIAnimatedImage` images share the same size and scale.
  89. NSArray<UIImage *> *images = image.images;
  90. NSMutableArray<UIImage *> *scaledImages = [NSMutableArray arrayWithCapacity:images.count];
  91. for (UIImage *tempImage in images) {
  92. UIImage *tempScaledImage = [[UIImage alloc] initWithCGImage:tempImage.CGImage scale:scale orientation:tempImage.imageOrientation];
  93. [scaledImages addObject:tempScaledImage];
  94. }
  95. animatedImage = [UIImage animatedImageWithImages:scaledImages duration:image.duration];
  96. #else
  97. // Animated GIF for `NSImage` need to grab `NSBitmapImageRep`;
  98. NSRect imageRect = NSMakeRect(0, 0, image.size.width, image.size.height);
  99. NSImageRep *imageRep = [image bestRepresentationForRect:imageRect context:nil hints:nil];
  100. NSBitmapImageRep *bitmapImageRep;
  101. if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
  102. bitmapImageRep = (NSBitmapImageRep *)imageRep;
  103. }
  104. if (bitmapImageRep) {
  105. NSSize size = NSMakeSize(image.size.width / scale, image.size.height / scale);
  106. animatedImage = [[NSImage alloc] initWithSize:size];
  107. bitmapImageRep.size = size;
  108. [animatedImage addRepresentation:bitmapImageRep];
  109. }
  110. #endif
  111. scaledImage = animatedImage;
  112. } else {
  113. #if SD_UIKIT || SD_WATCH
  114. scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:image.imageOrientation];
  115. #else
  116. scaledImage = [[UIImage alloc] initWithCGImage:image.CGImage scale:scale orientation:kCGImagePropertyOrientationUp];
  117. #endif
  118. }
  119. if (scaledImage) {
  120. SDImageCopyAssociatedObject(image, scaledImage);
  121. return scaledImage;
  122. }
  123. return nil;
  124. }
  125. #pragma mark - Context option
  126. SDWebImageContextOption const SDWebImageContextSetImageOperationKey = @"setImageOperationKey";
  127. SDWebImageContextOption const SDWebImageContextCustomManager = @"customManager";
  128. SDWebImageContextOption const SDWebImageContextCallbackQueue = @"callbackQueue";
  129. SDWebImageContextOption const SDWebImageContextImageCache = @"imageCache";
  130. SDWebImageContextOption const SDWebImageContextImageLoader = @"imageLoader";
  131. SDWebImageContextOption const SDWebImageContextImageCoder = @"imageCoder";
  132. SDWebImageContextOption const SDWebImageContextImageTransformer = @"imageTransformer";
  133. SDWebImageContextOption const SDWebImageContextImageForceDecodePolicy = @"imageForceDecodePolicy";
  134. SDWebImageContextOption const SDWebImageContextImageDecodeOptions = @"imageDecodeOptions";
  135. SDWebImageContextOption const SDWebImageContextImageScaleFactor = @"imageScaleFactor";
  136. SDWebImageContextOption const SDWebImageContextImagePreserveAspectRatio = @"imagePreserveAspectRatio";
  137. SDWebImageContextOption const SDWebImageContextImageThumbnailPixelSize = @"imageThumbnailPixelSize";
  138. SDWebImageContextOption const SDWebImageContextImageTypeIdentifierHint = @"imageTypeIdentifierHint";
  139. SDWebImageContextOption const SDWebImageContextImageScaleDownLimitBytes = @"imageScaleDownLimitBytes";
  140. SDWebImageContextOption const SDWebImageContextImageEncodeOptions = @"imageEncodeOptions";
  141. SDWebImageContextOption const SDWebImageContextQueryCacheType = @"queryCacheType";
  142. SDWebImageContextOption const SDWebImageContextStoreCacheType = @"storeCacheType";
  143. SDWebImageContextOption const SDWebImageContextOriginalQueryCacheType = @"originalQueryCacheType";
  144. SDWebImageContextOption const SDWebImageContextOriginalStoreCacheType = @"originalStoreCacheType";
  145. SDWebImageContextOption const SDWebImageContextOriginalImageCache = @"originalImageCache";
  146. SDWebImageContextOption const SDWebImageContextAnimatedImageClass = @"animatedImageClass";
  147. SDWebImageContextOption const SDWebImageContextDownloadRequestModifier = @"downloadRequestModifier";
  148. SDWebImageContextOption const SDWebImageContextDownloadResponseModifier = @"downloadResponseModifier";
  149. SDWebImageContextOption const SDWebImageContextDownloadDecryptor = @"downloadDecryptor";
  150. SDWebImageContextOption const SDWebImageContextCacheKeyFilter = @"cacheKeyFilter";
  151. SDWebImageContextOption const SDWebImageContextCacheSerializer = @"cacheSerializer";