Skip to content

Commit 7c63bad

Browse files
authored
Merge pull request SDWebImage#3466 from dreampiggy/feat/encode_options
Added `SDWebImageContextImageEncodeOptions` to pass encode options like compression quality to SDImageCache storeImage API. Seperate the SDImageCache encode queue and IO queue to match waitStoreCache behavior
2 parents 05f7fb9 + 911a9a8 commit 7c63bad

File tree

7 files changed

+174
-126
lines changed

7 files changed

+174
-126
lines changed

SDWebImage/Core/SDImageCache.m

Lines changed: 37 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ - (void)storeImage:(nullable UIImage *)image
220220
forKey:(nullable NSString *)key
221221
toDisk:(BOOL)toDisk
222222
completion:(nullable SDWebImageNoParamsBlock)completionBlock {
223-
return [self storeImage:image imageData:imageData forKey:key options:0 context:nil cacheType:(toDisk ? SDImageCacheTypeDisk : SDImageCacheTypeMemory) completion:completionBlock];
223+
[self storeImage:image imageData:imageData forKey:key options:0 context:nil cacheType:(toDisk ? SDImageCacheTypeAll : SDImageCacheTypeMemory) completion:completionBlock];
224224
}
225225

226226
- (void)storeImage:(nullable UIImage *)image
@@ -250,38 +250,47 @@ - (void)storeImage:(nullable UIImage *)image
250250
}
251251
return;
252252
}
253+
NSData *data = imageData;
254+
if (!data && [image respondsToSelector:@selector(animatedImageData)]) {
255+
// If image is custom animated image class, prefer its original animated data
256+
data = [((id<SDAnimatedImage>)image) animatedImageData];
257+
}
253258
SDCallbackQueue *queue = context[SDWebImageContextCallbackQueue];
254-
dispatch_async(self.ioQueue, ^{
255-
@autoreleasepool {
256-
NSData *data = imageData;
257-
if (!data && [image respondsToSelector:@selector(animatedImageData)]) {
258-
// If image is custom animated image class, prefer its original animated data
259-
data = [((id<SDAnimatedImage>)image) animatedImageData];
260-
}
261-
if (!data && image) {
262-
// Check image's associated image format, may return .undefined
263-
SDImageFormat format = image.sd_imageFormat;
264-
if (format == SDImageFormatUndefined) {
265-
// If image is animated, use GIF (APNG may be better, but has bugs before macOS 10.14)
266-
if (image.sd_isAnimated) {
267-
format = SDImageFormatGIF;
268-
} else {
269-
// If we do not have any data to detect image format, check whether it contains alpha channel to use PNG or JPEG format
270-
format = [SDImageCoderHelper CGImageContainsAlpha:image.CGImage] ? SDImageFormatPNG : SDImageFormatJPEG;
271-
}
259+
if (!data && image) {
260+
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
261+
// Check image's associated image format, may return .undefined
262+
SDImageFormat format = image.sd_imageFormat;
263+
if (format == SDImageFormatUndefined) {
264+
// If image is animated, use GIF (APNG may be better, but has bugs before macOS 10.14)
265+
if (image.sd_isAnimated) {
266+
format = SDImageFormatGIF;
267+
} else {
268+
// If we do not have any data to detect image format, check whether it contains alpha channel to use PNG or JPEG format
269+
format = [SDImageCoderHelper CGImageContainsAlpha:image.CGImage] ? SDImageFormatPNG : SDImageFormatJPEG;
272270
}
273-
data = [[SDImageCodersManager sharedManager] encodedDataWithImage:image format:format options:nil];
274271
}
272+
NSData *data = [[SDImageCodersManager sharedManager] encodedDataWithImage:image format:format options:context[SDWebImageContextImageEncodeOptions]];
273+
dispatch_async(self.ioQueue, ^{
274+
[self _storeImageDataToDisk:data forKey:key];
275+
[self _archivedDataWithImage:image forKey:key];
276+
if (completionBlock) {
277+
[(queue ?: SDCallbackQueue.mainQueue) async:^{
278+
completionBlock();
279+
}];
280+
}
281+
});
282+
});
283+
} else {
284+
dispatch_async(self.ioQueue, ^{
275285
[self _storeImageDataToDisk:data forKey:key];
276286
[self _archivedDataWithImage:image forKey:key];
277-
}
278-
279-
if (completionBlock) {
280-
[(queue ?: SDCallbackQueue.mainQueue) async:^{
281-
completionBlock();
282-
}];
283-
}
284-
});
287+
if (completionBlock) {
288+
[(queue ?: SDCallbackQueue.mainQueue) async:^{
289+
completionBlock();
290+
}];
291+
}
292+
});
293+
}
285294
}
286295

287296
- (void)_archivedDataWithImage:(UIImage *)image forKey:(NSString *)key {

SDWebImage/Core/SDImageCacheDefine.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ FOUNDATION_EXPORT void SDSetDecodeOptionsToContext(SDWebImageMutableContext * _N
122122
imageData:(nullable NSData *)imageData
123123
forKey:(nullable NSString *)key
124124
cacheType:(SDImageCacheType)cacheType
125-
completion:(nullable SDWebImageNoParamsBlock)completionBlock API_DEPRECATED_WITH_REPLACEMENT("storeImage:imageData:forKey:options:context:cacheType:completion:", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));;
125+
completion:(nullable SDWebImageNoParamsBlock)completionBlock API_DEPRECATED_WITH_REPLACEMENT("storeImage:imageData:forKey:options:context:cacheType:completion:", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));
126126

127127
@optional
128128
/**
@@ -144,7 +144,7 @@ FOUNDATION_EXPORT void SDSetDecodeOptionsToContext(SDWebImageMutableContext * _N
144144
cacheType:(SDImageCacheType)cacheType
145145
completion:(nullable SDWebImageNoParamsBlock)completionBlock;
146146

147-
@required
147+
#pragma mark - Deprecated because SDWebImageManager does not use these APIs
148148
/**
149149
Remove the image from image cache for the given key. If cache type is memory only, completion is called synchronously, else asynchronously.
150150
@@ -154,7 +154,7 @@ FOUNDATION_EXPORT void SDSetDecodeOptionsToContext(SDWebImageMutableContext * _N
154154
*/
155155
- (void)removeImageForKey:(nullable NSString *)key
156156
cacheType:(SDImageCacheType)cacheType
157-
completion:(nullable SDWebImageNoParamsBlock)completionBlock;
157+
completion:(nullable SDWebImageNoParamsBlock)completionBlock API_DEPRECATED("No longer use. Cast to cache instance and call its API", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));
158158

159159
/**
160160
Check if image cache contains the image for the given key (does not load the image). If image is cached in memory, completion is called synchronously, else asynchronously.
@@ -165,7 +165,7 @@ FOUNDATION_EXPORT void SDSetDecodeOptionsToContext(SDWebImageMutableContext * _N
165165
*/
166166
- (void)containsImageForKey:(nullable NSString *)key
167167
cacheType:(SDImageCacheType)cacheType
168-
completion:(nullable SDImageCacheContainsCompletionBlock)completionBlock;
168+
completion:(nullable SDImageCacheContainsCompletionBlock)completionBlock API_DEPRECATED("No longer use. Cast to cache instance and call its API", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));
169169

170170
/**
171171
Clear all the cached images for image cache. If cache type is memory only, completion is called synchronously, else asynchronously.
@@ -174,6 +174,6 @@ FOUNDATION_EXPORT void SDSetDecodeOptionsToContext(SDWebImageMutableContext * _N
174174
@param completionBlock A block executed after the operation is finished
175175
*/
176176
- (void)clearWithCacheType:(SDImageCacheType)cacheType
177-
completion:(nullable SDWebImageNoParamsBlock)completionBlock;
177+
completion:(nullable SDWebImageNoParamsBlock)completionBlock API_DEPRECATED("No longer use. Cast to cache instance and call its API", macos(10.10, API_TO_BE_DEPRECATED), ios(8.0, API_TO_BE_DEPRECATED), tvos(9.0, API_TO_BE_DEPRECATED), watchos(2.0, API_TO_BE_DEPRECATED));
178178

179179
@end

SDWebImage/Core/SDWebImageDefine.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -295,6 +295,13 @@ FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageT
295295

296296
#pragma mark - Cache Context Options
297297

298+
/**
299+
A Dictionary (SDImageCoderOptions) value, which pass the extra encode options to the SDImageCoder. Introduced in SDWebImage 5.15.0
300+
You can pass encode options like `compressionQuality`, `maxFileSize`, `maxPixelSize` to control the encoding related thing, this is used inside `SDImageCache` during store logic.
301+
@note For developer who use custom cache protocol (not SDImageCache instance), they need to upgrade and use these options for encoding.
302+
*/
303+
FOUNDATION_EXPORT SDWebImageContextOption _Nonnull const SDWebImageContextImageEncodeOptions;
304+
298305
/**
299306
A SDImageCacheType raw value which specify the source of cache to query. Specify `SDImageCacheTypeDisk` to query from disk cache only; `SDImageCacheTypeMemory` to query from memory only. And `SDImageCacheTypeAll` to query from both memory cache and disk cache. Specify `SDImageCacheTypeNone` is invalid and totally ignore the cache query.
300307
If not provide or the value is invalid, we will use `SDImageCacheTypeAll`. (NSNumber)

SDWebImage/Core/SDWebImageDefine.m

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ inline CGFloat SDImageScaleFactorForKey(NSString * _Nullable key) {
137137
SDWebImageContextOption const SDWebImageContextImagePreserveAspectRatio = @"imagePreserveAspectRatio";
138138
SDWebImageContextOption const SDWebImageContextImageThumbnailPixelSize = @"imageThumbnailPixelSize";
139139
SDWebImageContextOption const SDWebImageContextImageTypeIdentifierHint = @"imageTypeIdentifierHint";
140+
SDWebImageContextOption const SDWebImageContextImageEncodeOptions = @"imageEncodeOptions";
140141
SDWebImageContextOption const SDWebImageContextQueryCacheType = @"queryCacheType";
141142
SDWebImageContextOption const SDWebImageContextStoreCacheType = @"storeCacheType";
142143
SDWebImageContextOption const SDWebImageContextOriginalQueryCacheType = @"originalQueryCacheType";

SDWebImage/Core/SDWebImageManager.m

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -499,18 +499,16 @@ - (void)callTransformProcessForOperation:(nonnull SDWebImageCombinedOperation *)
499499
}
500500

501501
if (shouldTransformImage) {
502+
// transformed cache key
503+
NSString *key = [self cacheKeyForURL:url context:context];
502504
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
503-
@autoreleasepool {
504-
// transformed cache key
505-
NSString *key = [self cacheKeyForURL:url context:context];
506-
// Case that transformer on thumbnail, which this time need full pixel image
507-
UIImage *transformedImage = [transformer transformedImageWithImage:cacheImage forKey:key];
508-
if (transformedImage) {
509-
transformedImage.sd_isTransformed = YES;
510-
[self callStoreOriginCacheProcessForOperation:operation url:url options:options context:context originalImage:originalImage cacheImage:transformedImage originalData:originalData cacheData:nil cacheType:cacheType finished:finished completed:completedBlock];
511-
} else {
512-
[self callStoreOriginCacheProcessForOperation:operation url:url options:options context:context originalImage:originalImage cacheImage:cacheImage originalData:originalData cacheData:cacheData cacheType:cacheType finished:finished completed:completedBlock];
513-
}
505+
// Case that transformer on thumbnail, which this time need full pixel image
506+
UIImage *transformedImage = [transformer transformedImageWithImage:cacheImage forKey:key];
507+
if (transformedImage) {
508+
transformedImage.sd_isTransformed = YES;
509+
[self callStoreOriginCacheProcessForOperation:operation url:url options:options context:context originalImage:originalImage cacheImage:transformedImage originalData:originalData cacheData:nil cacheType:cacheType finished:finished completed:completedBlock];
510+
} else {
511+
[self callStoreOriginCacheProcessForOperation:operation url:url options:options context:context originalImage:originalImage cacheImage:cacheImage originalData:originalData cacheData:cacheData cacheType:cacheType finished:finished completed:completedBlock];
514512
}
515513
});
516514
} else {
@@ -557,14 +555,12 @@ - (void)callStoreOriginCacheProcessForOperation:(nonnull SDWebImageCombinedOpera
557555
NSString *key = [self originalCacheKeyForURL:url context:context];
558556
if (finished && cacheSerializer && (originalStoreCacheType == SDImageCacheTypeDisk || originalStoreCacheType == SDImageCacheTypeAll)) {
559557
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
560-
@autoreleasepool {
561-
NSData *newOriginalData = [cacheSerializer cacheDataWithImage:originalImage originalData:originalData imageURL:url];
562-
// Store original image and data
563-
[self storeImage:originalImage imageData:newOriginalData forKey:key options:options context:context imageCache:imageCache cacheType:originalStoreCacheType finished:finished completion:^{
564-
// Continue store cache process, transformed data is nil
565-
[self callStoreCacheProcessForOperation:operation url:url options:options context:context image:cacheImage data:cacheData cacheType:cacheType finished:finished completed:completedBlock];
566-
}];
567-
}
558+
NSData *newOriginalData = [cacheSerializer cacheDataWithImage:originalImage originalData:originalData imageURL:url];
559+
// Store original image and data
560+
[self storeImage:originalImage imageData:newOriginalData forKey:key options:options context:context imageCache:imageCache cacheType:originalStoreCacheType finished:finished completion:^{
561+
// Continue store cache process, transformed data is nil
562+
[self callStoreCacheProcessForOperation:operation url:url options:options context:context image:cacheImage data:cacheData cacheType:cacheType finished:finished completed:completedBlock];
563+
}];
568564
});
569565
} else {
570566
// Store original image and data

0 commit comments

Comments
 (0)