Skip to content

Commit 985c84b

Browse files
committed
Opt the macOS legacy animated encode, with the weak assigned frames to avoid re-decode again
It's still recommended to use the new API
1 parent 8ec3bc8 commit 985c84b

File tree

3 files changed

+47
-0
lines changed

3 files changed

+47
-0
lines changed

SDWebImage/Core/SDAnimatedImageRep.m

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
#import "SDImageHEICCoder.h"
1717
#import "SDImageAWebPCoder.h"
1818

19+
@interface SDAnimatedImageRep ()
20+
/// This wrap the animated image frames for legacy animated image coder API (`encodedDataWithImage:`).
21+
@property (nonatomic, readwrite, weak) NSArray<SDImageFrame *> *frames;
22+
@end
23+
1924
@implementation SDAnimatedImageRep {
2025
CGImageSourceRef _imageSource;
2126
}

SDWebImage/Core/SDImageCoderHelper.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,13 @@ static inline BOOL SDImageSupportsHardwareHEVCDecoder(void) {
9494

9595
static const CGFloat kDestSeemOverlap = 2.0f; // the numbers of pixels to overlap the seems where tiles meet.
9696

97+
#if SD_MAC
98+
@interface SDAnimatedImageRep (Private)
99+
/// This wrap the animated image frames for legacy animated image coder API (`encodedDataWithImage:`).
100+
@property (nonatomic, readwrite, weak) NSArray<SDImageFrame *> *frames;
101+
@end
102+
#endif
103+
97104
@implementation SDImageCoderHelper
98105

99106
+ (UIImage *)animatedImageWithFrames:(NSArray<SDImageFrame *> *)frames {
@@ -159,6 +166,7 @@ + (UIImage *)animatedImageWithFrames:(NSArray<SDImageFrame *> *)frames {
159166
SDAnimatedImageRep *imageRep = [[SDAnimatedImageRep alloc] initWithData:imageData];
160167
NSSize size = NSMakeSize(imageRep.pixelsWide / scale, imageRep.pixelsHigh / scale);
161168
imageRep.size = size;
169+
imageRep.frames = frames; // Weak assign to avoid effect lazy semantic of NSBitmapImageRep
162170
animatedImage = [[NSImage alloc] initWithSize:size];
163171
[animatedImage addRepresentation:imageRep];
164172
#endif
@@ -211,6 +219,14 @@ + (UIImage *)animatedImageWithFrames:(NSArray<SDImageFrame *> *)frames {
211219

212220
NSRect imageRect = NSMakeRect(0, 0, animatedImage.size.width, animatedImage.size.height);
213221
NSImageRep *imageRep = [animatedImage bestRepresentationForRect:imageRect context:nil hints:nil];
222+
// Check weak assigned frames firstly
223+
if ([imageRep isKindOfClass:[SDAnimatedImageRep class]]) {
224+
SDAnimatedImageRep *animatedImageRep = (SDAnimatedImageRep *)imageRep;
225+
if (animatedImageRep.frames) {
226+
return animatedImageRep.frames;
227+
}
228+
}
229+
214230
NSBitmapImageRep *bitmapImageRep;
215231
if ([imageRep isKindOfClass:[NSBitmapImageRep class]]) {
216232
bitmapImageRep = (NSBitmapImageRep *)imageRep;

Tests/Tests/SDImageCoderTests.m

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,32 @@ - (void)test26ThatRawImageTypeHintWorks {
422422
#endif
423423
}
424424

425+
- (void)test27ThatEncodeWithFramesWorks {
426+
// Mock
427+
NSMutableArray<SDImageFrame *> *frames = [NSMutableArray array];
428+
NSUInteger frameCount = 5;
429+
for (size_t i = 0; i < frameCount; i++) {
430+
CGSize size = CGSizeMake(100, 100);
431+
SDGraphicsImageRenderer *renderer = [[SDGraphicsImageRenderer alloc] initWithSize:size];
432+
UIImage *image = [renderer imageWithActions:^(CGContextRef _Nonnull context) {
433+
CGContextSetRGBFillColor(context, 1.0 / i, 0.0, 0.0, 1.0);
434+
CGContextSetRGBStrokeColor(context, 1.0 / i, 0.0, 0.0, 1.0);
435+
CGContextFillRect(context, CGRectMake(0, 0, size.width, size.height));
436+
}];
437+
SDImageFrame *frame = [SDImageFrame frameWithImage:image duration:0.1];
438+
[frames addObject:frame];
439+
}
440+
441+
// Test old API
442+
UIImage *animatedImage = [SDImageCoderHelper animatedImageWithFrames:frames];
443+
NSData *data = [SDImageGIFCoder.sharedCoder encodedDataWithImage:animatedImage format:SDImageFormatGIF options:nil];
444+
expect(data).notTo.beNil();
445+
446+
// Test new API
447+
NSData *data2 = [SDImageGIFCoder.sharedCoder encodedDataWithFrames:frames loopCount:0 format:SDImageFormatGIF options:nil];
448+
expect(data2).notTo.beNil();
449+
}
450+
425451
#pragma mark - Utils
426452

427453
- (void)verifyCoder:(id<SDImageCoder>)coder

0 commit comments

Comments
 (0)