术→技巧, 研发

图片格式AVIF简介

钱魏Way · · 0 次浏览

在介绍 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 还有尚不明确的 WebP 2。

相关工具

发表回复

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