webp介绍
2016-05-26 本文已影响1585人
ZachChen
图片格式
- 传统格式
- JPEG(有损压缩)
- PNG (无损压缩、透明通道)
- GIF (多帧动画)
- 新兴格式
- APNG (Mozilla)
- WebP (Google)VP8 视频帧内编码
支持有损和无损压缩、支持完整的透明通道、也支持多帧动画,并且没有版权问题
- BPG (Fabrice Bellard)HEVC (即 H.265) 帧内编码
相对于WebP 来说,同等体积下 BPG 能提供更高的图像质量,目前阻碍它流行的原因就是 HEVC 的版权问题和它较长的编码解码时间
移动端图片类型的支持情况
Android 和 iOS 目前的图片编解码架构静态图片的编码与解码库
- JPEG
- libjpeg
- libjpeg-turbo
- MozJPEG
- AppleJPEG
- PNG
- WebP
-
libwebp
WebP 编码主要参数: lossless | quality | method WebP 解码参数:use_threads | bypass_filtering
动态图片的编码与解码
在解码动图时,解码器通常采用所谓"画布模式"进行渲染
- GIF
- APNG
-
libwebp
WebP 动图实际上是把多个单帧 WebP 数据简单打包到一个文件内,而并不是由单帧 WebP 扩展而来
WebP 的优势
WebP 的优势体现在它具有更优的图像数据压缩算法,能带来更小的图片体积,而且拥有肉眼识别无差异的图像质量;同时具备了无损和有损的压缩模式、Alpha 透明以及动画的特性,在 JPEG 和 PNG 上的转化效果都非常优秀、稳定和统一
- 同等质量但是图片更小
+ (UIImage *)sd_imageWithData:(NSData *)data {
if (!data) {
return nil;
}
UIImage *image;
NSString *imageContentType = [NSData sd_contentTypeForImageData:data];
if ([imageContentType isEqualToString:@"image/gif"]) {
image = [UIImage sd_animatedGIFWithData:data];
}
#ifdef SD_WEBP
else if ([imageContentType isEqualToString:@"image/webp"])
{
image = [UIImage sd_imageWithWebPData:data];
}
#endif
else {
image = [[UIImage alloc] initWithData:data];
UIImageOrientation orientation = [self sd_imageOrientationFromImageData:data];
if (orientation != UIImageOrientationUp) {
image = [UIImage imageWithCGImage:image.CGImage
scale:image.scale
orientation:orientation];
}
}
return image;
}
- 在webView中使用webP
- JS 协作
A. 在网页加载出后截取到 HTML 及内部的 JS 后,调用 JS 预先准备好的方法获取需要转码的 webP 格式图片下载地址(其实一个一个的遍历也行).
B. 在App 本地开启线程下载图片,下载完成后,将图片转码由 webP—> png—>Base64
B1. 在App 本地开启线程下载图片,下载完成后,将图片转码由 webP—> png->file 生成自定义URL 例如:yxy://image/xxx.png
C. 将 Base64及原图片下载地址一一对应调用 JS 准备好的方法进行替换
C1. 将 自定义URL及原图片下载地址一一对应调用 JS 准备好的方法进行替换
D. 将下载后的图片进行缓存,并进行管理
- NSURLProtocol
NSURLProtocol是 iOS里面的URL Loading System的一部分
- 可以拦截UIWebView,基于系统的NSUIConnection或者NSUISession进行封装的网络请求。
- 忽略网络请求,直接返回自定义的Response
- 修改request(请求地址,认证信息等等)
- 返回数据拦截
- (void)startLoading
{
// 标示改request已经处理过了,防止无限循环
NSMutableURLRequest *mutableReqeust = [[self request] mutableCopy];
if ([[mutableReqeust.URL.absoluteString lowercaseString] hasPrefix:YXYOpenConnectBaseUrl] ||
[[mutableReqeust.URL.absoluteString lowercaseString] hasPrefix:YXYOpenConnectDevBaseUrl]) {
mutableReqeust = [NSURLProtocolCustom changeRequset:mutableReqeust];
}
[NSURLProtocol setProperty:@YES forKey:YXYURLProtocolHandledKey inRequest:mutableReqeust];
if ([mutableReqeust.URL.scheme caseInsensitiveCompare:@"yxy"] == NSOrderedSame) {
// 处理图片
NSString *tempPath = NSTemporaryDirectory();
NSString *imageTempPath = [NSString stringWithFormat:@"%@%@", tempPath, self.request.URL.host];
NSData *data = [NSData dataWithContentsOfFile:imageTempPath];
NSUInteger length = [data length];
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:[self request].URL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{@"Access-Control-Allow-Origin" : @"*", @"Content-Type" : @"image/png", @"Content-Length" : [NSString stringWithFormat:@"%lu", (unsigned long)length]}];
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
[[self client] URLProtocol:self didLoadData:data];
[[self client] URLProtocolDidFinishLoading:self];
} else {
if ([NSURLProtocolCustom isOssImageUrl:mutableReqeust]) {
NSString *urlString = [mutableReqeust.URL absoluteString];
NSURL *url = [NSURL URLWithString:[urlString stringByAppendingString:@"@1o.webp"]];
@weakify(self);
[[SDWebImageManager sharedManager] downloadImageWithURL:url options:SDWebImageLowPriority|SDWebImageRetryFailed progress:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) {
@strongify(self);
if (!error) {
if (image) {
NSData *jpgData = UIImageJPEGRepresentation(image, 1.0f);
NSUInteger length = [jpgData length];
NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:mutableReqeust.URL statusCode:200 HTTPVersion:@"HTTP/1.1" headerFields:@{@"Content-Type" : @"image/jpg", @"Content-Length" : [NSString stringWithFormat:@"%lu", (unsigned long)length]}];
[[self client] URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
[[self client] URLProtocol:self didLoadData:jpgData];
[[self client] URLProtocolDidFinishLoading:self];
}
} else {
[self.client URLProtocol:self didFailWithError:error];
}
}];
} else {
// 处理第三方统一接入
self.connection = [NSURLConnection connectionWithRequest:mutableReqeust delegate:self];
}
}
}