diff --git a/Libraries/Image/RCTImageCache.m b/Libraries/Image/RCTImageCache.m index ca116b5d0..a25f35222 100644 --- a/Libraries/Image/RCTImageCache.m +++ b/Libraries/Image/RCTImageCache.m @@ -71,7 +71,7 @@ static NSString *RCTCacheKeyForImage(NSString *imageTag, CGSize size, CGFloat sc if (!image) { return; } - CGFloat bytes = image.size.width * image.size.height * image.scale * image.scale * 4; + NSInteger bytes = image.reactDecodedImageBytes; if (bytes <= RCTMaxCachableDecodedImageSizeInBytes) { [self->_decodedImageCache setObject:image forKey:cacheKey diff --git a/Libraries/Image/RCTImageLoader.h b/Libraries/Image/RCTImageLoader.h index 57a6db76d..90a0a43a7 100644 --- a/Libraries/Image/RCTImageLoader.h +++ b/Libraries/Image/RCTImageLoader.h @@ -52,6 +52,11 @@ typedef dispatch_block_t RCTImageLoaderCancellationBlock; @property (nonatomic, copy) CAKeyframeAnimation *reactKeyframeAnimation; +/** + * Image's memory bytes. It has the dafault calculation of single image of GIF, if you have custom calculation of image decoded bytes, you can assign it using your value. + */ +@property (nonatomic, assign) NSInteger reactDecodedImageBytes; + @end @interface RCTImageLoader : NSObject diff --git a/Libraries/Image/RCTImageLoader.m b/Libraries/Image/RCTImageLoader.m index 6ceb7da4f..bb04437a9 100644 --- a/Libraries/Image/RCTImageLoader.m +++ b/Libraries/Image/RCTImageLoader.m @@ -20,6 +20,17 @@ #import "RCTImageCache.h" #import "RCTImageUtils.h" +static NSInteger RCTImageBytesForImage(UIImage *image) +{ + CAKeyframeAnimation *keyFrameAnimation = [image reactKeyframeAnimation]; + NSInteger singleImageBytes = image.size.width * image.size.height * image.scale * image.scale * 4; + if (keyFrameAnimation) { + return keyFrameAnimation.values.count * singleImageBytes; + } else { + return image.images ? image.images.count * singleImageBytes : singleImageBytes; + } +} + @implementation UIImage (React) - (CAKeyframeAnimation *)reactKeyframeAnimation @@ -32,6 +43,20 @@ objc_setAssociatedObject(self, @selector(reactKeyframeAnimation), reactKeyframeAnimation, OBJC_ASSOCIATION_COPY_NONATOMIC); } +- (NSInteger)reactDecodedImageBytes +{ + NSNumber *imageBytes = objc_getAssociatedObject(self, _cmd); + if (!imageBytes) { + imageBytes = @(RCTImageBytesForImage(self)); + } + return [imageBytes integerValue]; +} + +- (void)setReactDecodedImageBytes:(NSInteger)bytes +{ + objc_setAssociatedObject(self, @selector(reactDecodedImageBytes), @(bytes), OBJC_ASSOCIATION_RETAIN_NONATOMIC); +} + @end @implementation RCTImageLoader