Skip to content

Commit 69e91f0

Browse files
Revert "Animated image improvements (facebook#24822)"
This reverts commit 3b67bfa.
1 parent 407d2c4 commit 69e91f0

File tree

2 files changed

+89
-6
lines changed

2 files changed

+89
-6
lines changed

Libraries/Image/RCTGIFImageDecoder.m

+87-4
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,96 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)imageData
3131
resizeMode:(RCTResizeMode)resizeMode
3232
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
3333
{
34-
RCTAnimatedImage *image = [[RCTAnimatedImage alloc] initWithData:imageData scale:scale];
35-
36-
if (!image) {
34+
CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
35+
if (!imageSource) {
3736
completionHandler(nil, nil);
3837
return ^{};
3938
}
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+
41124
completionHandler(nil, image);
42125
return ^{};
43126
}

Libraries/Image/RCTImageView.m

+2-2
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ @implementation RCTImageView
8282
// Whether the latest change of props requires the image to be reloaded
8383
BOOL _needsReload;
8484

85-
RCTUIImageViewAnimated *_imageView;
85+
UIImageView *_imageView;
8686
}
8787

8888
- (instancetype)initWithBridge:(RCTBridge *)bridge
@@ -98,7 +98,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
9898
selector:@selector(clearImageIfDetached)
9999
name:UIApplicationDidEnterBackgroundNotification
100100
object:nil];
101-
_imageView = [[RCTUIImageViewAnimated alloc] init];
101+
_imageView = [[UIImageView alloc] init];
102102
_imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
103103
[self addSubview:_imageView];
104104
}

0 commit comments

Comments
 (0)