Merge pull request #33 from SDWebImage/feature_progressive_animated_webp
Feature - Supports Progressive Animated WebP (Important)
This commit is contained in:
commit
e4af4b805e
|
@ -22,6 +22,8 @@
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
// Do any additional setup after loading the view, typically from a nib.
|
// Do any additional setup after loading the view, typically from a nib.
|
||||||
|
|
||||||
|
[SDImageCache.sharedImageCache clearDiskOnCompletion:nil];
|
||||||
|
|
||||||
[[SDImageCodersManager sharedManager] addCoder:[SDImageWebPCoder sharedCoder]];
|
[[SDImageCodersManager sharedManager] addCoder:[SDImageWebPCoder sharedCoder]];
|
||||||
|
|
||||||
self.imageView1 = [UIImageView new];
|
self.imageView1 = [UIImageView new];
|
||||||
|
@ -46,7 +48,7 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
[self.imageView2 sd_setImageWithURL:animatedWebPURL completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
[self.imageView2 sd_setImageWithURL:animatedWebPURL placeholderImage:nil options:SDWebImageProgressiveLoad completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
|
||||||
if (image) {
|
if (image) {
|
||||||
NSLog(@"%@", @"Animated WebP load success");
|
NSLog(@"%@", @"Animated WebP load success");
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,7 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
@implementation SDImageWebPCoder {
|
@implementation SDImageWebPCoder {
|
||||||
WebPIDecoder *_idec;
|
WebPIDecoder *_idec;
|
||||||
WebPDemuxer *_demux;
|
WebPDemuxer *_demux;
|
||||||
|
WebPData *_webpdata; // Copied for progressive animation demuxer
|
||||||
NSData *_imageData;
|
NSData *_imageData;
|
||||||
CGFloat _scale;
|
CGFloat _scale;
|
||||||
NSUInteger _loopCount;
|
NSUInteger _loopCount;
|
||||||
|
@ -113,6 +114,10 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
WebPDemuxDelete(_demux);
|
WebPDemuxDelete(_demux);
|
||||||
_demux = NULL;
|
_demux = NULL;
|
||||||
}
|
}
|
||||||
|
if (_webpdata) {
|
||||||
|
WebPDataClear(_webpdata);
|
||||||
|
_webpdata = NULL;
|
||||||
|
}
|
||||||
if (_canvas) {
|
if (_canvas) {
|
||||||
CGContextRelease(_canvas);
|
CGContextRelease(_canvas);
|
||||||
_canvas = NULL;
|
_canvas = NULL;
|
||||||
|
@ -290,6 +295,8 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
preserveAspectRatio = preserveAspectRatioValue.boolValue;
|
preserveAspectRatio = preserveAspectRatioValue.boolValue;
|
||||||
}
|
}
|
||||||
_preserveAspectRatio = preserveAspectRatio;
|
_preserveAspectRatio = preserveAspectRatio;
|
||||||
|
_currentBlendIndex = NSNotFound;
|
||||||
|
_lock = dispatch_semaphore_create(1);
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -300,16 +307,54 @@ static CGSize SDCalculateThumbnailSize(CGSize fullSize, BOOL preserveAspectRatio
|
||||||
}
|
}
|
||||||
_imageData = data;
|
_imageData = data;
|
||||||
_finished = finished;
|
_finished = finished;
|
||||||
VP8StatusCode status = WebPIUpdate(_idec, data.bytes, data.length);
|
if (!_demux) {
|
||||||
if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED) {
|
VP8StatusCode status = WebPIUpdate(_idec, data.bytes, data.length);
|
||||||
return;
|
if (status == VP8_STATUS_OK || status == VP8_STATUS_SUSPENDED) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// This case may be Animated WebP progressive decode
|
||||||
|
if (status == VP8_STATUS_UNSUPPORTED_FEATURE) {
|
||||||
|
WebPDemuxState state;
|
||||||
|
WebPData tmpData;
|
||||||
|
WebPDataInit(&tmpData);
|
||||||
|
tmpData.bytes = data.bytes;
|
||||||
|
tmpData.size = data.length;
|
||||||
|
// Copy to avoid the NSData dealloc and VP8 internal retain the pointer
|
||||||
|
_webpdata = malloc(sizeof(WebPData));
|
||||||
|
WebPDataCopy(&tmpData, _webpdata);
|
||||||
|
_demux = WebPDemuxPartial(_webpdata, &state);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// libwebp current have no API to update demuxer, so we always delete and recreate demuxer
|
||||||
|
WebPDemuxDelete(_demux);
|
||||||
|
_demux = NULL;
|
||||||
|
WebPDemuxState state;
|
||||||
|
WebPData tmpData;
|
||||||
|
WebPDataInit(&tmpData);
|
||||||
|
tmpData.bytes = data.bytes;
|
||||||
|
tmpData.size = data.length;
|
||||||
|
// Copy to avoid the NSData dealloc and VP8 internal retain the pointer
|
||||||
|
WebPDataClear(_webpdata);
|
||||||
|
WebPDataCopy(&tmpData, _webpdata);
|
||||||
|
_demux = WebPDemuxPartial(_webpdata, &state);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_demux) {
|
||||||
|
[self scanAndCheckFramesValidWithDemuxer:_demux];
|
||||||
}
|
}
|
||||||
// libwebp current does not support progressive decoding for animated image, so no need to scan and update the frame information
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
|
- (UIImage *)incrementalDecodedImageWithOptions:(SDImageCoderOptions *)options {
|
||||||
UIImage *image;
|
UIImage *image;
|
||||||
|
|
||||||
|
// For Animated WebP Images, progressive decoding only return the first frame.
|
||||||
|
// If you want progressive animation, use the SDAniamtedCoder protocol method instead.
|
||||||
|
if (_demux) {
|
||||||
|
SD_LOCK(_lock);
|
||||||
|
image = [self safeStaticImageFrame];
|
||||||
|
SD_UNLOCK(_lock);
|
||||||
|
}
|
||||||
|
// For Static WebP images
|
||||||
int width = 0;
|
int width = 0;
|
||||||
int height = 0;
|
int height = 0;
|
||||||
int last_y = 0;
|
int last_y = 0;
|
||||||
|
@ -832,6 +877,10 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
||||||
|
|
||||||
// We should loop all the frames and scan each frames' blendFromIndex for later decoding, this can also ensure all frames is valid
|
// We should loop all the frames and scan each frames' blendFromIndex for later decoding, this can also ensure all frames is valid
|
||||||
do {
|
do {
|
||||||
|
if (!iter.complete) {
|
||||||
|
// Skip partial frame
|
||||||
|
continue;
|
||||||
|
}
|
||||||
SDWebPCoderFrame *frame = [[SDWebPCoderFrame alloc] init];
|
SDWebPCoderFrame *frame = [[SDWebPCoderFrame alloc] init];
|
||||||
frame.index = iterIndex;
|
frame.index = iterIndex;
|
||||||
frame.duration = [self sd_frameDurationWithIterator:iter];
|
frame.duration = [self sd_frameDurationWithIterator:iter];
|
||||||
|
|
Loading…
Reference in New Issue