SDWebImage 加載顯示 WebP 與性能問題


SDWebImage 加載顯示 WebP 與性能問題

本文包含自定義下載操作 SDWebImageDownloaderOperation 與編碼器 SDWebImageCoder。SDWebImage 的版本為 4.2.3。

靜態圖片

對於靜態圖片來說,WebP 比 PNG 體積小,可以省流量,但是解碼時間長。如果不需要 WebP 的原圖數據,可以把 WebP 靜態圖片保存為 PNG 或 JPEG,加快解碼速度。這一步可以通過自定義下載操作 SDWebImageDownloaderOperation 實現。

SDWebImageDownloaderOperation 的 URLSession:task:didCompleteWithError: 方法會把下載好的原圖數據 imageData 通過 callCompletionBlocksWithImage:imageData:error:finished: 方法傳給上層的回調 SDWebImageDownloaderCompletedBlock。

可以自定義 SDWebImageDownloaderOperation,修改 URLSession:task:didCompleteWithError: 方法,在上圖箭頭所指處修改 imageData,把靜態 WebP 圖片數據轉為 PNG 或 JPEG 圖片數據。修改上述方法只需要添加一行代碼

imageData = [[SDWebImageCodersManager sharedInstance] encodedDataWithImage:image format:SDImageFormatUndefined];

原圖數據有 Alpha 信息就轉為 PNG,否則轉為 JPEG。

自定義的類是 ImageDownloaderOperation,使用這個類需要一行代碼

[[SDWebImageManager sharedManager].imageDownloader setOperationClass:[ImageDownloaderOperation class]];

動態圖片

WebP 格式支持動態圖片。SDWebImageWebPCoder 的 decodedImageWithData: 負責解碼,返回 UIImage。如果是動態圖片,每一幀圖片都會解碼,用所有圖片幀和總動畫時長通過 animatedImageWithImages:duration: 方法生成 UIImage。這樣做的好處是,節省 CPU 資源,不用重復解碼。對小圖片來說,比較合適。如果圖片太大,就會占內存多。另外,如果原圖的每一幀動畫時長不相等,那么實際播放的動畫就與原圖動畫不符。可以用 YYImage 和 YYAnimatedImageView 來顯示動態 WebP。這樣可以用 CPU 資源換取內存空間(YYImage 也可以預先解碼所有圖片幀),也可以根據原圖的每一幀動畫時長來播放動畫。直接使用 YYWebImage 框架是最方便的方法。然而,如果項目中需要統一圖片的下載、緩存管理等操作,最好只用一套圖片下載庫。這里介紹用 SDWebImage 下載、緩存,用 YYImage 顯示 WebP 的方法。

YYImage 會對 WebP 進行解碼,因此不需要 SDWebImageWebPCoder 解碼所有圖片幀。自定義編碼器 SDWebImageCoder,只對第一幀圖片進行解碼,減少解碼時間。修改 decodedImageWithData: 方法,在解碼每一幀圖片的 while 循環中 (下圖箭頭所指處) 添加 break 即可,解碼成功一幀圖片就退出循環。

自定義編碼器的類是 FirstFrameWebPCoder,使用這個編碼器

[SDWebImageCodersManager sharedInstance].coders = @[[SDWebImageImageIOCoder sharedCoder],
                                                    [FirstFrameWebPCoder sharedCoder]];

加載顯示圖片 (cell.imageView 是 YYAnimatedImageView)

cell.imageView.image = placeholder;
[[SDWebImageManager sharedManager] loadImageWithURL:url options:0 progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
	if ([image isKindOfClass:[YYImage class]]) {
		cell.imageView.image = image;
	} else if (data) {
		YYImage *yyimage = [YYImage imageWithData:data];
		cell.imageView.image = yyimage;
		NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:url];
		[[SDWebImageManager sharedManager].imageCache storeImage:yyimage forKey:key toDisk:NO completion:nil];
	}
}];

代碼已上傳 GitHub:https://github.com/Silence-GitHub/WebPDemo

轉載請注明出處:http://www.cnblogs.com/silence-cnblogs/p/8319917.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM