webp格式图片

webp格式图片是google推出的,相比jpg png有着巨大的优势,同样质量的图片webp格式的图片占用空间更小,在像电商这样图片比较多的App中,使用webp格式图片会很有优势。

引言

很早之前,我们的项目中就已经采用了webp格式,但是由于webView本身并不能解析webp格式,所以我们基于webView的文章详情页就无法使用到这项优化。

那么有没有什么办法能实现呢?当然是有的。

在开始技术讲解之前需要先说明,本文的技术方案,是基于本项目的情况:文章的正文大部分通过接口直接获取到,通过在客户端本地进行html正文组装,最后通过webView的loadHTMLString方法进行加载显示。普通的图片可以通过转换链接得到webp服务器获取到相应的webp版的图片。

本项目中,图片缓存使用了SDWebImage,并且开启了webp支持功能,那么我们对详情页webView的处理也会基于此来实现。

通过思考,方案其实还是比较明确的,就是替换html中图片链接,通过客户端下载webp图片,然后在通过js刷新出页面上的下完的图片,但实际开发中也遇到了一些坑,比如:

HTML解析库的setAttributeNamed不能增加属性

webp服务器图片下载后的默认缓存时gif不能正常存储

下载完的图片不能实时通过js更改src为本地文件地址加载出来

最终的技术实现:

1.对下载回来的html内容进行处理,获取所有图片链接,并进行webp链接处理转换

对html内容的解析处理我使用的是Objective-C-HMTL-Parser,但是该库已经多年不维护,这里有我fork后进行部分优化调整的版本:https://github.com/YueRuo/Objective-C-HMTL-Parser (本地下载)

处理html图片核心处理逻辑代码:

@try {

HTMLParser *parser = [[HTMLParser alloc] initWithString:htmlContent error:&error];

HTMLNode *bodyNode = [parser body];

if (error) {

return;

}

//得到所有的img标签

NSArray *inputNodes = [bodyNode findChildTags:@"img"];

for (HTMLNode *inputNode in inputNodes) {

NSString *imageSrc = [inputNode getAttributeNamed:@"src"];

if (!imageSrc) {

continue;

}

NSString *newSrc = [[GlobalVariable shareInstance] resizeWebpImageWithUrl:imageSrc size:CGSizeMake((SCREEN_WIDTH - 20) * 2, 0)];//根据原图片,得到webp服务器使用的图片链接,需要有webp处理服务器

//检查本地图片缓存

NSString *key = [[SDWebImageManager sharedManager] cacheKeyForURL:[NSURL URLWithString:newSrc]];

NSString *localPath = [[SDImageCache sharedImageCache] defaultCachePathForKey:key];

NSString *webpImage = newSrc;

BOOL localExsit = [[NSFileManager defaultManager] fileExistsAtPath:localPath];

if (localExsit) {

newSrc = [NSString stringWithFormat:@"file://%@", localPath];

}

//存储疑似webp图片和原图片,如果newSrc和webp相同则说明本地没有缓存图片

[_webpImageUrlDic setObject:webpImage forKey:newSrc];

if(localExsit){

setAttributeNamed(inputNode->_node, "src", [newSrc cStringUsingEncoding:NSUTF8StringEncoding]);

}else{

setAttributeNamed(inputNode->_node, "src", "详情页占位图@2x.png");

}

//给img标签中增加一个叫osrc的属性,便于后续处理

setAttributeNamed(inputNode->_node, "osrc", [newSrc cStringUsingEncoding:NSUTF8StringEncoding]);

}

htmlContent = [NSMutableString stringWithString:parser.doc.rawContents];

}

@catch (NSException *exception) {

}

@finally {

[webView loadHTMLString:htmlContent baseURL:baseUrl];

}

2.用原生方法下载webp图片,缓存到本地

下载之后会存储为jpg或png格式,这样就可以被webView进行本地加载,但是需要注意gif的存储特殊处理。

另外通过实验,直接通过js无法实时更新下载到本地的图片,只好通过图片的base64encode数据加载方式实现。

具体代码如下:

- (void)webViewDidFinishLoad:(UIWebView *)web {

//处理webp格式加载

[_webpImageUrlDic enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {

if([obj isEqualToString:key]){//说明这图没有缓存,还需要下载

[[SDWebImageDownloader sharedDownloader] downloadImageWithURL:[NSURL URLWithString:obj] options:0 progress:nil completed:^(UIImage *image, NSData *data, NSError *error, BOOL finished) {

if (image&&finished) {

NSString *js;

NSRange range = [[obj lowercaseString] rangeOfString:@".gif"];//检查是否是gif

BOOL isGif = (range.location != NSNotFound);

if (!isGif) {

[[SDImageCache sharedImageCache] storeImage:image forKey:obj];

NSString *base64 = [UIImageJPEGRepresentation(image,1) base64EncodedStringWithOptions:0];

js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/jpeg;base64,%@')",key,base64];

}else{//gif的图片如果直接存储,会变成jpg从而失去动画,因此要特殊处理

[[SDImageCache sharedImageCache] storeImage:image recalculateFromImage:false imageData:data forKey:key toDisk:true];

NSString *base64 = [data base64EncodedStringWithOptions:0];

js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/gif;base64,%@')",key,base64];

}

[NSThread excuteInMainThread:^{

[webView stringByEvaluatingJavaScriptFromString:js];

} async:false];

}

}];

} else {//缓存中存在,那么直接加载吧

NSString *js;

NSRange range = [[obj lowercaseString] rangeOfString:@".gif"];//检查是否是gif

NSData* data = [NSData dataWithContentsOfFile:[key stringByReplacingOccurrencesOfString:@"file://" withString:@""]];

NSString *base64 = [data base64EncodedStringWithOptions:0];

BOOL isGif = (range.location != NSNotFound);

if (!isGif) {

js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/jpeg;base64,%@')",obj,base64];

}else{

js = [NSString stringWithFormat:@"replaceWebPImg('%@','data:image/gif;base64,%@')",obj,base64];

}

[NSThread excuteInMainThread:^{

[webView stringByEvaluatingJavaScriptFromString:js];

} async:false];

}

}];

}

3.回调webView页面,用本地链接替换原有的图片

加载已下载好的图片,这里主要通过js来实现,即第2步中的replaceWebPImg方法,该js方法可通过提前置于html的模板中,或者webViewDidFinishLoad后采用js注入进去

replaceWebPImg = function(src, localPath) {

var imgs = document.querySelectorAll('img[osrc="'+src+'"]'),len = imgs.length;;

for (var i = 0; i < len; i++) {

var img = imgs[i];

img.src = localPath;

}

}

好再次总结一下整个流程:

对服务器返回的htmlContent数据进行相应处理,检查图片是否存在缓存,存在则使用本地地址为src,不存在则把图片的src替换成占位图。记录下图片地址,并增加属性做好标记。

图片的地址进行webp转换,通过客户端进行下载

下载后的图片,通过js方法进行src更改,并且赋值的base64的图片编码数据,因为给本地地址无法实时展示出来

这篇写的比较简单,更详细的步骤请查阅上面的代码,里面我加上还算详细的注释,希望对想要在webView中使用webp图片的大家有所帮助。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对编程圈的支持。

android webview webp,iOS WebView中使用webp格式图片的方法相关推荐

  1. Android解析xml的方法,Android中解析XML格式数据的方法

    XML介绍:Extensible Markup Language,即可扩展标记语言 一.概述 Android中解析XML格式数据大致有三种方法: SAX DOM PULL 二.详解 2.1 SAX S ...

  2. Android应用开发中三种常见的图片压缩方法

    Android应用开发中三种常见的图片压缩方法,分别是:质量压缩法.比例压缩法(根据路径获取图片并压缩)和比例压缩法(根据Bitmap图片压缩). 一.质量压缩法private Bitmap comp ...

  3. java读取pdf_Java 读取PDF中的文本和图片的方法

    本文将介绍通过Java程序来读取PDF文档中的文本和图片的方法.分别调用方法extractText()和extractImages()来读取. 使用工具:Free Spire.PDF for Java ...

  4. Python 获得pdf中的文字、图片文字方法

    Python 获得pdf中的文字.图片文字方法 下载word版文件 OCR,全称Optical character recognition,中文译名叫做光学文字识别.它把图像中的字符,转换为机器编码的 ...

  5. Android Studio中关于9-patch格式图片的编译错误

    最近在编译Android Studio开发的项目中在使用了9宫图后出现了编译错误,尝试了多种方法未能解决,最后仔细查看出错的日志发现,居然是图片的原因,图片中包含有alpah通道所以在执行app:me ...

  6. ios加载本地html懒加载图片方案,IOS开发中加载大量网络图片优化方法

    IOS开发中加载大量网络图片如何优化 1.概述 在IOS下通过URL读一张网络图片并不像其他编程语言那样可以直接把图片路径放到图片路径的位置就ok,而是需要我们通过一段类似流的方式去加载网络图片,接着 ...

  7. android 手势放缩_Android应用中实现手势控制图片缩放的完全攻略

    一.概述现在app中,图片预览功能肯定是少不了的,用户基本已经形成条件反射,看到小图,点击看大图,看到大图两个手指开始进行放大,放大后,开始移动到指定部位~~~ 我相信看图的整个步骤,大家或者说用户应 ...

  8. Photoshop如何打开、编辑和导出Webp格式图片的方法

    一.前文 Photoshop默认不支持WebP格式的图片.需要额外安装插件. 二.下载插件 插件源码是开源的:WebP file format plug-in for Photoshop 不管源码,只 ...

  9. Android与HEIF格式图片适配方法

    本文字数:1490字 预计阅读时间:8分钟 一. 什么是HEIF图片 HEIF (High Efficiency Image File Format)是由动态图像专家组(MPEG)在2013年推出的新 ...

最新文章

  1. PHP框架性能不权威对比
  2. 综合布线系统设计遵循的标准和条件
  3. 软件开发项目云端All
  4. numpy.random.rand使用详解
  5. 设计模式之Builder
  6. 前端学习(3348):数组方法的运用和数值
  7. python安装不了是什么问题_安装不上python的模块怎么办?别怕,我这有妙招!
  8. Ural_1003 Parity(并查集)
  9. 怎么测试服务器端口是否对外开放_12个经典性能测试人员面试题
  10. 运用Parcelable将类序列化并绑定给Intent
  11. GitHub 发布 2018 年开源项目趋势预测:跨平台、深度学习增长最快!
  12. Java 内存模型(Java Memory Model,JMM)
  13. Stubs和Mocks区别 (Stubs vs. Mocks)
  14. 自力更生给笔记本电脑换固态并重装系统
  15. 如何从Docker容器内部获取Docker主机的IP地址
  16. 掌控堆栈确保系统稳定 IAR技术手册翻译
  17. 绿盟漏扫使用手册_【技术干货】Oracle数据库漏洞扫描指南
  18. 27岁从业软件测试5年的我被无情的辞退了
  19. qq邮箱 实现邮件的发送
  20. 视觉平台Visionpro脚本神器

热门文章

  1. java 判断对象是否是xml格式_java对象与xml格式之间的转换
  2. 交换机选用要点及订货主要技术条件
  3. 什么是光纤以太网交换机?
  4. [渝粤教育] 湘潭大学 土力学 参考 资料
  5. 【渝粤教育】国家开放大学2018年春季 0529-21T高级英语阅读(1) 参考试题
  6. 【渝粤教育】广东开放大学 电路分析基础 形成性考核 (59)
  7. 挡土墙计算软件_广联达软件如何计算钢板止水带?
  8. 应用c语言编辑画图程序,应用C语言编辑画图程序
  9. php按钮css样式,CSS 按钮
  10. 信号与系统 chapter2 冲激偶函数与阶跃函数