@@ -218,7 +218,22 @@ + (NSTimeInterval)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRe
218
218
return frameDuration;
219
219
}
220
220
221
- + (UIImage *)createFrameAtIndex : (NSUInteger )index source : (CGImageSourceRef)source scale : (CGFloat)scale preserveAspectRatio : (BOOL )preserveAspectRatio thumbnailSize : (CGSize)thumbnailSize lazyDecode : (BOOL )lazyDecode options : (NSDictionary *)options {
221
+ + (UIImage *)createFrameAtIndex : (NSUInteger )index source : (CGImageSourceRef)source scale : (CGFloat)scale preserveAspectRatio : (BOOL )preserveAspectRatio thumbnailSize : (CGSize)thumbnailSize lazyDecode : (BOOL )lazyDecode animatedImage : (BOOL )animatedImage {
222
+ // `animatedImage` means called from `SDAnimatedImageProvider.animatedImageFrameAtIndex`
223
+ NSDictionary *options;
224
+ if (animatedImage) {
225
+ if (!lazyDecode) {
226
+ options = @{
227
+ // image decoding and caching should happen at image creation time.
228
+ (__bridge NSString *)kCGImageSourceShouldCacheImmediately : @(YES ),
229
+ };
230
+ } else {
231
+ options = @{
232
+ // image decoding will happen at rendering time
233
+ (__bridge NSString *)kCGImageSourceShouldCacheImmediately : @(NO ),
234
+ };
235
+ }
236
+ }
222
237
// Some options need to pass to `CGImageSourceCopyPropertiesAtIndex` before `CGImageSourceCreateImageAtIndex`, or ImageIO will ignore them because they parse once :)
223
238
// Parse the image properties
224
239
NSDictionary *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex (source, index, (__bridge CFDictionaryRef)options);
@@ -287,7 +302,7 @@ + (UIImage *)createFrameAtIndex:(NSUInteger)index source:(CGImageSourceRef)sourc
287
302
isDecoded = YES ;
288
303
}
289
304
}
290
- } else {
305
+ } else if (animatedImage) {
291
306
// iOS 15+, CGImageRef now retains CGImageSourceRef internally. To workaround its thread-safe issue, we have to strip CGImageSourceRef, using Force-Decode (or have to use SPI `CGImageSetImageSource`), See: https://github.com/SDWebImage/SDWebImage/issues/3273
292
307
if (@available (iOS 15 , tvOS 15 , *)) {
293
308
// User pass `lazyDecode == YES`, but we still have to strip the CGImageSourceRef
@@ -297,21 +312,19 @@ + (UIImage *)createFrameAtIndex:(NSUInteger)index source:(CGImageSourceRef)sourc
297
312
CGImageRelease (imageRef);
298
313
imageRef = newImageRef;
299
314
}
300
- }
301
- }
302
315
#if SD_CHECK_CGIMAGE_RETAIN_SOURCE
303
- if (@available (iOS 15 , tvOS 15 , *)) {
304
- // Assert here to check CGImageRef should not retain the CGImageSourceRef and has possible thread-safe issue (this is behavior on iOS 15+)
305
- // If assert hit, fire issue to https://github.com/SDWebImage/SDWebImage/issues and we update the condition for this behavior check
306
- static dispatch_once_t onceToken;
307
- dispatch_once (&onceToken, ^{
308
- SDCGImageGetImageSource = dlsym (RTLD_DEFAULT, " CGImageGetImageSource" );
309
- });
310
- if (SDCGImageGetImageSource) {
311
- NSCAssert (!SDCGImageGetImageSource(imageRef), @"Animated Coder created CGImageRef should not retain CGImageSourceRef, which may cause thread-safe issue without lock");
316
+ // Assert here to check CGImageRef should not retain the CGImageSourceRef and has possible thread-safe issue (this is behavior on iOS 15+)
317
+ // If assert hit, fire issue to https://github.com/SDWebImage/SDWebImage/issues and we update the condition for this behavior check
318
+ static dispatch_once_t onceToken;
319
+ dispatch_once (&onceToken, ^{
320
+ SDCGImageGetImageSource = dlsym (RTLD_DEFAULT, " CGImageGetImageSource" );
321
+ });
322
+ if (SDCGImageGetImageSource) {
323
+ NSCAssert (!SDCGImageGetImageSource(imageRef), @"Animated Coder created CGImageRef should not retain CGImageSourceRef, which may cause thread-safe issue without lock");
324
+ }
325
+ #endif
312
326
}
313
327
}
314
- #endif
315
328
316
329
#if SD_UIKIT || SD_WATCH
317
330
UIImageOrientation imageOrientation = [SDImageCoderHelper imageOrientationFromEXIFOrientation: exifOrientation];
@@ -412,12 +425,12 @@ - (UIImage *)decodedImageWithData:(NSData *)data options:(nullable SDImageCoderO
412
425
413
426
BOOL decodeFirstFrame = [options[SDImageCoderDecodeFirstFrameOnly] boolValue ];
414
427
if (decodeFirstFrame || count <= 1 ) {
415
- animatedImage = [self .class createFrameAtIndex: 0 source: source scale: scale preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize lazyDecode: lazyDecode options: nil ];
428
+ animatedImage = [self .class createFrameAtIndex: 0 source: source scale: scale preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize lazyDecode: lazyDecode animatedImage: NO ];
416
429
} else {
417
430
NSMutableArray <SDImageFrame *> *frames = [NSMutableArray arrayWithCapacity: count];
418
431
419
432
for (size_t i = 0 ; i < count; i++) {
420
- UIImage *image = [self .class createFrameAtIndex: i source: source scale: scale preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize lazyDecode: lazyDecode options: nil ];
433
+ UIImage *image = [self .class createFrameAtIndex: i source: source scale: scale preserveAspectRatio: preserveAspectRatio thumbnailSize: thumbnailSize lazyDecode: lazyDecode animatedImage: NO ];
421
434
if (!image) {
422
435
continue ;
423
436
}
@@ -473,7 +486,7 @@ - (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)optio
473
486
preserveAspectRatio = preserveAspectRatioValue.boolValue ;
474
487
}
475
488
_preserveAspectRatio = preserveAspectRatio;
476
- BOOL lazyDecode = YES ; // Defaults YES for static image coder
489
+ BOOL lazyDecode = NO ; // Defaults NO for animated image coder
477
490
NSNumber *lazyDecodeValue = options[SDImageCoderDecodeUseLazyDecoding];
478
491
if (lazyDecodeValue != nil ) {
479
492
lazyDecode = lazyDecodeValue.boolValue ;
@@ -533,7 +546,7 @@ - (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
533
546
if (scaleFactor != nil ) {
534
547
scale = MAX ([scaleFactor doubleValue ], 1 );
535
548
}
536
- image = [self .class createFrameAtIndex: 0 source: _imageSource scale: scale preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize lazyDecode: _lazyDecode options: nil ];
549
+ image = [self .class createFrameAtIndex: 0 source: _imageSource scale: scale preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize lazyDecode: _lazyDecode animatedImage: NO ];
537
550
if (image) {
538
551
image.sd_imageFormat = self.class .imageFormat ;
539
552
}
@@ -695,6 +708,12 @@ - (nullable instancetype)initWithAnimatedImageData:(nullable NSData *)data optio
695
708
preserveAspectRatio = preserveAspectRatioValue.boolValue ;
696
709
}
697
710
_preserveAspectRatio = preserveAspectRatio;
711
+ BOOL lazyDecode = NO ; // Defaults NO for animated image coder
712
+ NSNumber *lazyDecodeValue = options[SDImageCoderDecodeUseLazyDecoding];
713
+ if (lazyDecodeValue != nil ) {
714
+ lazyDecode = lazyDecodeValue.boolValue ;
715
+ }
716
+ _lazyDecode = lazyDecode;
698
717
_imageSource = imageSource;
699
718
_imageData = data;
700
719
#if SD_UIKIT
@@ -785,24 +804,7 @@ - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {
785
804
}
786
805
787
806
- (UIImage *)safeAnimatedImageFrameAtIndex : (NSUInteger )index {
788
- NSDictionary *options;
789
- BOOL lazyDecode = NO ; // Defaults NO for animated image coder
790
- NSNumber *lazyDecodeValue = options[SDImageCoderDecodeUseLazyDecoding];
791
- if (lazyDecodeValue != nil ) {
792
- lazyDecode = lazyDecodeValue.boolValue ;
793
- }
794
- if (!lazyDecode) {
795
- options = @{
796
- (__bridge NSString *)kCGImageSourceShouldCacheImmediately : @(NO ),
797
- (__bridge NSString *)kCGImageSourceShouldCache : @(NO )
798
- };
799
- } else {
800
- options = @{
801
- (__bridge NSString *)kCGImageSourceShouldCacheImmediately : @(YES ),
802
- (__bridge NSString *)kCGImageSourceShouldCache : @(YES ) // Always cache to reduce CPU usage
803
- };
804
- }
805
- UIImage *image = [self .class createFrameAtIndex: index source: _imageSource scale: _scale preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize lazyDecode: lazyDecode options: options];
807
+ UIImage *image = [self .class createFrameAtIndex: index source: _imageSource scale: _scale preserveAspectRatio: _preserveAspectRatio thumbnailSize: _thumbnailSize lazyDecode: _lazyDecode animatedImage: YES ];
806
808
if (!image) {
807
809
return nil ;
808
810
}
0 commit comments