diff --git a/Examples/SDWebImage Demo/DetailViewController.m b/Examples/SDWebImage Demo/DetailViewController.m index d3293397..37a02f0a 100644 --- a/Examples/SDWebImage Demo/DetailViewController.m +++ b/Examples/SDWebImage Demo/DetailViewController.m @@ -23,7 +23,9 @@ } [self.imageView sd_setImageWithURL:self.imageURL placeholderImage:nil - options:SDWebImageProgressiveLoad | SDWebImageScaleDownLargeImages]; + options:SDWebImageProgressiveLoad | SDWebImageScaleDownLargeImages + context:@{SDWebImageContextImageForceDecodePolicy: @(SDImageForceDecodePolicyNever)} + ]; self.imageView.shouldCustomLoopCount = YES; self.imageView.animationRepeatCount = 0; } diff --git a/SDWebImage/Core/SDImageCache.h b/SDWebImage/Core/SDImageCache.h index 14926dd2..0289b920 100644 --- a/SDWebImage/Core/SDImageCache.h +++ b/SDWebImage/Core/SDImageCache.h @@ -37,8 +37,10 @@ typedef NS_OPTIONS(NSUInteger, SDImageCacheOptions) { /** * By default, we will decode the image in the background during cache query and download from the network. This can help to improve performance because when rendering image on the screen, it need to be firstly decoded. But this happen on the main queue by Core Animation. * However, this process may increase the memory usage as well. If you are experiencing a issue due to excessive memory consumption, This flag can prevent decode the image. + * @note 5.14.0 introduce `SDImageCoderDecodeUseLazyDecoding`, use that for better control from codec, instead of post-processing. Which acts the similar like this option but works for SDAnimatedImage as well (this one does not) + * @deprecated Deprecated in v5.17.0, if you don't want force-decode, pass [.imageForceDecodePolicy] = [SDImageForceDecodePolicy.never] in context option */ - SDImageCacheAvoidDecodeImage = 1 << 4, + SDImageCacheAvoidDecodeImage API_DEPRECATED("Use SDWebImageContextImageForceDecodePolicy instead", macos(10.10, 10.10), ios(8.0, 8.0), tvos(9.0, 9.0), watchos(2.0, 2.0)) = 1 << 4, /** * By default, we decode the animated image. This flag can force decode the first frame only and produce the static image. */ diff --git a/SDWebImage/Core/SDImageCache.m b/SDWebImage/Core/SDImageCache.m index 8bdadf99..da393b85 100644 --- a/SDWebImage/Core/SDImageCache.m +++ b/SDWebImage/Core/SDImageCache.m @@ -883,6 +883,8 @@ static NSString * _defaultDiskCacheDirectory; } #pragma mark - Helper +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + (SDWebImageOptions)imageOptionsFromCacheOptions:(SDImageCacheOptions)cacheOptions { SDWebImageOptions options = 0; if (cacheOptions & SDImageCacheScaleDownLargeImages) options |= SDWebImageScaleDownLargeImages; @@ -893,6 +895,7 @@ static NSString * _defaultDiskCacheDirectory; return options; } +#pragma clang diagnostic pop @end @@ -904,6 +907,8 @@ static NSString * _defaultDiskCacheDirectory; return [self queryImageForKey:key options:options context:context cacheType:SDImageCacheTypeAll completion:completionBlock]; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" - (id)queryImageForKey:(NSString *)key options:(SDWebImageOptions)options context:(nullable SDWebImageContext *)context cacheType:(SDImageCacheType)cacheType completion:(nullable SDImageCacheQueryCompletionBlock)completionBlock { SDImageCacheOptions cacheOptions = 0; if (options & SDWebImageQueryMemoryData) cacheOptions |= SDImageCacheQueryMemoryData; @@ -917,6 +922,7 @@ static NSString * _defaultDiskCacheDirectory; return [self queryCacheOperationForKey:key options:cacheOptions context:context cacheType:cacheType done:completionBlock]; } +#pragma clang diagnostic pop - (void)storeImage:(UIImage *)image imageData:(NSData *)imageData forKey:(nullable NSString *)key cacheType:(SDImageCacheType)cacheType completion:(nullable SDWebImageNoParamsBlock)completionBlock { [self storeImage:image imageData:imageData forKey:key options:0 context:nil cacheType:cacheType completion:completionBlock]; diff --git a/SDWebImage/Core/SDImageCacheDefine.m b/SDWebImage/Core/SDImageCacheDefine.m index 8e171e67..4e2e84c9 100644 --- a/SDWebImage/Core/SDImageCacheDefine.m +++ b/SDWebImage/Core/SDImageCacheDefine.m @@ -123,15 +123,15 @@ UIImage * _Nullable SDImageCacheDecodeImageData(NSData * _Nonnull imageData, NSS image = [imageCoder decodedImageWithData:imageData options:coderOptions]; } if (image) { - BOOL shouldDecode = !SD_OPTIONS_CONTAINS(options, SDWebImageAvoidDecodeImage); - BOOL lazyDecode = [coderOptions[SDImageCoderDecodeUseLazyDecoding] boolValue]; - if (lazyDecode) { - // lazyDecode = NO means we should not forceDecode, highest priority - shouldDecode = NO; - } - if (shouldDecode) { - image = [SDImageCoderHelper decodedImageWithImage:image]; + SDImageForceDecodePolicy policy = SDImageForceDecodePolicyAutomatic; + // TODO: Deprecated, remove in SD 6.0... +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if (SD_OPTIONS_CONTAINS(options, SDWebImageAvoidDecodeImage)) { + policy = SDImageForceDecodePolicyNever; } +#pragma clang diagnostic pop + image = [SDImageCoderHelper decodedImageWithImage:image policy:policy]; // assign the decode options, to let manager check whether to re-decode if needed image.sd_decodeOptions = coderOptions; } diff --git a/SDWebImage/Core/SDImageCoderHelper.h b/SDWebImage/Core/SDImageCoderHelper.h index acfb8072..a40e9085 100644 --- a/SDWebImage/Core/SDImageCoderHelper.h +++ b/SDWebImage/Core/SDImageCoderHelper.h @@ -20,6 +20,19 @@ typedef NS_ENUM(NSUInteger, SDImageCoderDecodeSolution) { SDImageCoderDecodeSolutionUIKit }; +/// The policy to force-decode the origin CGImage (produced by Image Coder Plugin) +/// Some CGImage may be lazy, or not lazy, but need extra copy to render on screen +/// The force-decode step help to `pre-process` to get the best suitable CGImage to render, which can increase frame rate +/// The downside is that force-decode may consume RAM and CPU, and may loss the `lazy` support (lazy CGImage can be purged when memory warning, and re-created if need), see more: `SDImageCoderDecodeUseLazyDecoding` +typedef NS_ENUM(NSUInteger, SDImageForceDecodePolicy) { + /// Based on input CGImage's colorspace, alignment, bitmapinfo, if it may trigger `CA::copy_image` extra copy, we will force-decode, else don't + SDImageForceDecodePolicyAutomatic, + /// Never force decode input CGImage + SDImageForceDecodePolicyNever, + /// Always force decode input CGImage (only once) + SDImageForceDecodePolicyAlways +}; + /// Byte alignment the bytes size with alignment /// - Parameters: /// - size: The bytes size @@ -144,20 +157,41 @@ static inline size_t SDByteAlign(size_t size, size_t alignment) { /** Return the decoded image by the provided image. This one unlike `CGImageCreateDecoded:`, will not decode the image which contains alpha channel or animated image. On iOS 15+, this may use `UIImage.preparingForDisplay()` to use CMPhoto for better performance than the old solution. @param image The image to be decoded + @note This translate to `decodedImageWithImage:policy:` with automatic policy @return The decoded image */ + (UIImage * _Nullable)decodedImageWithImage:(UIImage * _Nullable)image; +/** + Return the decoded image by the provided image. This one unlike `CGImageCreateDecoded:`, will not decode the image which contains alpha channel or animated image. On iOS 15+, this may use `UIImage.preparingForDisplay()` to use CMPhoto for better performance than the old solution. + @param image The image to be decoded + @param policy The force decode policy to decode image, will effect the check whether input image need decode + @return The decoded image + */ ++ (UIImage * _Nullable)decodedImageWithImage:(UIImage * _Nullable)image policy:(SDImageForceDecodePolicy)policy; + /** Return the decoded and probably scaled down image by the provided image. If the image pixels bytes size large than the limit bytes, will try to scale down. Or just works as `decodedImageWithImage:`, never scale up. @warning You should not pass too small bytes, the suggestion value should be larger than 1MB. Even we use Tile Decoding to avoid OOM, however, small bytes will consume much more CPU time because we need to iterate more times to draw each tile. @param image The image to be decoded and scaled down @param bytes The limit bytes size. Provide 0 to use the build-in limit. + @note This translate to `decodedAndScaledDownImageWithImage:limitBytes:policy:` with automatic policy @return The decoded and probably scaled down image */ + (UIImage * _Nullable)decodedAndScaledDownImageWithImage:(UIImage * _Nullable)image limitBytes:(NSUInteger)bytes; +/** + Return the decoded and probably scaled down image by the provided image. If the image pixels bytes size large than the limit bytes, will try to scale down. Or just works as `decodedImageWithImage:`, never scale up. + @warning You should not pass too small bytes, the suggestion value should be larger than 1MB. Even we use Tile Decoding to avoid OOM, however, small bytes will consume much more CPU time because we need to iterate more times to draw each tile. + + @param image The image to be decoded and scaled down + @param bytes The limit bytes size. Provide 0 to use the build-in limit. + @param policy The force decode policy to decode image, will effect the check whether input image need decode + @return The decoded and probably scaled down image + */ ++ (UIImage * _Nullable)decodedAndScaledDownImageWithImage:(UIImage * _Nullable)image limitBytes:(NSUInteger)bytes policy:(SDImageForceDecodePolicy)policy; + /** Control the default force decode solution. Available solutions in `SDImageCoderDecodeSolution`. @note Defaults to `SDImageCoderDecodeSolutionAutomatic`, which prefers to use UIKit for JPEG/HEIF, and fallback on CoreGraphics. If you want control on your hand, set the other solution. diff --git a/SDWebImage/Core/SDImageCoderHelper.m b/SDWebImage/Core/SDImageCoderHelper.m index c3fb6ba3..b0353172 100644 --- a/SDWebImage/Core/SDImageCoderHelper.m +++ b/SDWebImage/Core/SDImageCoderHelper.m @@ -508,7 +508,11 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over } + (UIImage *)decodedImageWithImage:(UIImage *)image { - if (![self shouldDecodeImage:image]) { + return [self decodedImageWithImage:image policy:SDImageForceDecodePolicyAutomatic]; +} + ++ (UIImage *)decodedImageWithImage:(UIImage *)image policy:(SDImageForceDecodePolicy)policy { + if (![self shouldDecodeImage:image policy:policy]) { return image; } @@ -565,7 +569,11 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over } + (UIImage *)decodedAndScaledDownImageWithImage:(UIImage *)image limitBytes:(NSUInteger)bytes { - if (![self shouldDecodeImage:image]) { + return [self decodedAndScaledDownImageWithImage:image limitBytes:bytes policy:SDImageForceDecodePolicyAutomatic]; +} + ++ (UIImage *)decodedAndScaledDownImageWithImage:(UIImage *)image limitBytes:(NSUInteger)bytes policy:(SDImageForceDecodePolicy)policy { + if (![self shouldDecodeImage:image policy:policy]) { return image; } @@ -804,11 +812,17 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over #endif #pragma mark - Helper Function -+ (BOOL)shouldDecodeImage:(nullable UIImage *)image { ++ (BOOL)shouldDecodeImage:(nullable UIImage *)image policy:(SDImageForceDecodePolicy)policy { // Prevent "CGBitmapContextCreateImage: invalid context 0x0" error if (image == nil) { return NO; } + // Check policy (never/always) + if (policy == SDImageForceDecodePolicyNever) { + return NO; + } else if (policy == SDImageForceDecodePolicyAlways) { + return YES; + } // Avoid extra decode if (image.sd_isDecoded) { return NO; @@ -821,7 +835,20 @@ static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to over if (image.sd_isVector) { return NO; } - + // Check policy (automatic) + CGImageRef cgImage = image.CGImage; + if (cgImage) { + CFStringRef uttype = CGImageGetUTType(cgImage); + if (uttype) { + // Only ImageIO can set `com.apple.ImageIO.imageSourceTypeIdentifier` + return YES; + } else { + // Now, let's check if the CGImage is hardware supported (not byte-aligned will cause extra copy) + BOOL isSupported = [SDImageCoderHelper CGImageIsHardwareSupported:cgImage]; + return !isSupported; + } + } + return YES; } diff --git a/SDWebImage/Core/SDImageLoader.m b/SDWebImage/Core/SDImageLoader.m index dc547918..e7d69d73 100644 --- a/SDWebImage/Core/SDImageLoader.m +++ b/SDWebImage/Core/SDImageLoader.m @@ -74,15 +74,15 @@ UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NS image = [imageCoder decodedImageWithData:imageData options:coderOptions]; } if (image) { - BOOL shouldDecode = !SD_OPTIONS_CONTAINS(options, SDWebImageAvoidDecodeImage); - BOOL lazyDecode = [coderOptions[SDImageCoderDecodeUseLazyDecoding] boolValue]; - if (lazyDecode) { - // lazyDecode = NO means we should not forceDecode, highest priority - shouldDecode = NO; - } - if (shouldDecode) { - image = [SDImageCoderHelper decodedImageWithImage:image]; + SDImageForceDecodePolicy policy = SDImageForceDecodePolicyAutomatic; + // TODO: Deprecated, remove in SD 6.0... +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if (SD_OPTIONS_CONTAINS(options, SDWebImageAvoidDecodeImage)) { + policy = SDImageForceDecodePolicyNever; } +#pragma clang diagnostic pop + image = [SDImageCoderHelper decodedImageWithImage:image policy:policy]; // assign the decode options, to let manager check whether to re-decode if needed image.sd_decodeOptions = coderOptions; } @@ -151,15 +151,15 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im image = [progressiveCoder incrementalDecodedImageWithOptions:coderOptions]; } if (image) { - BOOL shouldDecode = !SD_OPTIONS_CONTAINS(options, SDWebImageAvoidDecodeImage); - BOOL lazyDecode = [coderOptions[SDImageCoderDecodeUseLazyDecoding] boolValue]; - if (lazyDecode) { - // lazyDecode = NO means we should not forceDecode, highest priority - shouldDecode = NO; - } - if (shouldDecode) { - image = [SDImageCoderHelper decodedImageWithImage:image]; + SDImageForceDecodePolicy policy = SDImageForceDecodePolicyAutomatic; + // TODO: Deprecated, remove in SD 6.0... +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + if (SD_OPTIONS_CONTAINS(options, SDWebImageAvoidDecodeImage)) { + policy = SDImageForceDecodePolicyNever; } +#pragma clang diagnostic pop + image = [SDImageCoderHelper decodedImageWithImage:image policy:policy]; // assign the decode options, to let manager check whether to re-decode if needed image.sd_decodeOptions = coderOptions; // mark the image as progressive (completed one are not mark as progressive) diff --git a/SDWebImage/Core/SDWebImageDefine.h b/SDWebImage/Core/SDWebImageDefine.h index 14840a33..b828d739 100644 --- a/SDWebImage/Core/SDWebImageDefine.h +++ b/SDWebImage/Core/SDWebImageDefine.h @@ -172,8 +172,9 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageOptions) { * By default, we will decode the image in the background during cache query and download from the network. This can help to improve performance because when rendering image on the screen, it need to be firstly decoded. But this happen on the main queue by Core Animation. * However, this process may increase the memory usage as well. If you are experiencing an issue due to excessive memory consumption, This flag can prevent decode the image. * @note 5.14.0 introduce `SDImageCoderDecodeUseLazyDecoding`, use that for better control from codec, instead of post-processing. Which acts the similar like this option but works for SDAnimatedImage as well (this one does not) + * @deprecated Deprecated in v5.17.0, if you don't want force-decode, pass [.imageForceDecodePolicy] = [SDImageForceDecodePolicy.never] in context option */ - SDWebImageAvoidDecodeImage = 1 << 18, + SDWebImageAvoidDecodeImage API_DEPRECATED("Use SDWebImageContextImageForceDecodePolicy instead", macos(10.10, 10.10), ios(8.0, 8.0), tvos(9.0, 9.0), watchos(2.0, 2.0)) = 1 << 18, /** * By default, we decode the animated image. This flag can force decode the first frame only and produce the static image. @@ -256,6 +257,15 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageC */ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageTransformer; +#pragma mark - Force Decode Options + +/** + A NSNumber instance which store the`SDImageForceDecodePolicy` enum. This is used to control how current image loading should force-decode the decoded image (CGImage, typically). See more what's force-decode means in `SDImageForceDecodePolicy` comment. + Defaults to `SDImageForceDecodePolicyAutomatic`, which will detect the input CGImage's metadata, and only force-decode if the input CGImage can not directly render on screen (need extra CoreAnimation Copied Image and increase RAM usage). + @note If you want to always the force-decode for this image request, pass `SDImageForceDecodePolicyAlways`, for example, some WebP images which does not created by ImageIO. + */ +FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageForceDecodePolicy; + #pragma mark - Image Decoder Context Options /** diff --git a/SDWebImage/Core/SDWebImageDefine.m b/SDWebImage/Core/SDWebImageDefine.m index f7e7296d..e247429f 100644 --- a/SDWebImage/Core/SDWebImageDefine.m +++ b/SDWebImage/Core/SDWebImageDefine.m @@ -151,6 +151,7 @@ SDWebImageContextOption const SDWebImageContextImageCache = @"imageCache"; SDWebImageContextOption const SDWebImageContextImageLoader = @"imageLoader"; SDWebImageContextOption const SDWebImageContextImageCoder = @"imageCoder"; SDWebImageContextOption const SDWebImageContextImageTransformer = @"imageTransformer"; +SDWebImageContextOption const SDWebImageContextImageForceDecodePolicy = @"imageForceDecodePolicy"; SDWebImageContextOption const SDWebImageContextImageDecodeOptions = @"imageDecodeOptions"; SDWebImageContextOption const SDWebImageContextImageScaleFactor = @"imageScaleFactor"; SDWebImageContextOption const SDWebImageContextImagePreserveAspectRatio = @"imagePreserveAspectRatio"; diff --git a/SDWebImage/Core/SDWebImageDownloader.h b/SDWebImage/Core/SDWebImageDownloader.h index 6b1cb3b9..08ae16bf 100644 --- a/SDWebImage/Core/SDWebImageDownloader.h +++ b/SDWebImage/Core/SDWebImageDownloader.h @@ -74,8 +74,10 @@ typedef NS_OPTIONS(NSUInteger, SDWebImageDownloaderOptions) { /** * By default, we will decode the image in the background during cache query and download from the network. This can help to improve performance because when rendering image on the screen, it need to be firstly decoded. But this happen on the main queue by Core Animation. * However, this process may increase the memory usage as well. If you are experiencing a issue due to excessive memory consumption, This flag can prevent decode the image. + * @note 5.14.0 introduce `SDImageCoderDecodeUseLazyDecoding`, use that for better control from codec, instead of post-processing. Which acts the similar like this option but works for SDAnimatedImage as well (this one does not) + * @deprecated Deprecated in v5.17.0, if you don't want force-decode, pass [.imageForceDecodePolicy] = [SDImageForceDecodePolicy.never] in context option */ - SDWebImageDownloaderAvoidDecodeImage = 1 << 9, + SDWebImageDownloaderAvoidDecodeImage API_DEPRECATED("Use SDWebImageContextImageForceDecodePolicy instead", macos(10.10, 10.10), ios(8.0, 8.0), tvos(9.0, 9.0), watchos(2.0, 2.0)) = 1 << 9, /** * By default, we decode the animated image. This flag can force decode the first frame only and produce the static image. diff --git a/SDWebImage/Core/SDWebImageDownloader.m b/SDWebImage/Core/SDWebImageDownloader.m index 6e9fe062..cfd26461 100644 --- a/SDWebImage/Core/SDWebImageDownloader.m +++ b/SDWebImage/Core/SDWebImageDownloader.m @@ -288,6 +288,8 @@ void SDWebImageDownloaderOperationSetCompleted(id } #pragma mark Helper methods +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + (SDWebImageOptions)imageOptionsFromDownloaderOptions:(SDWebImageDownloaderOptions)downloadOptions { SDWebImageOptions options = 0; if (downloadOptions & SDWebImageDownloaderScaleDownLargeImages) options |= SDWebImageScaleDownLargeImages; @@ -298,6 +300,7 @@ void SDWebImageDownloaderOperationSetCompleted(id return options; } +#pragma clang diagnostic pop - (nullable NSOperation *)createDownloaderOperationWithUrl:(nonnull NSURL *)url options:(SDWebImageDownloaderOptions)options @@ -625,6 +628,8 @@ didReceiveResponse:(NSURLResponse *)response return YES; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" - (id)requestImageWithURL:(NSURL *)url options:(SDWebImageOptions)options context:(SDWebImageContext *)context progress:(SDImageLoaderProgressBlock)progressBlock completed:(SDImageLoaderCompletedBlock)completedBlock { UIImage *cachedImage = context[SDWebImageContextLoaderCachedImage]; @@ -651,6 +656,7 @@ didReceiveResponse:(NSURLResponse *)response return [self downloadImageWithURL:url options:downloaderOptions context:context progress:progressBlock completed:completedBlock]; } +#pragma clang diagnostic pop - (BOOL)shouldBlockFailedURLWithURL:(NSURL *)url error:(NSError *)error { return [self shouldBlockFailedURLWithURL:url error:error options:0 context:nil]; diff --git a/SDWebImage/Core/SDWebImageDownloaderOperation.m b/SDWebImage/Core/SDWebImageDownloaderOperation.m index 8b5e6be0..0ec65281 100644 --- a/SDWebImage/Core/SDWebImageDownloaderOperation.m +++ b/SDWebImage/Core/SDWebImageDownloaderOperation.m @@ -671,6 +671,8 @@ didReceiveResponse:(NSURLResponse *)response } #pragma mark Helper methods +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + (SDWebImageOptions)imageOptionsFromDownloaderOptions:(SDWebImageDownloaderOptions)downloadOptions { SDWebImageOptions options = 0; if (downloadOptions & SDWebImageDownloaderScaleDownLargeImages) options |= SDWebImageScaleDownLargeImages; @@ -681,6 +683,7 @@ didReceiveResponse:(NSURLResponse *)response return options; } +#pragma clang diagnostic pop - (BOOL)shouldContinueWhenAppEntersBackground { return SD_OPTIONS_CONTAINS(self.options, SDWebImageDownloaderContinueInBackground); diff --git a/SDWebImage/Core/UIImage+ForceDecode.h b/SDWebImage/Core/UIImage+ForceDecode.h index 18d0bf57..9d48a82f 100644 --- a/SDWebImage/Core/UIImage+ForceDecode.h +++ b/SDWebImage/Core/UIImage+ForceDecode.h @@ -20,7 +20,7 @@ -- 2. for non-ImageIO created image (via `CGImageCreate` API), we can ensure it's alignment is suitable to render on screen without copy by CoreAnimation @note For coder plugin developer, always use the SDImageCoderHelper's `colorSpaceGetDeviceRGB`/`preferredByteAlignment`/`preferredBitmapInfo:` to create CGImage. @note For more information why force decode, see: https://github.com/path/FastImageCache#byte-alignment - @note The defaults value is calculated based on UIImage's CGImage status. Do not assume it's always work as expected. Set the value to `true` if you don't need force decode + @note From v5.17.0, the default value is always NO. Use `SDImageForceDecodePolicy` to control complicated policy. */ @property (nonatomic, assign) BOOL sd_isDecoded; diff --git a/SDWebImage/Core/UIImage+ForceDecode.m b/SDWebImage/Core/UIImage+ForceDecode.m index 85cf6eb6..17b122eb 100644 --- a/SDWebImage/Core/UIImage+ForceDecode.m +++ b/SDWebImage/Core/UIImage+ForceDecode.m @@ -15,28 +15,7 @@ - (BOOL)sd_isDecoded { NSNumber *value = objc_getAssociatedObject(self, @selector(sd_isDecoded)); - if (value != nil) { - return value.boolValue; - } else { - // Assume only CGImage based can use lazy decoding - CGImageRef cgImage = self.CGImage; - BOOL isDecoded; - if (cgImage) { - CFStringRef uttype = CGImageGetUTType(self.CGImage); - if (uttype) { - // Only ImageIO can set `com.apple.ImageIO.imageSourceTypeIdentifier` - isDecoded = NO; - } else { - // Now, let's check if the CGImage is hardware supported (not byte-aligned will cause extra copy) - isDecoded = [SDImageCoderHelper CGImageIsHardwareSupported:cgImage]; - } - } else { - // Assume others as non-decoded - isDecoded = NO; - } - objc_setAssociatedObject(self, @selector(sd_isDecoded), @(isDecoded), OBJC_ASSOCIATION_RETAIN_NONATOMIC); - return isDecoded; - } + return [value boolValue]; } - (void)setSd_isDecoded:(BOOL)sd_isDecoded {