图片格式转换与压缩的一点理解


本想鸽掉这一篇,因为实在没啥好讲的。然后过了几天想想还是随便记点吧。

1. WEBP

谷歌推出的图片压缩格式,同时支持有损和无损压缩,通常比同品质的jpeg,png,gif小,已经得到主流浏览器的普遍支持。因此把自家网站的图片换成webp成了一个趋势。
一个不错的方案是,提供图片资源的服务器检测客户端的ua是否支持webp,对于支持的客户端重写url为对应的webp资源。通过cdn部署的话可以通过类似cloudfront的lambda钩子来实现。

  • 命令行工具gmagick/imagick
  • python库Pillow
  • nodejs库sharp/gm

一般来说,各个语言的图片处理库都会支持webp格式转换,不过要想得到比较好的体验,还是需要研究一下jpg,png的特点来调整对应的参数(如果支持接收参数的话)。转换的初衷肯定是因为webp更小,如果遇到下面问题就得不偿失了。

  1. jpeg转webp后更大了?
  2. png转webp后变大了?

2. JPEG

jpeg曾经是一个非常厉害的有损压缩格式,大致原理可以通过这个视频了解:

JPEG不可思议的压缩率——归功于信号处理理论
ps: 评论区也很精彩

大概总结下就是:

  • 利用人眼对亮度和色彩的不同敏感特点,将RGB转为YCbCr,然后进行下采样
  • 采用离散余弦变换 DCT进行维度压缩。虽然说这属于信号处理范畴(当然也是数学),但是好像特别眼熟:
    • PCA主成分分析。筛选特征有木有–尽量保持图像的品质;数据降维有木有–用更少的比特表示
    • VAE自编码器。高维特征压缩成低维向量,再还原成高维的特征,尽量表现得跟原来一样
    • 延申一下,为啥是余弦?因为cos(0)=1,这样才能作为空间变换的基底。

一旦了解了jpeg的压缩原理,那么就知道为啥jpeg转webp会变大了:原图jpeg的压缩率已经很高了,转换的时候指定的webp的压缩品质却比较高。举个简单例子解释一下:

  • jpeg压缩品质50,渲染图片的时候用5个比特解出10比特的像素。
  • webp输出品质80,渲染时用8个比特解出10比特的像素。
    但其实这个时候有效比特只有5位,多出来的3位都是0无效比特,白白占用空间,反而比原jpeg都大。所以转换之前需要读取jpeg的压缩品质,基于这个品质来决定webp的输出品质。jepg的压缩品质在文件头中,可以通过gmagick工具很方便的读取。
gm -verbose example.jpg

然而可惜的是目前尝试的各个python/js库都不支持获取这个值(也可能是姿势不对)。

3. PNG

PNG的原理没有去深挖,此处应该留个坑。仅凭印象对png的理解有

  • 需要透明像素,上png
  • 比jpg大,一般都比较清晰
    然而实际上对于某些色彩比较少的图片,png有独门秘技调色板palette,可以在无损的前提下达到非常高的压缩率。原本每个像素点都有RGBA4个通道,理论上有255^4种颜色变化。一张800*600的图片需要8006004字节来存储。但幸运的是这张图片只有256种颜色,那么我们先存储一张调色盘,大小是256*4字节,然后每个像素点都只需要存一个调色盘的索引:800*600字节。压缩率为
    (256*4+800*600)/(800*600*4) = 0.25

所以对于某些库,比如sharp,在转换webp的过程中会先把png转成RGBA格式,这样转成webp之后就会变得很大,需要手动指定palette的配置参数。

4. GIF

GIF其实就是连续的png,文件头中定义了帧数,播放间隔。可以理解为数组 PNG[]。一般来说默认的行为都是只读取gif的第一帧。因此如果需要转换webp,需要读取帧数pages和循环次数loop,再传给webp转换处理。

5. 图片resize

我们知道对于不同的屏幕,逻辑像素和物理像素并不是一比一的对应关系(DevicePixelRate)。因此为了在高分屏获得最佳体验,一般会提供2倍甚至3倍尺寸的图片。实际应用中我们可能希望只上传一张高清大图,通过图片处理服务生成更小尺寸的图,以及转换成对应的webp格式。这里就涉及到resize下采样的问题了。

  • 对于jpeg图片,一般的下采样算法(临近采样其实就是卷积?)是有效的
  • 对于RGB(A)的png,也是有效的
  • 对于采用了palette的png,因为原图的色彩数量是有限的(通常是256),通过下采样(卷积)会产生新的颜色。如果要保持palette调色板,那么图片就容易失真,锯齿严重。如果想要得到平滑的图片,图片大小就会不受控制地超过原图。这种情况下直接保持原尺寸的png是最好的。

原创文章,作者:jamestackk,如若转载,请注明出处:https://blog.ytso.com/268071.html

(0)
上一篇 2022年6月19日
下一篇 2022年6月19日

相关推荐

发表回复

登录后才能评论