Skip to content

Commit 3e2d252

Browse files
authored
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
2 parents 9319f87 + 7cd404c commit 3e2d252

File tree

2 files changed

+58
-7
lines changed

2 files changed

+58
-7
lines changed

SDWebImageWebPCoder/Classes/SDImageWebPCoder.m

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -711,6 +711,18 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
711711
uint32_t loopCount = WebPDemuxGetI(demuxer, WEBP_FF_LOOP_COUNT);
712712
NSMutableArray<SDWebPCoderFrame *> *frames = [NSMutableArray array];
713713

714+
_hasAnimation = hasAnimation;
715+
_hasAlpha = hasAlpha;
716+
_canvasWidth = canvasWidth;
717+
_canvasHeight = canvasHeight;
718+
_frameCount = frameCount;
719+
_loopCount = loopCount;
720+
721+
// If static WebP, does not need to parse the frame blend index
722+
if (frameCount <= 1) {
723+
return YES;
724+
}
725+
714726
// We should loop all the frames and scan each frames' blendFromIndex for later decoding, this can also ensure all frames is valid
715727
do {
716728
SDWebPCoderFrame *frame = [[SDWebPCoderFrame alloc] init];
@@ -748,12 +760,6 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
748760
return NO;
749761
}
750762
_frames = [frames copy];
751-
_hasAnimation = hasAnimation;
752-
_hasAlpha = hasAlpha;
753-
_canvasWidth = canvasWidth;
754-
_canvasHeight = canvasHeight;
755-
_frameCount = frameCount;
756-
_loopCount = loopCount;
757763

758764
return YES;
759765
}
@@ -774,6 +780,9 @@ - (NSTimeInterval)animatedImageDurationAtIndex:(NSUInteger)index {
774780
if (index >= _frameCount) {
775781
return 0;
776782
}
783+
if (_frameCount <= 1) {
784+
return 0;
785+
}
777786
return _frames[index].duration;
778787
}
779788

@@ -783,11 +792,40 @@ - (UIImage *)animatedImageFrameAtIndex:(NSUInteger)index {
783792
return nil;
784793
}
785794
SD_LOCK(_lock);
786-
image = [self safeAnimatedImageFrameAtIndex:index];
795+
if (_frameCount <= 1) {
796+
image = [self safeStaticImageFrame];
797+
} else {
798+
image = [self safeAnimatedImageFrameAtIndex:index];
799+
}
787800
SD_UNLOCK(_lock);
788801
return image;
789802
}
790803

804+
- (UIImage *)safeStaticImageFrame {
805+
UIImage *image;
806+
if (!_colorSpace) {
807+
_colorSpace = [self sd_colorSpaceWithDemuxer:_demux];
808+
}
809+
// Static WebP image
810+
WebPIterator iter;
811+
if (!WebPDemuxGetFrame(_demux, 1, &iter)) {
812+
WebPDemuxReleaseIterator(&iter);
813+
return nil;
814+
}
815+
CGImageRef imageRef = [self sd_createWebpImageWithData:iter.fragment colorSpace:_colorSpace];
816+
if (!imageRef) {
817+
return nil;
818+
}
819+
#if SD_UIKIT || SD_WATCH
820+
image = [[UIImage alloc] initWithCGImage:imageRef scale:_scale orientation:UIImageOrientationUp];
821+
#else
822+
image = [[UIImage alloc] initWithCGImage:imageRef scale:_scale orientation:kCGImagePropertyOrientationUp];
823+
#endif
824+
CGImageRelease(imageRef);
825+
WebPDemuxReleaseIterator(&iter);
826+
return image;
827+
}
828+
791829
- (UIImage *)safeAnimatedImageFrameAtIndex:(NSUInteger)index {
792830
if (!_canvas) {
793831
CGBitmapInfo bitmapInfo = kCGBitmapByteOrder32Host;

SDWebImageWebPCoderTests/SDWebImageWebPCoderTests.m

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
@import XCTest;
1111
#import <SDWebImage/SDWebImage.h>
1212
#import <SDWebImageWebPCoder/SDWebImageWebPCoder.h>
13+
#import <objc/runtime.h>
1314

1415
const int64_t kAsyncTestTimeout = 5;
1516

@@ -172,6 +173,18 @@ - (void)test33AnimatedImageBlendMethod {
172173
}
173174
}
174175

176+
- (void)test34StaticImageNotCreateCGContext {
177+
NSURL *staticWebPURL = [[NSBundle bundleForClass:[self class]] URLForResource:@"TestImageStatic" withExtension:@"webp"];
178+
NSData *data = [NSData dataWithContentsOfURL:staticWebPURL];
179+
SDImageWebPCoder *coder = [[SDImageWebPCoder alloc] initWithAnimatedImageData:data options:nil];
180+
XCTAssertTrue(coder.animatedImageFrameCount == 1);
181+
UIImage *image = [coder animatedImageFrameAtIndex:0];
182+
XCTAssertNotNil(image);
183+
Ivar ivar = class_getInstanceVariable(coder.class, "_canvas");
184+
CGContextRef canvas = ((CGContextRef (*)(id, Ivar))object_getIvar)(coder, ivar);
185+
XCTAssert(canvas == NULL);
186+
}
187+
175188
@end
176189

177190
@implementation SDWebImageWebPCoderTests (Helpers)

0 commit comments

Comments
 (0)