jpeg第一个标准是于 1992年制定的,适合压缩现实作品,比如常见的相机拍摄,而不适合设计作品,因为设计作品通常亮度分明,颜色种类少,如图标。jpeg不支持透明,是有损压缩,而且这种有损是累积性的。jpeg同时还分为Baseline JPEG(标准型)和Progressive JPEG(渐进式)两种格式,后者可以在数据传输一部分时显示出图片的大致轮廓,随着数据传输而逐渐清晰。jpeg第一个标准制定于1997年,第二个标准为jpeg2000,是于2000年制定的,新标准提升了压缩率,而且支持有损压缩和无损压缩两种方式,并用可以对感兴趣区域(ROI)采用低压缩比,而其他区域采用高压缩比的特殊处理。jpeg2000目前还没有得到广泛运用,标准没有专利,但是实现的核心代码有专利。JPEG 2000是基于小波变换的图像压缩标准,由Joint Photographic Experts Group组织创建和维护。JPEG 2000通常被认为是未来取代JPEG(基于离散余弦变换)的下一代图像压缩标准,其扩展名为jp2,MIME类型是image/jp2。
JPEG XR是微软在2006年后自家定义的一个jpeg标准,相比于普通jpeg,同等质量下它能小一半。除了更好的压缩比,它还能支持透明,而且还支持多种bit位数的颜色通道。2007年微软将这一标准推荐给Joint Photographic Experts Group组织,以希望能替代传统的jpeg,但目前为止JPEG XR只在windows media里有使用。
以上这些特性与jpeg的压缩算法有关,其将图像信号转换成频率域进行处理,频率越高的分量,系数越小,对图片产生的影响越小,使用的分量越多,图片就越细致。平衡适合的细致度和存储尺寸,抛弃掉一些频率分量即可。这一算法值得压缩到指定尺寸变得非常容易,渐进显示也更为原生自然。
像其他图片格式一样,jpeg支持很多其他信息的存储,使用图片编辑软件(photoshop或者美图秀秀)都会带上很多附属信息,使用相机也会带上各种信息,如下图是人人网相册中的一个截图,该相册提供了一个显示附属信息的功能,可知道拍照的时间、光圈、相册型号等等。用程序很容易抹除掉这些信息,或者添加其他信息。
gif产生于1987年,算是最早的适合网络传输且至今广泛使用的图片压缩格式,早期的带宽小且网络内容简单,它采用索引色方法,顶多只支持256色,所以有很高的压缩比,特别适合图标、图表等只有少量颜色的图片。1989年的修定版添加了透明和多帧动画的功能。gif是无损压缩,采用Lzw编码,特别适合反复重复的色值。gif也支持渐进显示,实际是叫交织编码(interlacing),效果比较粗糙,编码顺序为0, 8, 16, ...(8n), 4, 12, ...(8n+4), 2, 6, 10, 14, ...(4n+2), 1, 3, 5, 7, 9, ...(2n+1),所以渐进显示时像扫描仪一样一行一行扫下来,并不如JPEG那样逐渐清晰那样自然。
gif不支持半透明,所以有不可避免的边缘锯齿问题,一个圆形的gif图的边缘会相当丑陋。而接下来要讲的png支持半透明,所以同样是256索引色,png能够抗锯齿。
早期gif有专利的限制,使用是需要交专利费的,加上gif有256色的限制,随着网络带宽的发展,人们有理由享受更清晰的图片质量,这就导致了PNG的产生。PNG是无损压缩,它的压缩算法与PNG本身独立,通常是LZ77的衍生算法,好像也可以选用zip、lmza等等,同样尺寸的图片比JPEG大得多。不过,PNG细分几种格式,格式不一样,压缩情况也不一样:
PNG8:为256色索引图片,跟gif原理一样。支持布尔透明,也支持256 alpha通道透明,这种格式图片会小很多。PNG24:只有RGB三个通道,所以是不支持透明的全彩格式。PNG32:也就是RGBA四通道,这种格式存储会很占空间。
png的交织编码跟gif相似,不过有水平和垂直两个方向,算法名字叫 Adam7 algorithm,wikipedia上有很形象的动画,如下:
webp于2010年由Google推出,于2011年推出支持动画版本的webp。这种格式最大的特点就是体积小,跟JPEG相比,同样的质量,webp会小40%,特别适合移动设备上的图片传输,不过编码耗时比jpeg长8位。目前,chrome上已经支持webp格式,Facebook和Taobao都已开始使用webp了,安卓4.0以上也原生支持webp。webp只能用20个字节来存储附属信息,不像jpeg那样可以存储七七八八大量的额外信息。2010年推出的webp采用预测编码,是有损压缩,不支持透明。2011年推出的新版开始考虑无损压缩,以及对alpha通道的支持,相对于png能小45%。
gif和png适合于颜色数少的图片,而jpeg适合细节丰富的图片,webp对于两种情况都能很好支持。遗憾的是很多浏览器和移动终端(如:iphone)还不支持webp,均需要第三方扩展。下面这段代码可以用来检测浏览器对webp的支持与否,从而决定是向服务器请求jpeg还是webp图片:
function check_webp_feature(feature, callback) {
var kTestImages = {
lossy: "UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA",
lossless: "UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==",
alpha: "UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==",
animation: "UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA"
};
var img = new Image();
img.onload = function () {
var result = (img.width > 0) && (img.height > 0);
callback(feature, result);
};
img.onerror = function () {
callback(feature, false);
};
img.src = "data:image/webp;base64," + kTestImages[feature];
}
check_webp_feature('lossy', function(feature, result) { console.log(result); });