Skip to content

Commit

Permalink
Revert "Animated image improvements (facebook#24822)"
Browse files Browse the repository at this point in the history
This reverts commit 3b67bfa.
  • Loading branch information
janicduplessis committed Jul 28, 2019
1 parent 73299ff commit 005709b
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 535 deletions.
21 changes: 0 additions & 21 deletions Libraries/Image/RCTAnimatedImage.h

This file was deleted.

166 changes: 0 additions & 166 deletions Libraries/Image/RCTAnimatedImage.m

This file was deleted.

92 changes: 87 additions & 5 deletions Libraries/Image/RCTGIFImageDecoder.m
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
#import <QuartzCore/QuartzCore.h>

#import <React/RCTUtils.h>
#import <React/RCTAnimatedImage.h>

@implementation RCTGIFImageDecoder

Expand All @@ -31,13 +30,96 @@ - (RCTImageLoaderCancellationBlock)decodeImageData:(NSData *)imageData
resizeMode:(RCTResizeMode)resizeMode
completionHandler:(RCTImageLoaderCompletionBlock)completionHandler
{
RCTAnimatedImage *image = [[RCTAnimatedImage alloc] initWithData:imageData scale:scale];

if (!image) {
CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL);
if (!imageSource) {
completionHandler(nil, nil);
return ^{};
}

NSDictionary<NSString *, id> *properties = (__bridge_transfer NSDictionary *)CGImageSourceCopyProperties(imageSource, NULL);
CGFloat loopCount = 0;
if ([[properties[(id)kCGImagePropertyGIFDictionary] allKeys] containsObject:(id)kCGImagePropertyGIFLoopCount]) {
loopCount = [properties[(id)kCGImagePropertyGIFDictionary][(id)kCGImagePropertyGIFLoopCount] unsignedIntegerValue];
if (loopCount == 0) {
// A loop count of 0 means infinite
loopCount = HUGE_VALF;
} else {
// A loop count of 1 means it should repeat twice, 2 means, thrice, etc.
loopCount += 1;
}
}

UIImage *image = nil;
size_t imageCount = CGImageSourceGetCount(imageSource);
if (imageCount > 1) {

NSTimeInterval duration = 0;
NSMutableArray<NSNumber *> *delays = [NSMutableArray arrayWithCapacity:imageCount];
NSMutableArray<id /* CGIMageRef */> *images = [NSMutableArray arrayWithCapacity:imageCount];
for (size_t i = 0; i < imageCount; i++) {

CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, i, NULL);
if (!imageRef) {
continue;
}
if (!image) {
image = [UIImage imageWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
}

NSDictionary<NSString *, id> *frameProperties = (__bridge_transfer NSDictionary *)CGImageSourceCopyPropertiesAtIndex(imageSource, i, NULL);
NSDictionary<NSString *, id> *frameGIFProperties = frameProperties[(id)kCGImagePropertyGIFDictionary];

const NSTimeInterval kDelayTimeIntervalDefault = 0.1;
NSNumber *delayTime = frameGIFProperties[(id)kCGImagePropertyGIFUnclampedDelayTime] ?: frameGIFProperties[(id)kCGImagePropertyGIFDelayTime];
if (delayTime == nil) {
if (delays.count == 0) {
delayTime = @(kDelayTimeIntervalDefault);
} else {
delayTime = delays.lastObject;
}
}

const NSTimeInterval kDelayTimeIntervalMinimum = 0.02;
if (delayTime.floatValue < (float)kDelayTimeIntervalMinimum - FLT_EPSILON) {
delayTime = @(kDelayTimeIntervalDefault);
}

duration += delayTime.doubleValue;
[delays addObject:delayTime];
[images addObject:(__bridge_transfer id)imageRef];
}
CFRelease(imageSource);

NSMutableArray<NSNumber *> *keyTimes = [NSMutableArray arrayWithCapacity:delays.count];
NSTimeInterval runningDuration = 0;
for (NSNumber *delayNumber in delays) {
[keyTimes addObject:@(runningDuration / duration)];
runningDuration += delayNumber.doubleValue;
}

[keyTimes addObject:@1.0];

// Create animation
CAKeyframeAnimation *animation = [CAKeyframeAnimation animationWithKeyPath:@"contents"];
animation.calculationMode = kCAAnimationDiscrete;
animation.repeatCount = loopCount;
animation.keyTimes = keyTimes;
animation.values = images;
animation.duration = duration;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
image.reactKeyframeAnimation = animation;

} else {

// Don't bother creating an animation
CGImageRef imageRef = CGImageSourceCreateImageAtIndex(imageSource, 0, NULL);
if (imageRef) {
image = [UIImage imageWithCGImage:imageRef scale:scale orientation:UIImageOrientationUp];
CFRelease(imageRef);
}
CFRelease(imageSource);
}

completionHandler(nil, image);
return ^{};
}
Expand Down
5 changes: 2 additions & 3 deletions Libraries/Image/RCTImageView.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
#import <SDWebImage/UIImageView+WebCache.h>
#import <SDWebImagePhotosPlugin/SDWebImagePhotosPlugin.h>

#import <React/RCTUIImageViewAnimated.h>
#import <React/RCTImageBlurUtils.h>
#import <React/RCTImageLoader.h>
#import <React/RCTImageUtils.h>
Expand Down Expand Up @@ -82,7 +81,7 @@ @implementation RCTImageView
// Whether the latest change of props requires the image to be reloaded
BOOL _needsReload;

RCTUIImageViewAnimated *_imageView;
UIImageView *_imageView;
}

- (instancetype)initWithBridge:(RCTBridge *)bridge
Expand All @@ -98,7 +97,7 @@ - (instancetype)initWithBridge:(RCTBridge *)bridge
selector:@selector(clearImageIfDetached)
name:UIApplicationDidEnterBackgroundNotification
object:nil];
_imageView = [[RCTUIImageViewAnimated alloc] init];
_imageView = [[UIImageView alloc] init];
_imageView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[self addSubview:_imageView];
}
Expand Down
12 changes: 0 additions & 12 deletions Libraries/Image/RCTUIImageViewAnimated.h

This file was deleted.

Loading

0 comments on commit 005709b

Please sign in to comment.