avif-ffi是一个avif格式图片进行解码显示的仓颉库,解码后静态avif图片和动态avif图片都可以显示在控件上
以下内容由 AI 翻译,如有问题请 点此提交 issue 反馈
介绍
avif-ffi是一个对avif图片进行解码显示的库,解码后静态avif图片和动态avif图片都可以显示在控件上
特性
本项目参考开源库libavif开发
- 🚀 支持avif静态图片解码显示。
- 🚀 支持avif动态图片解码显示。
- 🚀 提供了自定义组件方式,方便用户使用。
- 🚀 增加了缓存功能
源码目录
─avif_hybrid
└─src
└─main
├─cangjie
├─ets
└─resources
avif_hybrid工程模块 - 编译生成一个har包avif_hybrid src模块代码目录avif_hybrid src main模块项目目录avif_hybrid src main cangjie仓颉代码目录avif_hybrid src main etsets代码目录avif_hybrid src main resources资源文件目录
接口说明
主要类和函数接口说明详见 API
使用说明
三方库导入使用
1. 本地编译安装
描述具体的编译过程:
1.先通过命令把代码下载下来
git clone -b avif-ffi_hybrid-cangjie-plugin-5.1.1_xc https://gitcode.com/Cangjie-TPC/avif-ffi.git
2.在deveco里选择avif_hybrid模块,点击Build菜单,然后点击 Make Module 'avif_hybrid' 等待编译完成,项目则编译成功
3. 然后在avif_hybrid模块下的build/default/outputs/default/下找到avif_hybrid.har
4. 用户在自己应用的module下新建一个文件夹名为har,然后把avif_hybrid.har文件放入其中
5. 然后在用户module下的oh-package.json5下面添加依赖
"dependencies": {
"@cangjie-tpc/avif_hybrid": "file:./har/avif_hybrid.har"
}
添加完后点击自动弹出的sync now同步
6. 在项目中使用avif项目
import { AvifDecoderTS,CjCacheCheckTS,GlobalUtils,global_customLib,CJReturnValue } from '@cangjie-tpc/avif_hybrid';
功能示例
1. 在项目中显示avif图片
1.1 用提供的自定义组件加载两个本地的resources下的media下的avif图片,一个是静态图,一个是动态图
示例代码如下:
import { AvifViewTS, AvifImageModel } from '@cangjie-tpc/avifhybrid';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct page11Test {
avifImageModel1: AvifImageModel = new AvifImageModel()
avifImageModel2: AvifImageModel = new AvifImageModel()
avifImageModel3: AvifImageModel = new AvifImageModel()
avifImageModel4: AvifImageModel = new AvifImageModel()
avifImageModel5: AvifImageModel = new AvifImageModel()
avifImageModel6: AvifImageModel = new AvifImageModel()
@State ready: boolean = false
completeCallback(status: number): void {
hilog.error(1, "1", 'complete')
}
async aboutToAppear(): Promise<void> {
this.avifImageModel1.setUri("https://pic1.iqiyipic.com/image/20240622/65/fc/v_177081820_m_601_m1_592_333.avif")
.setImageViewWidth('600px')
.setImageViewHeight('400px')
.setTopleftBorderRadius('20vp')
.setToprightBorderRadius('20vp')
.setBottomleftBorderRadius('20vp')
.setBottomrightBorderRadius('20vp')
.setOnComplete(this.completeCallback)
.setDraggable(false)
this.avifImageModel2.setUri("https://pic8.iqiyipic.com/animated/20250806/3f/9e/5830642737316600_1754449128430_720_405.avif")
.setImageViewWidth('600px')
.setImageViewHeight('400px')
.setTopleftBorderRadius('20vp')
.setToprightBorderRadius('20vp')
.setBottomleftBorderRadius('20vp')
.setBottomrightBorderRadius('20vp')
.setOnComplete(this.completeCallback)
.setDraggable(true)
this.avifImageModel3.setUri("media://a2")
.setImageViewWidth('600px')
.setImageViewHeight('400px')
.setTopleftBorderRadius('20vp')
.setToprightBorderRadius('20vp')
.setBottomleftBorderRadius('20vp')
.setBottomrightBorderRadius('20vp')
.setOnComplete(this.completeCallback)
.setDraggable(true)
this.avifImageModel4.setUri("media://a22")
.setImageViewWidth('600px')
.setImageViewHeight('400px')
.setTopleftBorderRadius('20vp')
.setToprightBorderRadius('20vp')
.setBottomleftBorderRadius('20vp')
.setBottomrightBorderRadius('20vp')
.setOnComplete(this.completeCallback)
.setDraggable(true)
this.avifImageModel5.setUri("rawfile://a3.avif")
.setImageViewWidth('600px')
.setImageViewHeight('400px')
.setTopleftBorderRadius('20vp')
.setToprightBorderRadius('20vp')
.setBottomleftBorderRadius('20vp')
.setBottomrightBorderRadius('20vp')
.setOnComplete(this.completeCallback)
.setDraggable(true)
this.avifImageModel6.setUri("rawfile://a23.avif")
.setImageViewWidth('600px')
.setImageViewHeight('400px')
.setTopleftBorderRadius('20vp')
.setToprightBorderRadius('20vp')
.setBottomleftBorderRadius('20vp')
.setBottomrightBorderRadius('20vp')
.setOnComplete(this.completeCallback)
.setDraggable(true)
this.ready = true
}
build() {
Row() {
Scroll() {
Column() {
if (this.ready) {
AvifViewTS({ model: this.avifImageModel1 })
AvifViewTS({ model: this.avifImageModel2 })
AvifViewTS({ model: this.avifImageModel3 })
AvifViewTS({ model: this.avifImageModel4 })
AvifViewTS({ model: this.avifImageModel5 })
AvifViewTS({ model: this.avifImageModel6 })
}
}
.width('100%')
}.scrollBar(BarState.Off)
.height('100%')
}
}
}
执行结果如下: 图片在手机上成功展示。
正常显示图片
1.2 使用提供的 API 加载 URL 中的 AVIF 图片。内存图片为原图大小
示例代码如下:
import { AvifDecoderTS, CjCacheCheckTS } from '@cangjie-tpc/avifhybrid';
import { image } from '@kit.ImageKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct page1Test {
@State pixelMap: PixelMap | undefined = undefined
@State mWidth: number = 0
@State mHeight: number = 0
async aboutToAppear(): Promise<void> {
let uri = "https://pic1.iqiyipic.com/image/20240622/65/fc/v_177081820_m_601_m1_592_333.avif"
let cacheCheck = new CjCacheCheckTS()
let cJReturnValue = cacheCheck.getMemoryCache(uri,0,0)
if(cJReturnValue.issuccess){
hilog.error(0,"aviflog","走的是内存缓存"+cJReturnValue.memoryHeight+"---"+cJReturnValue.memoryWidth)
if(cJReturnValue.color){
let array = new Uint8Array(cJReturnValue.color)
hilog.error(0,"aviflog","走的是内存缓存"+array.length)
}
this.mWidth = cJReturnValue.memoryWidth
this.mHeight = cJReturnValue.memoryHeight
let validReturnValue = cJReturnValue.color ?? new Uint8Array()
let opts: image.InitializationOptions =
{ editable: true, pixelFormat: 3, size: { height: cJReturnValue.memoryHeight, width: cJReturnValue.memoryWidth } }
this.pixelMap = await image.createPixelMap(validReturnValue, opts)
}else{
let decoderTs = await AvifDecoderTS.create(uri)
if(!decoderTs){
return
}
this.mWidth = decoderTs.getWidth()
this.mHeight = decoderTs.getHeight()
let cjreturnValue = await decoderTs.nextFrameffi(0,0)
let validReturnValue = cjreturnValue.color ?? new Uint8Array()
if(cjreturnValue.color){
let array = new Uint8Array(cjreturnValue.color)
hilog.error(0,"aviflog","数据"+array.length)
}
let opts: image.InitializationOptions =
{ editable: true, pixelFormat: 3, size: { height: this.mHeight, width: this.mWidth } }
this.pixelMap = await image.createPixelMap(validReturnValue, opts)
decoderTs.release()
}
}
aboutToDisappear(): void {
if (this.pixelMap) {
this.pixelMap.release()
}
}
build() {
Row() {
Scroll() {
Column() {
Image(this.pixelMap)
.width(this.mWidth)
.height(this.mHeight)
.objectFit(ImageFit.Fill)
}
.width('100%')
}.scrollBar(BarState.Off)
.height('100%')
}
}
}
执行结果如下: 图片在手机上成功展示。
正常显示图片
1.3 使用提供的API加载一个URL中的AVIF图片。内存图片尺寸为100*100
示例代码如下:
import { AvifDecoderTS, CjCacheCheckTS } from '@cangjie-tpc/avifhybrid';
import { image } from '@kit.ImageKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
@Entry
@Component
struct page5Test {
@State pixelMap: PixelMap | undefined = undefined
@State mWidth: number = 0
@State mHeight: number = 0
async aboutToAppear(): Promise<void> {
let uri = "https://pic1.iqiyipic.com/image/20240622/65/fc/v_177081820_m_601_m1_592_333.avif"
let cacheCheck = new CjCacheCheckTS()
let cJReturnValue = cacheCheck.getMemoryCache(uri,100,100)
if(cJReturnValue.issuccess){
hilog.error(0,"aviflog","走的是内存缓存"+cJReturnValue.memoryHeight+"---"+cJReturnValue.memoryWidth)
if(cJReturnValue.color){
let array = new Uint8Array(cJReturnValue.color)
hilog.error(0,"aviflog","走的是内存缓存"+array.length)
}
let validReturnValue = cJReturnValue.color ?? new Uint8Array()
let opts: image.InitializationOptions =
{ editable: true, pixelFormat: 3, size: { height: cJReturnValue.memoryHeight, width: cJReturnValue.memoryWidth } }
this.pixelMap = await image.createPixelMap(validReturnValue, opts)
}else{
let decoderTs = await AvifDecoderTS.create(uri)
if(!decoderTs){
return
}
let cjreturnValue =await decoderTs.nextFrameffi(100,100)
let validReturnValue = cjreturnValue.color ?? new Uint8Array()
if(cjreturnValue.color){
let array = new Uint8Array(cjreturnValue.color)
hilog.error(0,"aviflog","数据"+array.length)
}
let opts: image.InitializationOptions =
{ editable: true, pixelFormat: 3, size: { height: 100, width: 100 } }
this.pixelMap = await image.createPixelMap(validReturnValue, opts)
decoderTs.release()
}
}
aboutToDisappear(): void {
if (this.pixelMap) {
this.pixelMap.release()
}
}
build() {
Row() {
Scroll() {
Column() {
Image(this.pixelMap)
.objectFit(ImageFit.Fill)
}
.width('100%')
}.scrollBar(BarState.Off)
.height('100%')
}
}
}
执行结果如下: 图片在手机上成功展示。
正常显示图片
约束与限制
在下述版本验证通过:
| 编号 | 依赖构建工具 | 版本号 |
|---|---|---|
| 1 | DevEco Studio | 5.1.1.851 |
| 2 | cjc | v1.0.5 |
avif依赖三方库:
| 编号 | 依赖三方库 | 版本号 |
|---|---|---|
| 1 | stdx | v1.0.1.1 |
开源协议
本项目基于 Apache-2.0 License,请自由地享受和参与开源。
参与贡献
欢迎给我们提交PR,欢迎给我们提交Issue,欢迎参与任何形式的贡献。