Merge pull request #1985 from dreampiggy/performance_webp_decoding_optimize
Performance enhancement related to single WebP and animated WebP decoding...
This commit is contained in:
commit
250e1fc87f
|
@ -347,6 +347,12 @@ FOUNDATION_STATIC_INLINE NSUInteger SDCacheCostForImage(UIImage *image) {
|
||||||
if (data) {
|
if (data) {
|
||||||
UIImage *image = [UIImage sd_imageWithData:data];
|
UIImage *image = [UIImage sd_imageWithData:data];
|
||||||
image = [self scaledImageForKey:key image:image];
|
image = [self scaledImageForKey:key image:image];
|
||||||
|
#ifdef SD_WEBP
|
||||||
|
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:data];
|
||||||
|
if (imageFormat == SDImageFormatWebP) {
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (self.config.shouldDecompressImages) {
|
if (self.config.shouldDecompressImages) {
|
||||||
image = [UIImage decodedImageWithImage:image];
|
image = [UIImage decodedImageWithImage:image];
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,8 +446,20 @@ didReceiveResponse:(NSURLResponse *)response
|
||||||
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
|
NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:self.request.URL];
|
||||||
image = [self scaledImageForKey:key image:image];
|
image = [self scaledImageForKey:key image:image];
|
||||||
|
|
||||||
// Do not force decoding animated GIFs
|
BOOL shouldDecode = YES;
|
||||||
if (!image.images) {
|
// Do not force decoding animated GIFs and WebPs
|
||||||
|
if (image.images) {
|
||||||
|
shouldDecode = NO;
|
||||||
|
} else {
|
||||||
|
#ifdef SD_WEBP
|
||||||
|
SDImageFormat imageFormat = [NSData sd_imageFormatForImageData:self.imageData];
|
||||||
|
if (imageFormat == SDImageFormatWebP) {
|
||||||
|
shouldDecode = NO;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldDecode) {
|
||||||
if (self.shouldDecompressImages) {
|
if (self.shouldDecompressImages) {
|
||||||
if (self.options & SDWebImageDownloaderScaleDownLargeImages) {
|
if (self.options & SDWebImageDownloaderScaleDownLargeImages) {
|
||||||
#if SD_UIKIT || SD_WATCH
|
#if SD_UIKIT || SD_WATCH
|
||||||
|
|
|
@ -43,14 +43,6 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t flags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS);
|
|
||||||
if (!(flags & ANIMATION_FLAG)) {
|
|
||||||
// for static single webp image
|
|
||||||
UIImage *staticImage = [self sd_rawWebpImageWithData:webpData];
|
|
||||||
WebPDemuxDelete(demuxer);
|
|
||||||
return staticImage;
|
|
||||||
}
|
|
||||||
|
|
||||||
WebPIterator iter;
|
WebPIterator iter;
|
||||||
if (!WebPDemuxGetFrame(demuxer, 1, &iter)) {
|
if (!WebPDemuxGetFrame(demuxer, 1, &iter)) {
|
||||||
WebPDemuxReleaseIterator(&iter);
|
WebPDemuxReleaseIterator(&iter);
|
||||||
|
@ -58,6 +50,8 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t flags = WebPDemuxGetI(demuxer, WEBP_FF_FORMAT_FLAGS);
|
||||||
|
|
||||||
#if SD_UIKIT || SD_WATCH
|
#if SD_UIKIT || SD_WATCH
|
||||||
int loopCount = WebPDemuxGetI(demuxer, WEBP_FF_LOOP_COUNT);
|
int loopCount = WebPDemuxGetI(demuxer, WEBP_FF_LOOP_COUNT);
|
||||||
int frameCount = WebPDemuxGetI(demuxer, WEBP_FF_FRAME_COUNT);
|
int frameCount = WebPDemuxGetI(demuxer, WEBP_FF_FRAME_COUNT);
|
||||||
|
@ -77,6 +71,30 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
||||||
return nil;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!(flags & ANIMATION_FLAG)) {
|
||||||
|
// for static single webp image
|
||||||
|
UIImage *staticImage = [self sd_rawWebpImageWithData:webpData];
|
||||||
|
if (staticImage) {
|
||||||
|
// draw on CGBitmapContext can reduce memory usage
|
||||||
|
CGImageRef imageRef = staticImage.CGImage;
|
||||||
|
size_t width = CGImageGetWidth(imageRef);
|
||||||
|
size_t height = CGImageGetHeight(imageRef);
|
||||||
|
CGContextDrawImage(canvas, CGRectMake(0, 0, width, height), imageRef);
|
||||||
|
CGImageRef newImageRef = CGBitmapContextCreateImage(canvas);
|
||||||
|
#if SD_UIKIT || SD_WATCH
|
||||||
|
staticImage = [[UIImage alloc] initWithCGImage:newImageRef];
|
||||||
|
#else
|
||||||
|
staticImage = [[UIImage alloc] initWithCGImage:newImageRef size:NSZeroSize];
|
||||||
|
#endif
|
||||||
|
CGImageRelease(newImageRef);
|
||||||
|
}
|
||||||
|
WebPDemuxReleaseIterator(&iter);
|
||||||
|
WebPDemuxDelete(demuxer);
|
||||||
|
CGContextRelease(canvas);
|
||||||
|
return staticImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for animated webp image
|
||||||
NSMutableArray<UIImage *> *images = [NSMutableArray array];
|
NSMutableArray<UIImage *> *images = [NSMutableArray array];
|
||||||
#if SD_UIKIT || SD_WATCH
|
#if SD_UIKIT || SD_WATCH
|
||||||
NSTimeInterval totalDuration = 0;
|
NSTimeInterval totalDuration = 0;
|
||||||
|
@ -84,33 +102,36 @@ static void FreeImageData(void *info, const void *data, size_t size) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
do {
|
do {
|
||||||
UIImage *image;
|
@autoreleasepool {
|
||||||
if (iter.blend_method == WEBP_MUX_BLEND) {
|
UIImage *image;
|
||||||
image = [self sd_blendWebpImageWithCanvas:canvas iterator:iter];
|
if (iter.blend_method == WEBP_MUX_BLEND) {
|
||||||
} else {
|
image = [self sd_blendWebpImageWithCanvas:canvas iterator:iter];
|
||||||
image = [self sd_nonblendWebpImageWithCanvas:canvas iterator:iter];
|
} else {
|
||||||
}
|
image = [self sd_nonblendWebpImageWithCanvas:canvas iterator:iter];
|
||||||
|
}
|
||||||
if (!image) {
|
|
||||||
continue;
|
if (!image) {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
[images addObject:image];
|
|
||||||
|
[images addObject:image];
|
||||||
|
|
||||||
#if SD_MAC
|
#if SD_MAC
|
||||||
break;
|
break;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
int duration = iter.duration;
|
int duration = iter.duration;
|
||||||
if (duration <= 10) {
|
if (duration <= 10) {
|
||||||
// WebP standard says 0 duration is used for canvas updating but not showing image, but actually Chrome and other implementations set it to 100ms if duration is lower or equal than 10ms
|
// WebP standard says 0 duration is used for canvas updating but not showing image, but actually Chrome and other implementations set it to 100ms if duration is lower or equal than 10ms
|
||||||
// Some animated WebP images also created without duration, we should keep compatibility
|
// Some animated WebP images also created without duration, we should keep compatibility
|
||||||
duration = 100;
|
duration = 100;
|
||||||
}
|
}
|
||||||
totalDuration += duration;
|
totalDuration += duration;
|
||||||
size_t count = images.count;
|
size_t count = images.count;
|
||||||
durations[count - 1] = duration;
|
durations[count - 1] = duration;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} while (WebPDemuxNextFrame(&iter));
|
} while (WebPDemuxNextFrame(&iter));
|
||||||
|
|
||||||
WebPDemuxReleaseIterator(&iter);
|
WebPDemuxReleaseIterator(&iter);
|
||||||
|
|
Loading…
Reference in New Issue