1

图片格式AVIF简介

 1 week ago
source link: https://www.biaodianfu.com/avif.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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

AVIF简介

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

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

avif-1.png

事实上,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 情况下编码成不同格式的图片。

avif-webp.png

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

类型 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兼容性

avif-2.png

不兼容浏览器的解决方案

方案一:使用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>
<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)
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代码

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);
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')
from PIL import Image
from pyavif import AVIF

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

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

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

目前 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');
const sharp = require('sharp');

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

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

package main
import (
avif "github.com/Kagami/go-avif"
"image/jpeg"
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)
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。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK