Skip to content

Commit e4af4b8

Browse files
authored
Merge pull request #33 from SDWebImage/feature_progressive_animated_webp
Feature - Supports Progressive Animated WebP (Important)
2 parents 9f66a66 + b6f4692 commit e4af4b8

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-5
lines changed

Example/SDWebImageWebPCoderExample/ViewController.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ - (void)viewDidLoad {
2222
[super viewDidLoad];
2323
// Do any additional setup after loading the view, typically from a nib.
2424

25+
[SDImageCache.sharedImageCache clearDiskOnCompletion:nil];
26+
2527
[[SDImageCodersManager sharedManager] addCoder:[SDImageWebPCoder sharedCoder]];
2628

2729
self.imageView1 = [UIImageView new];
@@ -46,7 +48,7 @@ - (void)viewDidLoad {
4648
}
4749
});
4850
}];
49-
[self.imageView2 sd_setImageWithURL:animatedWebPURL completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
51+
[self.imageView2 sd_setImageWithURL:animatedWebPURL placeholderImage:nil options:SDWebImageProgressiveLoad completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
5052
if (image) {
5153
NSLog(@"%@", @"Animated WebP load success");
5254
}

SDWebImageWebPCoder/Classes/SDImageWebPCoder.m

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ @implementation SDWebPCoderFrame
8686
@implementation SDImageWebPCoder {
8787
WebPIDecoder *_idec;
8888
WebPDemuxer *_demux;
89+
WebPData *_webpdata; // Copied for progressive animation demuxer
8990
NSData *_imageData;
9091
CGFloat _scale;
9192
NSUInteger _loopCount;
@@ -113,6 +114,10 @@ - (void)dealloc {
113114
WebPDemuxDelete(_demux);
114115
_demux = NULL;
115116
}
117+
if (_webpdata) {
118+
WebPDataClear(_webpdata);
119+
_webpdata = NULL;
120+
}
116121
if (_canvas) {
117122
CGContextRelease(_canvas);
118123
_canvas = NULL;
@@ -290,6 +295,8 @@ - (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)optio
290295
preserveAspectRatio = preserveAspectRatioValue.boolValue;
291296
}
292297
_preserveAspectRatio = preserveAspectRatio;
298+
_currentBlendIndex = NSNotFound;
299+
_lock = dispatch_semaphore_create(1);
293300
}
294301
return self;
295302
}
@@ -300,16 +307,54 @@ - (void)updateIncrementalData:(NSData *)data finished:(BOOL)finished {
300307
}
301308
_imageData = data;
302309
_finished = finished;
303-
VP8StatusCode status = WebPIUpdate(_idec, data.bytes, data.length);
304-
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) {
305-
return;
310+
if (!_demux) {
311+
VP8StatusCode status = WebPIUpdate(_idec, data.bytes, data.length);
312+
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
313+
return;
314+
}
315+
// This case may be Animated WebP progressive decode
316+
if (status == VP8_STATUS_UNSUPPORTED_FEATURE) {
317+
WebPDemuxState state;
318+
WebPData tmpData;
319+
WebPDataInit(&tmpData);
320+
tmpData.bytes = data.bytes;
321+
tmpData.size = data.length;
322+
// Copy to avoid the NSData dealloc and VP8 internal retain the pointer
323+
_webpdata = malloc(sizeof(WebPData));
324+
WebPDataCopy(&tmpData, _webpdata);
325+
_demux = WebPDemuxPartial(_webpdata, &state);
326+
}
327+
} else {
328+
// libwebp current have no API to update demuxer, so we always delete and recreate demuxer
329+
WebPDemuxDelete(_demux);
330+
_demux = NULL;
331+
WebPDemuxState state;
332+
WebPData tmpData;
333+
WebPDataInit(&tmpData);
334+
tmpData.bytes = data.bytes;
335+
tmpData.size = data.length;
336+
// Copy to avoid the NSData dealloc and VP8 internal retain the pointer
337+
WebPDataClear(_webpdata);
338+
WebPDataCopy(&tmpData, _webpdata);
339+
_demux = WebPDemuxPartial(_webpdata, &state);
340+
}
341+
342+
if (_demux) {
343+
[self scanAndCheckFramesValidWithDemuxer:_demux];
306344
}
307-
// libwebp current does not support progressive decoding for animated image, so no need to scan and update the frame information
308345
}
309346

310347
- (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
311348
UIImage *image;
312349

350+
// For Animated WebP Images, progressive decoding only return the first frame.
351+
// If you want progressive animation, use the SDAniamtedCoder protocol method instead.
352+
if (_demux) {
353+
SD_LOCK(_lock);
354+
image = [self safeStaticImageFrame];
355+
SD_UNLOCK(_lock);
356+
}
357+
// For Static WebP images
313358
int width = 0;
314359
int height = 0;
315360
int last_y = 0;
@@ -832,6 +877,10 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
832877

833878
// We should loop all the frames and scan each frames' blendFromIndex for later decoding, this can also ensure all frames is valid
834879
do {
880+
if (!iter.complete) {
881+
// Skip partial frame
882+
continue;
883+
}
835884
SDWebPCoderFrame *frame = [[SDWebPCoderFrame alloc] init];
836885
frame.index = iterIndex;
837886
frame.duration = [self sd_frameDurationWithIterator:iter];

0 commit comments

Comments
 (0)