术→技巧, 研发

图片格式AVIF简介

钱魏Way · · 315 次浏览
!文章内容如有错误或排版问题,请提交反馈,非常感谢!

在介绍WebP的时候,我们已经知道了相比JPG和PNG来说,WebP已经兼顾了高呈现质量以及更小的文件体积,可以说已经非常优秀了,然后还是有一群人不满足于此,他们开发出了AVIF这种号称下一代图像压缩格式的玩意。

AVIF简介

AVIF(AV1 Image File Format)是一种开源的、高效的图像文件格式。它是由联盟开放媒体项目(AOMedia)的AV1视频格式衍生而来的,用于更有效地编码图像数据。AVIF提供了比传统的JPEG和其他图像格式更高的数据压缩性能,同时也提供了更高的图像质量。

AVIF这种图像格式首次是由Netflix这个公司在2020年2月14号这天公布的。Netflix(奈飞)是一家流媒体影视公司,所以必然会有大量的影视海报,它们都是体积很大的大图片。因此Netflix对呈现质量有很高的要求,同时又希望图片体积能尽可能的小,所以他们一直在探寻一种新的图像格式希望能替换JPG。

事实上,AVIF这种图像格式是由开放媒体联盟(aomedia.org)与Google、Cisco以及Xiph.org合作开发出来的。这种格式被创建为一种开源且免版税的图像格式,不像JPEG XR,它是一种压缩非常小但需要昂贵许可才能实现的文件格式。

AVIF的主要优势包括:

  • 高效的压缩:与JPEG,PNG,GIF等格式相比,AVIF可以在相同的文件大小下提供更好的图像质量,或者以更小的文件大小提供相同的图像质量。
  • 丰富的颜色深度:AVIF为每个颜色通道提供高达10位或12位的颜色深度,这比许多传统格式提供的8位深度更高,可以更准确地表示颜色。
  • 高动态范围(HDR)和宽色域(WCG):AVIF支持高动态范围(HDR)和宽色域(WCG),也就是说,它可以包含更明亮的亮点,更深的黑色,以及比标准动态范围图像更广的颜色范围。
  • 透明度支持:AVIF支持alpha透明度(也就是每个像素可以有其自己的透明度级别),类似于PNG和GIF格式。
  • 兼容性:AVIF由多个大型科技公司(包括Google,Netflix,Amazon,Microsoft等)所支持,并已经在一些主流浏览器(如Chrome和Firefox)中实现。

总的来说,AVIF是一种新兴的图像格式,它在压缩效率、颜色表现、HDR和WCG支持等方面都优于传统的图像格式,有望在未来的网络和媒体应用中得到更广泛的使用。

与WebP的比较

国外有个程序员Daniel Aleksandersen写了一个博客,然后他希望他博客的图片尽可能小的占用网络带宽,但是他在犹豫使用什么格式的图像会比较好,所以他决定亲自探索一翻。

他使用了大于600张的图片,通过将他们基于相同的DSSIM情况下编码成不同格式的图片。

然后通过对比这些大量的不同格式的图片数据,他得到的结论是:

类型 50分位数压缩率 85分位数压缩率
WebP -30% -20%
AVIF -50% -40%

AVIF和WebP都是现代的图像文件格式,它们都旨在提供比传统格式(如JPEG和PNG)更高效的图像压缩。然而,它们之间还是有一些关键的区别的:

  • 压缩效率:AVIF大约可以提供比WebP更高20%-30%的数据压缩效率,这意味着在同等图像质量的条件下,AVIF文件的大小比WebP文件的大小更小。
  • 颜色深度:AVIF支持高达10位或12位的颜色深度,而WebP的颜色深度限制为8位。这意味着AVIF可以提供更丰富、更精细的颜色。
  • HDR和WCG:AVIF支持高动态范围(HDR)和宽色域(WCG),而WebP不支持。这使AVIF能够展示更明亮的亮点、更深的黑色和更广的颜色范围。
  • 透明度:AVIF和WebP都支持alpha透明度,也就是说,每个像素可以有其自己的透明度级别。
  • 支持和兼容性:WebP格式由Google开发,目前在各大浏览器和许多应用程序中都得到了广泛支持。而AVIF是一种更年轻的格式,虽然已经得到了Google、Netflix、Amazon、Microsoft等公司的支持,但目前在浏览器和应用程序的支持情况还不如WebP。

总的来说,AVIF在技术参数上(如压缩效率和颜色深度)表现优于WebP,但在设备和软件的兼容性方面,WebP当前的支持度更高。随着时间的推移,AVIF的兼容性和支持度可能会提高。

AVIF的兼容性

AVIF兼容多种浏览器。关于AVIF格式图片兼容的浏览器及其版本,请参见AVIF兼容性

不兼容浏览器的解决方案

方案一:使用picture标签

采用HTML的picture标签,在picture标签中填写一个source标签和一个img标签,source标签设置为AVIF图片。浏览器会优先显示AVIF图片,如果浏览器渲染AVIF图片失败,就会再次请求img标签内的图片并正常渲染:

<picture>
<source srcset="img/photo.avif" type="image/avif">
<source srcset="img/photo.webp" type="image/webp">
<img src="img/photo.jpg" alt="Description of Photo">
</picture>

方案二:使用CSS+JS方式

除了使用picture标签外,还可以使用CSS+JS的方式,兼容显示AVIF图片。使用supportsAvif方法判断浏览器是否支持AVIF,如果支持就设置div的样式为avif,背景图片设置为AVIF图片。如果不支持就会设置div的样式为no-avif,背景图片设置为原图(其他格式备用图片也可以),具体代码如下所示:

JS代码

async function supportsAvif() {
if (!this.createImageBitmap) return false

const avifData =
'data:image/avif;base64,AAAAIGZ0eXBhdmlmAAAAAGF2aWZtaWYxbWlhZk1BMUIAAADybWV0YQAAAAAAAAAoaGRscgAAAAAAAAAAcGljdAAAAAAAAAAAAAAAAGxpYmF2aWYAAAAADnBpdG0AAAAAAAEAAAAeaWxvYwAAAABEAAABAAEAAAABAAABGgAAAB0AAAAoaWluZgAAAAAAAQAAABppbmZlAgAAAAABAABhdjAxQ29sb3IAAAAAamlwcnAAAABLaXBjbwAAABRpc3BlAAAAAAAAAAIAAAACAAAAEHBpeGkAAAAAAwgICAAAAAxhdjFDgQ0MAAAAABNjb2xybmNseAACAAIAAYAAAAAXaXBtYQAAAAAAAAABAAEEAQKDBAAAACVtZGF0EgAKCBgANogQEAwgMg8f8D///8WfhwB8+ErK42A='
const blob = await fetch(avifData).then((r) => r.blob())
return createImageBitmap(blob).then(
() => true,
() => false
)
}

;(async () => {
const classAvif = (await supportsAvif()) ? 'avif' : 'no-avif'
document.body.classList.add(classAvif)
})()

CSS代码

div {
background-repeat: no-repeat;
background-size: 500px 200px;
width: 500px;
height: 200px;
}
.avif div {
background-image: url(https://image-compress-demo.oss-cn-zhangjiakou.aliyuncs.com/demo.jpg?x-oss-process=image/format,avif);
}
.no-avif div {
background-image: url(https://image-compress-demo.oss-cn-zhangjiakou.aliyuncs.com/demo.jpg);
}

方案三:使用JS解码

avif.js这个方案的特点是非常的轻量,生产版本只需要不到4kb。它依赖service worker的请求拦截特性,当页面发出fetch操作时,它可以将请求拦截住,然后给出自己的响应。

这样就能在请求完AVIF格式的图片以后,在service worker当中调用解码器,将图片转码。同时,因为是运行在service worker线程当中,解码操作并不会阻塞UI线程。

方案四:WebAssembly

js做编解码的事情不是特别合适,如果用c语言来做编解码的事情,岂不是更好,目前社区关于WebAssembly的热度很高,发现已经有使用WebAssembly来做AVIF的编解码。

webassembly/packages/avif at main · saschazar21/webassembly (github.com)

AVIF图片的转化

使用编程语言转换图片到AVIF格式需要借助一些库或工具。以下是一些使用Python, PHP, Java, NodeJS, 和Go语言转换图片的示例:

Python

你可以使用pyavif库。首先安装库pip install pyavif,然后使用以下代码:

from PIL import Image
from pyavif import AVIF

img = Image.open('input.jpg')
avif_img = AVIF(img)
avif_img.save('output.avif')

PHP

在PHP中,你可以使用Imagick扩展进行图像转换。注意,你需要在服务器上安装支持AVIF的ImageMagick。

$image = new Imagick('input.jpg');
$image->setImageFormat('avif');
$image->writeImage('output.avif');

Java

目前Java没有直接支持AVIF格式的库。你可能需要调用系统命令执行ImageMagick或者其他转换工具,或者使用JNI调用C语言的libavif库。

Node.js

在Node.js中,可以使用sharp库进行图像格式转换。首先安装sharp(npm install sharp),然后使用以下代码:

const sharp = require('sharp');

sharp('input.jpg')
.avif({ quality: 50 })
.toFile('output.avif');

Go

在Go中,可以使用image库读取图像,然后使用go-avif库进行转换。

package main

import (
avif "github.com/Kagami/go-avif"
"image/jpeg"
"os"
)

func main() {
// Open JPEG file
imgFile, _ := os.Open("input.jpg")
defer imgFile.Close()

// Decode JPEG
img, _ := jpeg.Decode(imgFile)

// Create AVIF file
avifFile, _ := os.Create("output.avif")
defer avifFile.Close()

// Encode AVIF
opts := &avif.Options{
Speed: avif.SpeedFastest,
}
_ = avif.Encode(avifFile, img, opts)
}

请注意,以上代码仅作示例用途。在实际使用中,你还需要处理错误,并确保你的环境正确地安装了所需的库和工具。

其他次世代图片格式

在次世代的图片格式中,BPG被同样使用HEVC(H.265)并且有苹果设备支持的HEIF取代,而由于专利原因HEIF难有更广泛的使用机会,与此相使用AV1的AVIF是HEIF的平替,没有专利问题,有浏览器支持。JPEG XL吸收了FLIF,并且同样没有专利问题。

所以最后剩下的次世代格式就是AVIF、JPEG XL还有尚不明确的WebP2。

相关工具

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注