@@ -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,11 +307,41 @@ - (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 {
@@ -832,6 +869,10 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
832869
833870 // We should loop all the frames and scan each frames' blendFromIndex for later decoding, this can also ensure all frames is valid
834871 do {
872+ if (!iter.complete ) {
873+ // Skip partial frame
874+ continue ;
875+ }
835876 SDWebPCoderFrame *frame = [[SDWebPCoderFrame alloc ] init ];
836877 frame.index = iterIndex;
837878 frame.duration = [self sd_frameDurationWithIterator: iter];
0 commit comments