@@ -86,6 +86,7 @@ @implementation SDWebPCoderFrame
86
86
@implementation SDImageWebPCoder {
87
87
WebPIDecoder *_idec;
88
88
WebPDemuxer *_demux;
89
+ WebPData *_webpdata; // Copied for progressive animation demuxer
89
90
NSData *_imageData;
90
91
CGFloat _scale;
91
92
NSUInteger _loopCount;
@@ -113,6 +114,10 @@ - (void)dealloc {
113
114
WebPDemuxDelete (_demux);
114
115
_demux = NULL ;
115
116
}
117
+ if (_webpdata) {
118
+ WebPDataClear (_webpdata);
119
+ _webpdata = NULL ;
120
+ }
116
121
if (_canvas) {
117
122
CGContextRelease (_canvas);
118
123
_canvas = NULL ;
@@ -290,6 +295,8 @@ - (instancetype)initIncrementalWithOptions:(nullable SDImageCoderOptions *)optio
290
295
preserveAspectRatio = preserveAspectRatioValue.boolValue ;
291
296
}
292
297
_preserveAspectRatio = preserveAspectRatio;
298
+ _currentBlendIndex = NSNotFound ;
299
+ _lock = dispatch_semaphore_create (1 );
293
300
}
294
301
return self;
295
302
}
@@ -300,11 +307,41 @@ - (void)updateIncrementalData:(NSData *)data finished:(BOOL)finished {
300
307
}
301
308
_imageData = data;
302
309
_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];
306
344
}
307
- // libwebp current does not support progressive decoding for animated image, so no need to scan and update the frame information
308
345
}
309
346
310
347
- (UIImage *)incrementalDecodedImageWithOptions : (SDImageCoderOptions *)options {
@@ -832,6 +869,10 @@ - (BOOL)scanAndCheckFramesValidWithDemuxer:(WebPDemuxer *)demuxer {
832
869
833
870
// We should loop all the frames and scan each frames' blendFromIndex for later decoding, this can also ensure all frames is valid
834
871
do {
872
+ if (!iter.complete ) {
873
+ // Skip partial frame
874
+ continue ;
875
+ }
835
876
SDWebPCoderFrame *frame = [[SDWebPCoderFrame alloc ] init ];
836
877
frame.index = iterIndex;
837
878
frame.duration = [self sd_frameDurationWithIterator: iter];
0 commit comments