图片资源,在我们的业务中可谓是占据了非常大头的一环,尤其是其对带宽的消耗是十分巨大的。
对图片的性能优化及体验优化在今天就显得尤为重要。本文,就将从各个方面阐述,在各种新特性满头飞的今天,我们可以如何尽可能的对我们的图片资源,进行性能优化及体验优化。
首先,从图片的类型上而言,除了常见的 PNG-8/PNG-24,JPEG,GIF 之外,我们更多的关注另外几个较新的图片格式:
首先,通过一张表格,快速过一下这几个图片,我们将从图片类型、透明通道、动画、编解码性能、压缩算法、颜色支持、内存占用、兼容性方面,对比它们:
| 图片类型 | Alpha 通道 | 动画 | 编解码性能 | 压缩算法 | 颜色支持 | 内存占用 | 兼容性 |
|---|---|---|---|---|---|---|---|
| GIF | 支持 | 支持 | 较高 | 无损压缩 | 索引色(256) | 基本一致 | ALL |
| PNG-8/PNG-24 | 支持 | 不支持 | 较高 | 无损压缩 | 索引色(256)\直接色 | 基本一致 | ALL |
| JPEG | 不支持 | 不支持 | 较高 | 有损压缩 | 直接色 | 基本一致 | ALL |
| WebP | 支持 | 支持 | 编解码性能差(低配设备更为显著) | 有损压缩\无损压缩 | 直接色 | 基本一致 | 高版本 Chrome\Opera\Android |
| JPEG XL | 支持 | 支持 | 渐进式解码 | 有损压缩\无损压缩 | 直接色 | 基本一致 | 部分高版本 Chrome\Opera\Firefox\Edge |
| AVIF | 支持 | 支持 | 编解码性能一般 | 有损压缩\无损压缩 | 直接色 | 基本一致 | 高版本 Chrome\Opera\Android\Edge |
首先,了解了解上述的一些参数含义:
当然,需要指出的是,Alpha 没有透明度的意思,不代表透明度。opacity 和 transparency 才和透明度有关,前者是不透明度,后者是透明度。比如 css 中的「opacity: 0.5」就是设定元素有 50% 的不透明度。后来 Alvy Ray Smith 提出每个像素再增加一个 Alpha 通道,取值为0到1,用来储存这个像素是否对图片有「贡献」,0代表透明、1代表不透明。也就是说,「Alpha 通道」储存一个值,其外在表现是「透明度」,Alpha 和透明度没啥关系
有损压缩算法是一种数据压缩方法,经过此方法压缩、解压的数据会与原始数据不同但是非常接近。原理是借由将次要的信息数据舍弃,牺牲一些质量来减少数据量、提高压缩比
无损压缩指数据经过压缩后,信息不受损失,还能完全恢复到压缩前的原样。无损压缩通常用于严格要求“经过压缩、解压缩的数据必须与原始数据一致”的场合。
索引颜色是一种以有限的方式管理数字图像颜色的技术,以节省计算机内存和文件存储,同时加速显示刷新和文件传输。即用一个数字来代表(索引)一种颜色,在存储图片的时候,存储一个数字的组合,同时存储数字到图片颜色的映射。这种方式只能存储有限种颜色。索引色常见有1位(即黑白),8位(即灰阶/256色),16位(即高彩),24位(即真彩),30/36/48位(即全彩)。
直接色使用四个数字来代表一种颜色,这四个数字分别代表这个颜色中红色、绿色、蓝色以及透明度(即 RGBA)。现在流行的显示设备可以在这四个维度分别支持256种变化,所以直接色可以表示2的32次方种颜色。
因为传统的 PNG-8/PNG-24,JPEG,GIF 各自或多或少都存在一些问题,近些年来它们的替代方案之争也愈演愈烈,核心领跑者可能是 WebP、JPEG XL、AVIF。
再简单了解了解它们:
WebP 最初由 Google 在 2010 年 9 月发布,其特性总结如下:
对于复杂的图像(比如照片)来说,WebP 无损编码表现并不好,但有损编码表现却非常棒。相近质量的图片解码速度 WebP 相距 JPEG 也已经相差不大了,而文件压缩比却能提升不少。
下图是我之前还在 TX 的时候做的一个测试对比:
加载同样张数的 JPEG 与 WebP 的耗时对比:
对于 WebP 图片格式,简单做个总结:
截止至(2023-02-05)的兼容性图:
JPEG XL 由联合图像专家组(开发原始 JPEG 标准的同一组织)于 2021 年发布,旨在成为传统 JPEG 的长期替代品。作为一种免版税的开源标准,JPEG XL 的创建者希望其格式的开放性能够吸引网络开发人员采用该标准,该格式的扩展名为 .jxl,JXL 核心比特流于 2021 年 1 月冻结,文件格式于 2021 年 4 月定稿。:
JPEG XL 中的 X 指 2000 年以来的多个 JPEG 标准的名称:JPEG XT、JPEG XR、JPEG XS,而 L 表示 'long-term',表示“长期”。创建这种格式是为替换旧的JPEG文件格式,并使用足够长的时间。
其主要特点有:
看看同一张图片,相同质量下的大小表现:
JPEG XL 是目前而言,最有可能全面替代传统图片格式(Gif、PNG、JPEG)的下一代标准,当然,在今天,需要看看其兼容性:
好吧,目前的兼容有点离谱。Chrome 从 91 版本开始已经实验室性质支持了 .jxl 格式的图片,需要通过 --enable-features=JXL 配置开启,遗憾的是,从 Chrome 110 开始,Chrome 又不再支持 JPEG XL 。
有趣的是,Chrome 从 110 版本开始中弃用了对 JPEG-XL 的支持,谷歌的回答是,人们对 JPEG-XL 没有足够的兴趣,并且与现有格式相比也没有足够的优势。谷歌之前一直对 JPEG 的支持都是实验性的性质的,他们认为 JPEG XL 缺乏生态系统支持,并且该格式没有足够多的好处(相对 WebP 和 AVIF)。也就是说,目前而言,Chrome 对 WebP 和 AVIF 等替代格式更感兴趣。
最后,我们再来看看 AVIF 格式图片。
AVIF 是由开放媒体联盟 (AOM) 开发并于 2019 年发布的另一种最新图像格式。该格式基于 AV1 视频编解码器,源自视频帧。其特点如下:
看看 CaniUse 的数据:
下图是 WebP vs JPEG XL vs AVIF 三者在图片解码上的性能表现:
从图中可以看到,对于解码性能的对比,结果居然是 WebP > AVIF > JPEG XL 。JPEG XL 的编解码性能并没有其描述的那么强大。
总结一下,WebP、AVIF 和 JPEG XL 都是浏览器不广泛支持的新型图像格式。虽然 WebP、AVIF 已经存在很长时间,但到今天,影响它们大规模使用的依旧是兼容问题。它们各自有各自的特点与优势,谁能胜出仍未知晓。
虽然 AVIF、JPEG XL 等新型图片格式未得到任何浏览器的完全支持,但是在新版本的 Chrome、Firefox 和 Edge Chromium,可以使用配置标志启用对应图像格式,配合 HTML 的 Picture 标签,我们还是可以一定程度上对我们的图片进行格式选择上的优化的。
这,就可以引出我们要说的第二部分 -- HTML Picture 标签的使用。
HTML5 规范新增了 Picture Element。那么 <picture> 元素的作用是什么呢?
<picture> 元素通过包含零或多个 <source> 元素和一个 <img> 元素来为不同的显示/设备场景提供图像版本。浏览器会选择最匹配的子 <source> 元素,如果没有匹配的,就选择 <img> 元素的 src 属性中的 URL。然后,所选图像呈现在 <img> 元素占据的空间中。
什么意思呢?怎么使用 <picture> 元素呢?
假设,没有 <picture> ,只有 <img> 元素,我们想尽可能在支持一些现代图片格式的浏览器上使用类似于上述我们提到的 WebP、AVIF 和 JPEG XL 等图片格式,而不支持的浏览器回退使用常规的 JPEG、PNG 等。没错,就是一种渐进增强的思想,该怎么办呢?
只能是 JavaScript 去写对应的逻辑,通过 JS 脚本进行特性查询,动态赋值给 <img> 的 src。
而有了 <picture> 后,浏览器将原生支持上述的一些列操作,我们来看看对应的语法:
<picture>
<!-- 可能是一些对兼容性有要求的,但是性能表现更好的现代图片格式-->
<source src="image.avif" type="image/avif">
<source src="image.jxl" type="image/jxl">
<source src="image.webp" type="image/webp">
<!-- 最终的兜底方案-->
<img src="image.jpg" type="image/jpeg">
</picture>
上述代码的含义是:
source 元素指向新 AVIF 格式的图像。如果浏览器支持 AVIF 图像,那么它会选择该图像文件。否则,它将移动到下一个 source 元素。source 元素指向新 JPEG XL 格式的图像。如果浏览器支持 JPEG XL 图像,那么它会选择该图像文件。否则,它将移动到下一个 source 元素。source 元素指向一张WebP 格式的图像。如果浏览器能够渲染 WebP 图像,它将使用该图像文件。img 元素 src 属性中的图像文件。img 元素指向的是 JPEG 格式的图片,它是最终的兜底方案。这意味着现在我们可以在不牺牲向后兼容性的情况下开始使用新的图像格式。
简而言之,<picture> 元素的作用:
<source> 给出一系列对兼容性有所要求的现代图片格式选项<img> 给出兜底的高兼容性图片格式选项<source> 的 srcset、media 和 type 属性,来选择最匹配页面当前布局、显示设备特征等的兼容图像。<img> 元素占据的空间中总结一下,本文对常见的图片格式以及最新的几种未被大规模兼容的图片格式进行的对比,它们分别是:
其后,着重介绍了 3 种现代图片格式:WebP、JPEG XL、AVIF。相对于 JPEG 等传统格式,它们在色彩表现、动画支持、是否支持无损有损压缩、压损比率、编解码性能上有着更进一步的提升,正在成为下一阶段 Web 图像的标准。
最后,介绍了 <picture> 元素,借助它,我们能更好的实现图片的渐进增强。
当然,本文只是现代图片性能优化及体验优化指南的第一篇,后续将给大家带来图片在:
aspect-ratio 实现图片资源的比例固定及调整<img> 图片与背景图片的取舍等相关知识的介绍,感兴趣的可以提前关注。
OK,本文到此结束,希望本文对你有所帮助 ?
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
假设我做了一个模块如下:m=Module.newdoclassCendend三个问题:除了对m的引用之外,还有什么方法可以访问C和m中的其他内容?我可以在创建匿名模块后为其命名吗(就像我输入“module...”一样)?如何在使用完匿名模块后将其删除,使其定义的常量不再存在? 最佳答案 三个答案:是的,使用ObjectSpace.此代码使c引用你的类(class)C不引用m:c=nilObjectSpace.each_object{|obj|c=objif(Class===objandobj.name=~/::C$/)}当然这取决于
我正在尝试使用ruby和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
我想为Heroku构建一个Rails3应用程序。他们使用Postgres作为他们的数据库,所以我通过MacPorts安装了postgres9.0。现在我需要一个postgresgem并且共识是出于性能原因你想要pggem。但是我对我得到的错误感到非常困惑当我尝试在rvm下通过geminstall安装pg时。我已经非常明确地指定了所有postgres目录的位置可以找到但仍然无法完成安装:$envARCHFLAGS='-archx86_64'geminstallpg--\--with-pg-config=/opt/local/var/db/postgresql90/defaultdb/po