Merge pull request #30 from SDWebImage/fix_static_webp_cgcontext_RAM

Fix the issue when WebP is static webp, the `SDAnimatedImageCoder` protocol implementation still create CGContext, this can reduce RAM usage
This commit is contained in:
DreamPiggy 2020-01-07 16:20:00 +08:00 committed by GitHub
commit 3e2d252aa9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 58 additions and 7 deletions

View File

@ -711,6 +711,18 @@ static void FreeImageData(void *info, const void *data, size_t size) {
uint32_t loopCount = WebPDemuxGetI(demuxer, WEBP_FF_LOOP_COUNT);
NSMutableArray<SDWebPCoderFrame *> *frames = [NSMutableArray array];
_hasAnimation = hasAnimation;
_hasAlpha = hasAlpha;
_canvasWidth = canvasWidth;
_canvasHeight = canvasHeight;
_frameCount = frameCount;
_loopCount = loopCount;
// If static WebP, does not need to parse the frame blend index
if (frameCount <= 1) {
return YES;
}
// We should loop all the frames and scan each frames' blendFromIndex for later decoding, this can also ensure all frames is valid
do {
SDWebPCoderFrame *frame = [[SDWebPCoderFrame alloc] init];
@ -748,12 +760,6 @@ static void FreeImageData(void *info, const void *data, size_t size) {
return NO;
}
_frames = [frames copy];
_hasAnimation = hasAnimation;
_hasAlpha = hasAlpha;
_canvasWidth = canvasWidth;
_canvasHeight = canvasHeight;
_frameCount = frameCount;
_loopCount = loopCount;
return YES;
}
@ -774,6 +780,9 @@ static void FreeImageData(void *info, const void *data, size_t size) {
if (index >= _frameCount) {
return 0;
}
if (_frameCount <= 1) {
return 0;
}
return _frames[index].duration;
}
@ -783,11 +792,40 @@ static void FreeImageData(void *info, const void *data, size_t size) {
return nil;
}
SD_LOCK(_lock);
image = [self safeAnimatedImageFrameAtIndex:index];
if (_frameCount <= 1) {
image = [self safeStaticImageFrame];
} else {
image = [self safeAnimatedImageFrameAtIndex:index];
}
SD_UNLOCK(_lock);
return image;
}
- (UIImage *)safeStaticImageFrame {
UIImage *image;
if (!_colorSpace) {
_colorSpace = [self sd_colorSpaceWithDemuxer:_demux];
}
// Static WebP image
WebPIterator iter;
if (!WebPDemuxGetFrame(_demux, 1, &iter)) {
WebPDemuxReleaseIterator(&iter);
return nil;
}
CGImageRef imageRef = [self sd_createWebpImageWithData:iter.fragment colorSpace:_colorSpace];
if (!imageRef) {
return nil;
}
#if SD_UIKIT || SD_WATCH
image = [[UIImage alloc] initWithCGImage:imageRef scale:_scale orientation:UIImageOrientationUp];
#else
image = [[UIImage alloc] initWithCGImage:imageRef scale:_scale orientation:kCGImagePropertyOrientationUp];
#endif
CGImageRelease(imageRef);
WebPDemuxReleaseIterator(&iter);
return image;
}
- (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
if (!_canvas) {
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;

View File

@ -10,6 +10,7 @@
@import XCTest;
#import <SDWebImage/SDWebImage.h>
#import <SDWebImageWebPCoder/SDWebImageWebPCoder.h>
#import <objc/runtime.h>
const int64_t kAsyncTestTimeout = 5;
@ -172,6 +173,18 @@ const int64_t kAsyncTestTimeout = 5;
}
}
- (void)test34StaticImageNotCreateCGContext {
NSURL *staticWebPURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"TestImageStatic" withExtension:@"webp"];
NSData *data = [NSData dataWithContentsOfURL:staticWebPURL];
SDImageWebPCoder *coder = [[SDImageWebPCoder alloc] initWithAnimatedImageData:data options:nil];
XCTAssertTrue(coder.animatedImageFrameCount == 1);
UIImage *image = [coder animatedImageFrameAtIndex:0];
XCTAssertNotNil(image);
Ivar ivar = class_getInstanceVariable(coder.class, "_canvas");
CGContextRef canvas = ((CGContextRef (*)(id, Ivar))object_getIvar)(coder, ivar);
XCTAssert(canvas == NULL);
}
@end
@implementation SDWebImageWebPCoderTests (Helpers)