Performance enhancement: Allows to use progressive decoding image to callback the completion when finished. Which can reduce the decoding pressure and animation loading delay

This commit is contained in:
DreamPiggy 2021-03-04 18:42:11 +08:00
parent c82b7552b3
commit 2e7d526a69
3 changed files with 37 additions and 5 deletions

View File

@ -9,6 +9,7 @@
#import "SDWebImageCompat.h"
#import "SDWebImageDefine.h"
#import "SDWebImageOperation.h"
#import "SDImageCoder.h"
typedef void(^SDImageLoaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize, NSURL * _Nullable targetURL);
typedef void(^SDImageLoaderCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, BOOL finished);
@ -50,6 +51,18 @@ FOUNDATION_EXPORT UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Non
*/
FOUNDATION_EXPORT UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull imageData, NSURL * _Nonnull imageURL, BOOL finished, id<SDWebImageOperation> _Nonnull operation, SDWebImageOptions options, SDWebImageContext * _Nullable context);
/**
This function get the progressive decoder for current loading operation. If no progressive decoding is happended or decoder is not able to construct, return nil.
@return The progressive decoder associated with the loading operation.
*/
FOUNDATION_EXPORT id<SDProgressiveImageCoder> _Nullable SDImageLoaderGetProgressiveCoder(id<SDWebImageOperation> _Nonnull operation);
/**
This function set the progressive decoder for current loading operation. If no progressive decoding is happended, pass nil.
@param operation The loading operation to associate the progerssive decoder.
*/
FOUNDATION_EXPORT void SDImageLoaderSetProgressiveCoder(id<SDWebImageOperation> _Nonnull operation, id<SDProgressiveImageCoder> _Nullable progressiveCoder);
#pragma mark - SDImageLoader
/**

View File

@ -15,8 +15,20 @@
#import "SDInternalMacros.h"
#import "objc/runtime.h"
SDWebImageContextOption const SDWebImageContextLoaderCachedImage = @"loaderCachedImage";
static void * SDImageLoaderProgressiveCoderKey = &SDImageLoaderProgressiveCoderKey;
id<SDProgressiveImageCoder> SDImageLoaderGetProgressiveCoder(id<SDWebImageOperation> operation) {
NSCParameterAssert(operation);
return objc_getAssociatedObject(operation, SDImageLoaderProgressiveCoderKey);
}
void SDImageLoaderSetProgressiveCoder(id<SDWebImageOperation> operation, id<SDProgressiveImageCoder> progressiveCoder) {
NSCParameterAssert(operation);
objc_setAssociatedObject(operation, SDImageLoaderProgressiveCoderKey, progressiveCoder, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
UIImage * _Nullable SDImageLoaderDecodeImageData(NSData * _Nonnull imageData, NSURL * _Nonnull imageURL, SDWebImageOptions options, SDWebImageContext * _Nullable context) {
NSCParameterAssert(imageData);
NSCParameterAssert(imageURL);
@ -136,7 +148,7 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im
SDImageCoderOptions *coderOptions = [mutableCoderOptions copy];
// Grab the progressive image coder
id<SDProgressiveImageCoder> progressiveCoder = objc_getAssociatedObject(operation, SDImageLoaderProgressiveCoderKey);
id<SDProgressiveImageCoder> progressiveCoder = SDImageLoaderGetProgressiveCoder(operation);
if (!progressiveCoder) {
id<SDProgressiveImageCoder> imageCoder = context[SDWebImageContextImageCoder];
// Check the progressive coder if provided
@ -152,7 +164,7 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im
}
}
}
objc_setAssociatedObject(operation, SDImageLoaderProgressiveCoderKey, progressiveCoder, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
SDImageLoaderSetProgressiveCoder(operation, progressiveCoder);
}
// If we can't find any progressive coder, disable progressive download
if (!progressiveCoder) {
@ -196,5 +208,3 @@ UIImage * _Nullable SDImageLoaderDecodeProgressiveImageData(NSData * _Nonnull im
return image;
}
SDWebImageContextOption const SDWebImageContextLoaderCachedImage = @"loaderCachedImage";

View File

@ -11,6 +11,7 @@
#import "SDInternalMacros.h"
#import "SDWebImageDownloaderResponseModifier.h"
#import "SDWebImageDownloaderDecryptor.h"
#import "SDAnimatedImage.h"
static NSString *const kProgressCallbackKey = @"progress";
static NSString *const kCompletedCallbackKey = @"completed";
@ -262,6 +263,7 @@ typedef NSMutableDictionary<NSString *, id> SDCallbacksDictionary;
- (void)done {
self.finished = YES;
self.executing = NO;
SDImageLoaderSetProgressiveCoder(self, nil);
[self reset];
}
@ -471,7 +473,14 @@ didReceiveResponse:(NSURLResponse *)response
// decode the image in coder queue, cancel all previous decoding process
[self.coderQueue cancelAllOperations];
[self.coderQueue addOperationWithBlock:^{
UIImage *image = SDImageLoaderDecodeImageData(imageData, self.request.URL, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
// check if we already use progressive decoding, use that to produce faster decoding
id<SDProgressiveImageCoder> progressiveCoder = SDImageLoaderGetProgressiveCoder(self);
UIImage *image;
if (progressiveCoder) {
image = SDImageLoaderDecodeProgressiveImageData(imageData, self.request.URL, YES, self, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
} else {
image = SDImageLoaderDecodeImageData(imageData, self.request.URL, [[self class] imageOptionsFromDownloaderOptions:self.options], self.context);
}
CGSize imageSize = image.size;
if (imageSize.width == 0 || imageSize.height == 0) {
NSString *description = image == nil ? @"Downloaded image decode failed" : @"Downloaded image has 0 pixels";