Android性能优化-减小图片下载大小

Red5015 8年前
   <h3><strong>内容概要</strong></h3>    <ol>     <li> <p>理解图片的格式 PNG JPG WebP</p> </li>     <li> <p>如何选择一种图片格式</p> </li>     <li> <p>确定准确质量值</p> </li>     <li> <p>服务端的尺寸大小</p> <p>​</p> </li>    </ol>    <h2><strong>减小图像下载大小</strong></h2>    <p>大多数流量传输都包含图像。 因此,你制作的下载的图片越小,就会为用户提供更好的网络体验。 本篇文章提供了让你的图像文件更小以及更加网络友好的指导。</p>    <h2><strong>理解图像的格式</strong></h2>    <p>Android应用通常使用以下某种或多种文件格式的图片:PNG,JPG和WebP。 对于每种格式,你都可以采取措施缩小图片大小。</p>    <h3><strong>PNG</strong></h3>    <p>缩小PNG文件的关键是减少构成图像的每行像素中使用的唯一颜色数。通过使用更少的颜色,可以提高在其它管道中的压缩能力。</p>    <p>减少独唯一颜色的数量会取得显着效果的原因是,PNG压缩效果基于一个水平方向相邻像素颜色变化程度的函数。因此,减少PNG图像每行中唯一颜色数量可以减少文件大小。</p>    <p>当决定是否采用这种策略时,你应该记住,减少唯一颜色的数量实际上等于对图像应用了有损编码。然而,编码工具可能不会判断一个细小的偏差导致多糟糕的视觉效果。因此,为了保证有效压缩和可接受的图像质量的平衡,你应该手动执行此工作,</p>    <p>有两个特别有用的方法你可以采取:优化索引格式和应用矢量量化。</p>    <p>优化索引格式</p>    <p>任何减少颜色的尝试都应该首先尝试优化颜色,以便将图像导出为PNG时可以使用INDEXED格式。 INDEXED颜色模式会选择最佳的256色彩,并用索引将所有像素值替换到调色板中。 结果是从1600万色彩减少到仅256色彩:等同于从每像素3(没有透明度)或4(具有透明度)字节减少到每像素1字节。这种变化向减少文件迈出了重大的一步。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/e9700db99d47bd4c6350f36bdf40867d.png"></p>    <p>图片 1.一个图像在转换为INDEXED的前后对照</p>    <p>Figure 2 展示了图像1中的调色板</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/89fcebdc7c1a511a84fb7a2414745ef6.png"></p>    <p>将图像表示为调色图像对于显着改善文件大小有很大帮助,因此,如果你的大多数图片都可以转换,可以好好研究一下。</p>    <p>当然,并不是每个图像都可以用256种色彩准确表示。 例如,某些图像可能需要257,310,512或912种颜色才能正确显示。 在这种情况下,矢量化会可能会有帮助。</p>    <p><strong>矢量化</strong></p>    <p>矢量化(VQ)也许是对创建索引图像的过程更好地描述。 VQ会对多维数进行舍入处理。 在此过程中,你图片中的所有颜色都将根据相似性进行分组。 对于给定的组,该组中的所有颜色都将被单个 <em>中心点</em> 值替换,这样可以最大程度地减少该单元格中的颜色错误(如果使用Voronoi术语,则为“site”)。 在图3中,绿色点表示输入颜色,而红色点是替换输入颜色的中心点。 每个单元格由蓝线界定。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/d671f1ab5070b2ebfddbd77e93f428c1.gif"></p>    <p>图3 为图像中的颜色进行矢量化</p>    <p>将VQ应用于图像会减少了唯一颜色的数量,用视觉质量上“相当接近”的单一颜色替换每组颜色。</p>    <p>此技术也允许你为图像定义唯一颜色的最大数量。 例如,图4显示了1670万种颜色(每像素24位,或bpp)的鹦鹉头像,旁边是一个只使用16(3bpp)唯一颜色的版本。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/4f7c19317b634fadf0e5babd72f3dcdb.png"></p>    <p>你可以明显看到有一些质量的损失; 大多数渐变颜色已经被替换,赋予图像带状效果。 因此该图片需要超过16种唯一的色彩。</p>    <p>在管道中设置VQ的步骤可以帮助你对图像中使用的唯一色彩的真实数量有更好地了解,并且可以帮助你显著地减小它们。 有很多可用的工具来帮助你实现此技术。</p>    <h3><strong>JPG</strong></h3>    <p>如果你使用的是JPG图片,这里有几种只做很小的改变就可以显著节省文件大小的方法:</p>    <ul>     <li>通过不同的编码方法生成较小的文件(不影响质量)。</li>     <li>稍微调整质量以得到更好的压缩。</li>    </ul>    <p>执行这些策略通常可以将文件大小减少高达25%。</p>    <p>选择工具时,请记住照片导出工具会将不必要的元数据(如GPS信息)插入到图像中。为了最小化,你可以尝试利用现有工具删除这些信息。</p>    <h3>WebP</h3>    <p>WebP是Android 4.2.1(API 17)支持的较新的图像格式。 这种格式为网络图像提供了卓越的无损和有损压缩。 使用WebP,开发人员可以创建更小,更丰富的图像。 WebP无损图像文件平均比PNG小 26% 。 这些图像文件还支持透明度(也称为alpha通道),成本只有 22% 的字节。</p>    <p>WebP有损图像比同等 SSIM 质量指数下的JPG图像小 25-34% 。 对于可接受有损RGB压缩的场景,有损WebP还能支持透明度,产生的文件大小通常比PNG小3倍。</p>    <p>有关WebP的详细信息,请访问 WebP 。</p>    <h2><strong>选择一种格式</strong></h2>    <p>不同的图像格式适用于不同类型的图像。 JPG和PNG的压缩过程有很大差别,产生的效果差别也很大。</p>    <p>决定使用PNG还是JPG,通常归结于图像本身的复杂性。图5显示了两个图像,由于开发者应用了不同的压缩方案而导致很大的差别。左侧的图像有许多小细节,因此使用JPG压缩效率更高。右侧的图像,很多区域具有相同颜色,使用PNG压缩更有效。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/1efd1207d66e259a95d476b8f89266d6.png"></p>    <p>图5 JPG和PNG的适用场景</p>    <p>WebP格式可以支持有损和无损模式,是PNG和JPG的理想替代品。唯一要记住的是,它只对运行Android 4.2.1(API 17)及更高版本的设备提供支持。不过幸运的是, 大多数设备 都满足这一要求。</p>    <p>图6提供了一个简单的图示来帮助你决定使用哪种压缩方案。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/2a23e3c9c126b005c68ab76efc231eb6.png"></p>    <p>Figure 6. 如何决定一种压缩方案</p>    <h2><strong>确定最佳质量值</strong></h2>    <p>有几种技术可以用来实现压缩和图像质量之间的正确权衡。有一种技术使用标量值,因此仅适用于JPG和WebP。另一种技术利用了Butteraugli库,并可用于所有图像格式。</p>    <h3><strong>标量值(仅限JPG和WebP)</strong></h3>    <p>JPG和WebP的强大来自于你可以使用标量值来平衡质量和文件大小。诀窍是找出图像的正确的质量值。太低的质量水平虽然产生文件小,但以牺牲图像质量为代价。太高的质量水平会增加文件大小,对用户不友好。</p>    <p>最直接的解决方案是选择一些非最大值进行尝试。但是,请注意,质量值对每个图像的影响不同。例如,75%的质量在大多数图像上可能看起来很好,但在另一些图片上效果可能不好。你应该使用图像的代表性样本对选择的最大值进行测试。此外,要确保你是对原始图像执行所有测试,而不是压缩版本。</p>    <p>对于每天上传和发送数百万个JPG的大型媒体应用程序来说,手动调整每个资源是不切实际的。你可以根据图像类别指定几个不同的质量级别来解决这个问题。例如,可以将缩略图的质量设置为35%,因为较小的图像隐藏了更多的压缩伪影(伪影不是很好理解)。</p>    <h3><strong>Butteraugli</strong></h3>    <p>Butteraugli是一个库,用于测试图像的视觉误差阈值:观察者开始注意到图像质量下降的点。换句话说,这个项目试图将压缩图像的失真量化。</p>    <p>Butteraugli允许你定义视觉质量的目标,然后运行PNG,JPG,WebP有损和WebP无损压缩。然后,你可以选择文件大小和Butteraugli级别之间效果最佳的图像。图7示出了在视觉失真以至于用户可以感知到之前,如何使用Butteraugli来找到最低的JPG质量水平;最终文件大小减少了大约65%。</p>    <p style="text-align: center;"><img src="https://simg.open-open.com/show/7a92ceab54e75a4ff681abca3746671d.png"></p>    <p>图7.应用Butteraugli技术之前和之后的图像。</p>    <p>Butteraugli允许你基于输出或输入进行处理。也就是说,你可以在用户感觉到图像出现明显失真之前找到最低的质量设置,或者你可以依次设置图像失真级别去观察对应的质量水平。</p>    <h2><strong>服务端的尺寸</strong></h2>    <p>在服务器上仅存有一种分辨率的图像的方式是很便利的。当设备访问映像时,服务器直接返回给设备该分辨率的图片。</p>    <p>虽然这个解决方案方便了开发者,但对用户来说可能很痛苦,因为这种方案迫使用户下载比实际需要更多的数据。你应该存储多个大小的图像,并根据合适的使用场景提供不同的图像。例如,对于缩略图,服务应该提供缩略图图像而不是全尺寸的版本,这样可以节省很多网络带宽。</p>    <p>这种方法对于下载速度是有利的,并且降低了使用有限或按数据量收费用户的成本。图像在设备和主存储器上也会占用更少的空间。在大图像(例如4K图像)的情况下,这种方式还减少了设备在加载图像之前调整大小的时间。</p>    <p>实现此方法需要有一个后端图像服务,以提供具有适当缓存的各种分辨率的图像。有几种现有的服务可以帮助你,例如, <a href="/misc/goto?guid=4958861538246562274" rel="nofollow,noindex">App Engine</a> 自带了调整图片大小的功能。</p>    <p> </p>    <p>来自:http://www.lightskystreet.com/2016/10/19/android-optimize-image-download-size/</p>    <p> </p>