@@ -31,13 +31,96 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)imageData
31
31
resizeMode : (RCTResizeMode)resizeMode
32
32
completionHandler : (RCTImageLoaderCompletionBlock)completionHandler
33
33
{
34
- RCTAnimatedImage *image = [[RCTAnimatedImage alloc ] initWithData: imageData scale: scale];
35
-
36
- if (!image) {
34
+ CGImageSourceRef imageSource = CGImageSourceCreateWithData ((CFDataRef )imageData, NULL );
35
+ if (!imageSource) {
37
36
completionHandler (nil , nil );
38
37
return ^{};
39
38
}
40
-
39
+ NSDictionary <NSString *, id > *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties (imageSource, NULL );
40
+ CGFloat loopCount = 0 ;
41
+ if ([[properties[(id )kCGImagePropertyGIFDictionary ] allKeys ] containsObject: (id )kCGImagePropertyGIFLoopCount ]) {
42
+ loopCount = [properties[(id )kCGImagePropertyGIFDictionary ][(id )kCGImagePropertyGIFLoopCount ] unsignedIntegerValue ];
43
+ if (loopCount == 0 ) {
44
+ // A loop count of 0 means infinite
45
+ loopCount = HUGE_VALF;
46
+ } else {
47
+ // A loop count of 1 means it should repeat twice, 2 means, thrice, etc.
48
+ loopCount += 1 ;
49
+ }
50
+ }
51
+
52
+ UIImage *image = nil ;
53
+ size_t imageCount = CGImageSourceGetCount (imageSource);
54
+ if (imageCount > 1 ) {
55
+
56
+ NSTimeInterval duration = 0 ;
57
+ NSMutableArray <NSNumber *> *delays = [NSMutableArray arrayWithCapacity: imageCount];
58
+ NSMutableArray <id /* CGIMageRef */ > *images = [NSMutableArray arrayWithCapacity: imageCount];
59
+ for (size_t i = 0 ; i < imageCount; i++) {
60
+
61
+ CGImageRef imageRef = CGImageSourceCreateImageAtIndex (imageSource, i, NULL );
62
+ if (!imageRef) {
63
+ continue ;
64
+ }
65
+ if (!image) {
66
+ image = [UIImage imageWithCGImage: imageRef scale: scale orientation: UIImageOrientationUp];
67
+ }
68
+
69
+ NSDictionary <NSString *, id > *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex (imageSource, i, NULL );
70
+ NSDictionary <NSString *, id > *frameGIFProperties = frameProperties[(id )kCGImagePropertyGIFDictionary ];
71
+
72
+ const NSTimeInterval kDelayTimeIntervalDefault = 0.1 ;
73
+ NSNumber *delayTime = frameGIFProperties[(id )kCGImagePropertyGIFUnclampedDelayTime ] ?: frameGIFProperties[(id )kCGImagePropertyGIFDelayTime ];
74
+ if (delayTime == nil ) {
75
+ if (delays.count == 0 ) {
76
+ delayTime = @(kDelayTimeIntervalDefault );
77
+ } else {
78
+ delayTime = delays.lastObject ;
79
+ }
80
+ }
81
+
82
+ const NSTimeInterval kDelayTimeIntervalMinimum = 0.02 ;
83
+ if (delayTime.floatValue < (float )kDelayTimeIntervalMinimum - FLT_EPSILON) {
84
+ delayTime = @(kDelayTimeIntervalDefault );
85
+ }
86
+
87
+ duration += delayTime.doubleValue ;
88
+ [delays addObject: delayTime];
89
+ [images addObject: (__bridge_transfer id )imageRef];
90
+ }
91
+ CFRelease (imageSource);
92
+
93
+ NSMutableArray <NSNumber *> *keyTimes = [NSMutableArray arrayWithCapacity: delays.count];
94
+ NSTimeInterval runningDuration = 0 ;
95
+ for (NSNumber *delayNumber in delays) {
96
+ [keyTimes addObject: @(runningDuration / duration)];
97
+ runningDuration += delayNumber.doubleValue ;
98
+ }
99
+
100
+ [keyTimes addObject: @1.0 ];
101
+
102
+ // Create animation
103
+ CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath: @" contents" ];
104
+ animation.calculationMode = kCAAnimationDiscrete ;
105
+ animation.repeatCount = loopCount;
106
+ animation.keyTimes = keyTimes;
107
+ animation.values = images;
108
+ animation.duration = duration;
109
+ animation.removedOnCompletion = NO ;
110
+ animation.fillMode = kCAFillModeForwards ;
111
+ image.reactKeyframeAnimation = animation;
112
+
113
+ } else {
114
+
115
+ // Don't bother creating an animation
116
+ CGImageRef imageRef = CGImageSourceCreateImageAtIndex (imageSource, 0 , NULL );
117
+ if (imageRef) {
118
+ image = [UIImage imageWithCGImage: imageRef scale: scale orientation: UIImageOrientationUp];
119
+ CFRelease (imageRef);
120
+ }
121
+ CFRelease (imageSource);
122
+ }
123
+
41
124
completionHandler (nil , image);
42
125
return ^{};
43
126
}
0 commit comments