导语
AVIF 是一种基于 AV1 视频编码的新一代图像格式,压缩率高,画面细节好。移动端 APP 经常面临网络环境不稳定、需要帮用户节省流量等场景,那就使用 AVIF 图片吧。不过 AVIF 目前只在 iOS16、Android12 上得到原生支持,很多机型覆盖不到,怎么办?本文来教你一分钟集成 AVIF 解码器,兼容所有机型。
AVIF 简介
AVIF 是一种基于 AV1 视频编码的新图像格式,相对于 JPEG ,WEBP 这类图片格式来说,它的压缩率更高,并且画面细节更好。而最关键的是,AV1 由谷歌发起的 AOM (开放媒体联盟)推动,在 VP9 的基础上继续演进,无专利授权费用(而且腾讯也是 AOM 的创始成员哦),关于更多的 AVIF 介绍,可以自行搜索,这里不再赘述。
APP 显示 AVIF 图片
由于 AVIF 目前只在 iOS16、Android12 上得到原生支持,要想覆盖所有主流机型,单靠原生支持肯定是不够的。因此需要客户端开发时集成 AVIF 解码器自行解码,
业内开源编解码库:开源编解码库。
腾讯自研编解码库:本文的数据万象 AVIF SDK 基于该编解码库。
直接使用上述解码库,需要自行编译 Android 和 iOS 解码器产物,以及写一些 JNI 代码,如果您的 APP 使用 Glide、SDWebImage 等图片库,还得再按照图片库的要求进行封装集成。这些有不少的工作量,本文叫”一分钟让APP支持AVIF图片“显然是有更快的方法,那就是接入数据万象 AVIF SDK,上述这些事情我们已经帮您做好啦。
数据万象 AVIF 图片 SDK
Android 一分钟集成
使用 Glide 图片库
- 安装 Glide 和 AVIF SDK
implementation 'com.qcloud.cos:avif:1.1.0'
implementation 'com.github.bumptech.glide:glide:version'
annotationProcessor 'com.github.bumptech.glide:compiler:version'
- 注册解码器 GlideModule
// 注册自定义 GlideModule
// 开发者应该创建此类注册相关解码器
// 类库开发者可以继承 LibraryGlideModule 创建类似的注册类
@GlideModule
public class MyAppGlideModule extends AppGlideModule {
@Override
public void registerComponents(@NonNull Context context, @NonNull Glide glide, Registry registry) {
/*------------------解码器 开始-------------------------*/
//注册 AVIF 静态图片解码器
registry.prepend(Registry.BUCKET_BITMAP, InputStream.class, Bitmap.class, new StreamAvifDecoder(glide.getBitmapPool(), glide.getArrayPool()));
registry.prepend(Registry.BUCKET_BITMAP, ByteBuffer.class, Bitmap.class, new ByteBufferAvifDecoder(glide.getBitmapPool()));
//注册 AVIF 动图解码器
registry.prepend(InputStream.class, AvifSequenceDrawable.class, new StreamAvifSequenceDecoder(glide.getBitmapPool(), glide.getArrayPool()));
registry.prepend(ByteBuffer.class, AvifSequenceDrawable.class, new ByteBufferAvifSequenceDecoder(glide.getBitmapPool()));
/*------------------解码器 结束-------------------------*/
}
}
- 使用 Glide 加载图片
像普通 jpg png 图片那样加载图片即可,请参见 Glide 官方文档。
Glide.with(context).load(url).into(imageView);
使用 Fresco 图片库
- 安装 Fresco 和 AVIF SDK
implementation 'com.qcloud.cos:avif:1.1.0'
implementation 'com.facebook.fresco:fresco:version'
// 如果需要支持 avif 动图解码器 则需要加上 fresco:animated-base 依赖
implementation 'com.facebook.fresco:animated-base:version'
- 配置解码器
// 解码器配置
ImageDecoderConfig imageDecoderConfig = new ImageDecoderConfig.Builder()
// 配置 AVIF 静态解码器
.addDecodingCapability(
AvifFormatChecker.AVIF,
new AvifFormatChecker(),
new FrescoAvifDecoder())
// 配置 AVIF 动图解码器
.addDecodingCapability(
AvisFormatChecker.AVIS,
new AvisFormatChecker(),
new FrescoAvisDecoder())
.build();
// 配置 Image Pipeline
ImagePipelineConfig config = ImagePipelineConfig.newBuilder(context)
.setImageDecoderConfig(imageDecoderConfig)
.build();
// 初始化 Fresco
Fresco.initialize(context, config);
- 使用 Fresco 加载图片
像普通 jpg png 图片那样加载图片即可,请参见 Fresco 官方文档。
<com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/my_image_view"
android:layout_width="130dp"
android:layout_height="130dp"
fresco:placeholderImage="@drawable/my_drawable"
/>
Uri uri = Uri.parse("https://xxx.com/test.avif");
SimpleDraweeView draweeView = (SimpleDraweeView) findViewById(R.id.my_image_view);
draweeView.setImageURI(uri);
iOS 一分钟集成
- 安装 SDWebImage 和 AVIF SDK
在您工程 Podfile 文件中添加模块:
pod 'CloudInfinite/SDWebImage-CloudInfinite'
pod 'CloudInfinite/AVIF'
在终端执行安装命令:
pod install
- 使用 SDWebImage 直接加载 AVIF 图片
SDWebImage-CloudInfinite 模块在 APP 启动时已自动将 AVIF 解码器加入到 SDWebImage 解码器队列中,在加载解码器时自动找到 AVIF 解码器来解码图片。支持动图,无需额外操作。使用时与 SDWebImage 使用没有任何区别。
Objective-C:
[imageView sd_setImageWithURL:[NSURL URLWithString:@"AVIF 图片链接"]];
Swift:
UIImageView() .sd_setImage(with: NSURL.init(string: "AVIF 图片链接"))
数据万象 AVIF SDK 其他功能
基础解码器
用于直接将 AVIF 数据解码为 bitmap、UIImage,以及判断图片数据是否是 AVIF 格式
Android:
import com.tencent.qcloud.image.avif.Avif;
// 图片的字节数组
byte[] buffer = new byte[XXX];
// 是否是 AVIF 格式
boolean isAvif = Avif.isAvif(buffer);
// 是否是 AVIF 动图
boolean isAvis = Avif.isAvis(buffer);
// 原图解码
Bitmap bitmap = Avif.decode(buffer);
// 宽度等比解码
// 目标宽度
int dstWidth = 500;
Bitmap bitmap = Avif.decode(buffer, dstWidth);
// 区域缩放解码
// 区域左上角x坐标
int x = 0;
// 区域左上角y坐标
int y = 0;
// 区域宽度
int width = 100;
// 区域高度
int height = 100;
// 缩放比, 大于1的时候才生效,小于等于1的情况下不作缩放
int inSampleSize = 2;
Bitmap bitmap = Avif.decode(buffer, x, y, width, height, inSampleSize);
iOS:
#import "AVIFDecoderHelper.h"
#import "UIImage+AVIFDecode.h"
//判断是否是 AVIF 格式以及动图格式
// data为图片NSData类型数据
BOOL isAVIF = [AVIFDecoderHelper isAVIFImage:data];
//解码 AVIF 图片
// data为图片NSData类型数据
UIImage * image = [UIImage AVIFImageWithContentsOfData:data];
/ data为图片NSData类型数据
// 缩小两倍 并指定解码的范围( rect 以原图为基准)
UIImage * image = [UIImage AVIFImageWithContentsOfData:imageData scale:2 rect:CGRectMake(x, y, width, height)];
Android 超大图采样图片库
- 安装 subsampling-scale-image-view 和 AVIF SDK
implementation 'com.qcloud.cos:avif:1.1.0'
implementation 'com.davemorrissey.labs:subsampling-scale-image-view:3.10.0'
// AndroidX 请使用
// implementation 'com.davemorrissey.labs:subsampling-scale-image-view-androidx:3.10.0'
- 获取 SubsamplingScaleImageView 控件并注册解码器
SubsamplingScaleImageView subsamplingScaleImageView = findViewById(R.id.subsampling_scale_image_view);
// 设置 AVIF 图片解码器
subsamplingScaleImageView.setBitmapDecoderClass(AvifSubsamplingImageDecoder.class);
subsamplingScaleImageView.setRegionDecoderClass(AvifSubsamplingImageRegionDecoder.class);
- 使用 subsampling-scale-image-view 加载图片
像普通 jpg png 图片那样加载图片即可,请参见 subsampling-scale-image-view 官方文档。
// 加载 uri 图片
subsamplingScaleImageView.setImage(ImageSource.uri(uri));
// 加载 assets 图片
subsamplingScaleImageView.setImage(ImageSource.asset("test.avif"));
// 加载 resource 图片
subsamplingScaleImageView.setImage(ImageSource.resource(R.raw.avif));
总结
总之就是数据万象 AVIF SDK 帮您封装了 AVIF 解码器、对 Android iOS 常用的图片库生态也做了封装,真正让您一分钟就能将 AVIF 图片显示到 APP 中。
更加详细的使用说明,请参考:数据万象 Android SDK、数据万象 iOS SDK。