OpenHarmonyUI组件图像处理【免费下载链接】gifdrawable4cj一个gif图像加载库项目地址https://gitcode.com/Cangjie-TPC/gifdrawable4cj点击查看免费下载gifdrawable4cj是一个使用仓颉Cangjie语言实现的 GIF 图像渲染库面向 OpenHarmony/HarmonyOS 应用HAP与模块HAR场景提供从 GIF 二进制数据解析、帧解码到画布播放的完整链路。本文以仓库根目录的 README.md 为主线结合 doc/feature_api.md 中的完整 API 说明与gifdrawable模块源码带你掌握如何在工程中引入该库、用GIFComponent组件播放 GIF、通过ControllerOptions精细控制播放行为以及底层基于 Schema 的流式解析与 LZW 解压是如何工作的。项目定位与核心特性gifdrawable4cj 由entry示例应用 HAP 模块与gifdrawable可复用 HAR 库模块两个工程模块组成核心代码全部使用仓颉语言编写。作为图像加载库它解决的问题是在仓颉 UI 应用中把工程资源、沙箱文件或网络下载得到的 GIF 数据解码为逐帧图像并交给自定义组件驱动播放。仓库 README.md 明确列出以下特性支持播放 GIF 图片提供开箱即用的自定义组件GIFComponent支持控制 GIF 播放/暂停通过autoPlay状态变量一键切换支持调节 GIF 播放速率ControllerOptions.setSpeedFactor()支持加速与减速支持设置显示大小组件宽高由canvasWidth/canvasHeight状态驱动支持不同的拉伸类型内置ScaleType枚举覆盖 7 种缩放与对齐策略。软件架构模块划分与数据流架构图README 提供了两张与解码主题强相关的示意图。第一张展示 GIF 图片内部的主要结构逻辑屏幕描述符、颜色表、图像描述符、扩展块等第二张给出从原始字节到可播放帧的解析流程图源码目录结构README 给出的仓库目录骨架如下其中gifdrawable/src/main/cangjie/src下四个子目录各司其职├─AppScope ├─doc ├─entry │ └─src │ └─main │ ├─cangjie │ └─resources ├─gifdrawable │ └─src │ └─main │ ├─cangjie │ │ └─src │ │ ├─gifdisplay │ │ ├─parser │ │ ├─sparkmd5 │ │ └─utils │ └─resources └─hvigor各目录职责与 README 目录说明一致AppScope全局资源存放目录和应用全局信息配置目录docAPI 文档和使用手册存放目录接口细节见 doc/feature_api.mdentry工程模块编译生成一个 HAP其中entry/src/main/cangjie是仓颉代码目录resources是资源文件目录gifdrawable工程模块编译生成一个 HAR 包即本文使用的库本体gifdrawable/src/main/cangjie/src/gifdisplay组件主体代码目录包含GIFComponent、ControllerOptions、ResourceLoader、FileUtilsgifdrawable/src/main/cangjie/src/parser帧解码目录包含数据流解析GIFUnit8、Schema 解析parseGIF、LZW 解压、GIFFrame帧结构gifdrawable/src/main/cangjie/src/sparkmd5文件哈希计算代码目录用于网络下载文件的本地命名缓存gifdrawable/src/main/cangjie/src/utils解码工具目录URI 编解码、位运算等辅助工具hvigor构建工具目录。在gifdisplay目录下gif_component.cj 是GIFComponent组件实现controller_options.cj 是配置与解码入口resource_loader.cj 负责三种数据来源的读取。编译构建以 module 方式接入工程README 的编译构建章节给出完整的接入流程需要在被集成的应用工程中完成以下 5 步第 1 步克隆下载项目将本仓库拉取到本地。第 2 步把gifdrawable模块整体拷贝到你的应用项目目录下与entry同级。第 3 步修改自身应用entry下的oh-package.json5在dependencies字段添加对gifdrawable的本地文件依赖{ name: entry, version: 1.0.0, description: Please describe the basic information., main: , author: , license: , dependencies: { gifdrawable: file:../gifdrawable } }第 4 步修改自身应用entry/src/main/cangjie下的cjpm.toml在[dependencies]字段下按相对路径声明库的仓颉源码依赖。仓库中 entry/src/main/cangjie/cjpm.toml 的写法即为参考[dependencies] [dependencies.gifdrawable] path ../../../../gifdrawable/src/main/cangjie说明该相对路径从entry/src/main/cangjie出发向上回退四层到仓库根再进入gifdrawable/src/main/cangjie与 README 中的示例一致。实际接入时请以你自己的工程目录层级为准调整。第 5 步在项目中引用库的公开 APIimport gifdrawable.gifdisplay.* import gifdrawable.parser.*其中gifdrawable.gifdisplay提供组件与控制器GIFComponent、ControllerOptions、ResourceLoadergifdrawable.parser提供解码与帧结构parseBufferToFrame、GIFFrame、ScaleType等。功能示例从数据加载到播放控制README 的功能示例章节以GIF 动图数据解析为主线给出完整可复制的调用序列下面按步骤展开。第 1 步在 UI 中添加 GIFComponent 组件在页面状态中声明控制器与各类控制变量然后在build()中挂载组件// 创建一个控制器保证GIFComponent初始化 State var model: ControllerOptions ControllerOptions() // 是否自动播放 State var gifAutoPlay: Bool true // 重置GIF播放每次取反都能生效 State var gifReset: Bool false // 绘制区域宽度 State var compWidth: Float64 300.0 // 绘制区域高度 State var compHeight: Float64 300.0 // 添加GIFComponent组件 GIFComponent( model: model, // 控制器 autoPlay: gifAutoPlay, // 自动播放标志 resetGif: gifReset, // 重置标志 canvasWidth: compWidth, // 绘制区域宽度 canvasHeight: compHeight // 绘制区域高度 )从组件源码看gif_component.cj 中model、autoPlay、resetGif都是WatchLink双向绑定的状态变量autoPlay变化触发watchAutoPlay()为true时立即调用renderFrames()开始播放resetGif取反会先取消定时器、清空画布、将帧索引归零后重新渲染model变化则触发watchModel()等待画布尺寸就绪后重新解析。组件内部使用CanvasCanvasRenderingContext2D绘制并开启抗锯齿RenderingContextSettings(antialias: true)。第 2 步初始化控制器创建独立控制器实例进行数据预处理处理完成后一次性赋值给组件绑定的model可以减少组件刷新次数// 创建控制器 let modelx: ControllerOptions ControllerOptions() // 设置是否使用硬解码 modelx.setOpenHardware(true) // 设置拉伸方式 modelx.setScaleType(ScaleType.FIT_CENTER) // 设置速率 modelx.setSpeedFactor(1) // 设置完成一次播放后的回调函数 modelx.setLoopFinish({loopTime: OptionInt64 })第 3 步加载数据三种方式ResourceLoader提供三种数据来源的读取接口对应 resource_loader.cj 的实现// 读取工程内资源resId 为媒体资源 ID需要传入全局 AbilityContext let buffer: ArrayUInt8 ResourceLoader.loadMedia(UInt32(r(app.media.xxx).id), globalAbilityContext) // 读取沙箱路径下资源仅支持 .gif 后缀文件 let buffer: ArrayUInt8 ResourceLoader.loadRawFile(/data/storage/el2/base/files/xxx.gif) // 下载网络资源成功回调拿到 ArrayByte失败回调拿到错误信息 ResourceLoader.downloadDataWithContext( Model(网络资源地址), // 下载设置 globalAbilityContext, // AbilityContext {buffer: ArrayByte // 下载成功并读取成 ArrayByte 后的回调函数 }, { str: String // 下载错误回调函数 } )几个实现细节值得注意loadMedia(resId, context)通过ResourceManager.getResourceManager(stageContext).getMediaContent(resId, 0)读取媒体资源context为OptionAbilityContext为None时返回空数组并输出错误日志loadRawFile(filename)在 resource_loader.cj 中会先校验文件名必须以.gif结尾否则抛出Exception网络下载走 OpenHarmony 下载代理ohos.request.agent下载前用SparkMD5.hashBinary(model.url, false)生成 URL 的 MD5 作为文件名缓存到/data/storage/el2/base/files目录Model(url, progressCallBack)可附带进度回调进度区间 0%100%下载完成事件触发后自动读取文件内容并删除临时文件。第 4 步数据转换成可显示内容将字节数据交给控制器的loadBuffer异步处理回调中携带OptionString错误信息// 调用数据处理方法 modelx.loadBuffer( buffer, // 步骤3中获取的数据 {error: OptionString if (let Some(v) - error) { // 错误信息处理 } else { // 处理完成开始显示 gifAutoPlay true // 将已完成数据处理的控制器赋值给组件关联的初始化控制器 model modelx } } )loadBuffer在 controller_options.cj 中会根据openHardware分流软解码走userTaskPoolParse任务池解析 createPixelMapAll批量生成 PixelMap硬解码走useHardwareParse系统 ImageSource 的createPixelMapList一次取出全部帧。显示控制数据加载完成、开始播放之后以下状态与接口即构成完整的播放控制面板// 开始 gifAutoPlay true // 暂停 gifAutoPlay false // 重置每次取反都能生效 gifReset !gifReset // 修改宽高 compWidth 100.0 compHeight 200.0 // 修改速率 model.setSpeedFactor(2) // 修改拉伸方式 model.setScaleType(ScaleType.FIT_START)解码原理从字节流到 GIFFrame 的完整链路README 将详细接口指向 doc/feature_api.md该文档按GIF 解码器 → 二进制数据解析器 → 提取 gif 帧数据 → 动图播放 → 其他接口的层次组织。结合parser目录源码可以还原一条完整的解码调用链parseBufferToFrame(arraybuffer, patchRule) └─ parseGIF(byteData) // 包装 UInt8TypedArray构造 GIFSchema └─ parse(stream, schema, result, par) // 循环/条件解析各 GIF 块 └─ decompressFrames(gif, false) // 遍历 Schema 帧列表 └─ decompressFrame(gce, image, gct) // 提取单帧像素 └─ lzw(minCodeSize, data, pixelCount) // LZW 解压 └─ deinterlace(pixels, width) // 隔行扫描重排 └─ prePatchGIF(origins, patchFunc) // 颜色表 → 可绘制 patch 流数据流封装与逐字节读取gif_uint8.cj 定义了UInt8TypedArray字节数组 游标位置封装与GIFUnit8GIF 数据流解析类。GIFUnit8提供一组高阶函数式的读取原语全部以UInt8TypedArray为入参、移动内部游标readByte()/peekByte(offset!: Int64 0)读取/查看下一个字节readBytes(length)/peekBytes(length)读取/查看指定长度字节数组readString(length)读取指定长度并转成字符串用于解析 GIF 头、注释等 ASCII 字段readUnsigned(littleEndian: Bool)将两个字节合成一个 16 位无符号整数littleEndian决定合成顺序——这是 GIF 文件读取中固定的低位优先little-endian读取方式readArray(byteSize, totalFunc)分组读取数据totalFunc负责计算读取次数可结合当前/上次解析的Schema对象动态决定readBits(params: ArrayInt64)按(起始位置, 切割长度)的成对参数如[0, 3, 3, 5]把一个字节的 8 个 bit 重新组合subBitsTotal(bits, startIndex, length)把指定 bit 段计算为十进制值。Schema 驱动的流式解析框架GIF 文件本质是若干块Block的串联头、逻辑屏幕描述符、全局颜色表、图形控制扩展GCE、图像描述符、图像数据、尾块等。feature_api.md 用Schema体系抽象这一结构gif_schemas.cj 中Schema是基类GIFSchema整体帧集合 全局颜色表gct、ImageSchema图像描述符含局部颜色表lct与data_blocks是其子类各自重写parse(mStream, result, parent)与getTypeCode()。配套的四个顶层解析函数构成组合子框架parse(stream, loops, result, par)/parse(stream, schema, result, par)按子类数据处理流程解析流中数据conditional(schema, conditionFunc)条件判断——满足条件才按当前 Schema 逻辑处理loop(schema, continueFunc)循环处理continueFunc返回false时终止防止无限循环。parseGIF(byteData)见 gif_parse.cj就是这一框架的入口创建UInt8TypedArray(byteData, 0)与GIFSchema随后调用parse(stream, schema, schema, schema)完成整份数据的结构化解码。LZW 解压缩与隔行扫描重排GIF 图像数据采用 LZW 压缩编码。lzw(minCodeSize, data, pixelCount)实现于 lzw.cj按 GIF 规范维护prefix、suffix、pixelStack三张表栈上限 4096处理Clear Code、End of Information码动态扩展code_size最终输出长度恰为pixelCount的像素索引数组。对于隔行扫描Interlaced存储的 GIF解码后还需deinterlace(pixels, width)gif_parse.cj按offsets [0, 4, 2, 1]、steps [8, 8, 4, 2]的 4 遍扫描顺序把行数据重排回正常光栅顺序。帧结构与颜色表 → 可绘制数据decompressFrame(gceSchema, imageSchema, gct, buildImagePatch)将解析结果封装为GIFFrame结构定义见 gif_frame.cjdims帧的宽高与上、左边距Dims类pixels当前帧每个像素的颜色表查找索引colorTable本帧引用的颜色数组优先局部颜色表否则用全局颜色表3 个连续值表示一个颜色delay当前帧到下一帧的间隔时长由 GCE 字段gce_delay乘 10 得到gce_delay 0时按 100 兜底单位毫秒disposalType帧处置方式0 保留、1 不处置、2 恢复背景、3 恢复上一状态transparentIndex透明色索引patch颜色转换后的补片信息用于绘制。generatePatch(image, flagSwapRB!: Bool false)完成颜色表 索引到 RGBA 字节流的转换每个像素展开为 4 字节R、G、B 取自颜色表A 在像素索引等于transparentIndex时为 0否则为 255flagSwapRB可交换 R/B 通道以适应目标渲染格式。该流程在 gif_parse.cj 中有完整实现。parseBufferToFrame(arraybuffer, patchRule)是面向调用者的高层入口先解析为帧数组再通过patchRule让用户有机会对像素进行自定义处理如翻转、裁剪最后交给prePatchGIF生成可绘制的 patch 数据。软解码与硬解码两条路径在 controller_options.cj 中loadBuffer根据openHardware分流软解码默认userTaskPoolParse通过parseByTaskpool(buffer)即 gif_component.cj 封装的parseBufferToFrame在任务池中完成解码随后createPixelMapAll逐帧把patch数据通过createPixelMap(patchBuffer, initializationOptions)构建为PixelMap挂到frame.drawPixelMap上全部成功后回调readyRender(None)硬解码useHardwareParse使用系统createImageSource(buffer)DecodingOptions(sampleSize: 1, rotate: 0, editable: true)的createPixelMapList一次性产出全部PixelMap再通过getDelayTimeList()补齐每帧delay帧尺寸统一取首帧getImageInfo()的宽高。播放引擎速率、定位与回调GIFComponent的播放循环集中在renderFrames()gif_component.cj其工作机制是画一帧 → 按 delay 定时 → 画下一帧速率控制每帧停留时间stayTime由帧的delay与speedFactor计算——speedFactor 0时delay / speedFactor如 2 表示 2 倍速speedFactor 0时delay * |speedFactor|减速。实际定时器时长还会减去本次绘制耗时diff保证节奏准确循环回调播到最后一帧frameIndex frameLength - 1时触发model.getLoopFinish()(gifLoopDuration)参数为整轮播放耗时毫秒随后帧索引归零继续循环定点回调调用setPositionFinish(position, fn)后播到第position - 1帧时触发getPositionFinish()回调可用于帧级事件通知跳帧显示setSeekTo(gifPosition)让组件直接显示第 N 帧getSeekTo()返回当前定位。组件会暂停自动播放并逐帧绘制到目标帧保证非首帧数据不完整时画面依然正确见drawSeekToFrame。绘制阶段drawFrame→canvasDrawPixelMap根据上一帧的disposalType决定是否清空背景区域RESTOREBACKGROUND时清除对应区域随后按ScaleType设置画布变换再drawImage。ScaleType 拉伸类型一览ScaleType枚举定义在 gif_type.cj组件内对应 7 种独立绘制函数drawFIT_START等取值值行为描述FIT_START0图像位于组件左上角等比缩放至全部展示FIT_END1图像位于组件右下角等比缩放至全部展示FIT_CENTER2图像居中等比缩放至全部展示CENTER3图像绝对居中不缩放CENTER_CROP4短边缩放至组件大小长边超出部分裁剪FIT_XY5图像拉伸至组件大小不保持比例CENTER_INSIDE6图像大于组件时按 FIT_CENTER 缩放小于组件时按 CENTER 居中getTypeString()返回对应字符串fix_start、fix_center、center_crop等可用于日志与调试。配套的DisposalType枚举NOTHING/NOTRESOLVE/RESTOREBACKGROUND/PREVIOUSSTATUS取值 03对应 GIF 规范中的帧处置方式播放绘制时据此处理画布清除逻辑。关键 API 速查ControllerOptions 完整接口除上文使用过的接口外doc/feature_api.md 的动图播放章节还列出了以下能力getOpenHardware()/setOpenHardware(open: Bool)查询/设置硬解码开关返回ControllerOptions支持链式调用getFrames()/setFrames(images)获取/设置已解析的GIFFrame数组getLoopFinish()/setLoopFinish(fn)读取/设置整轮播放结束回调getPositionFinish()/setPositionFinish(position, fn)读取/设置指定帧位回调getPosition()获取当前设定帧位置getScaleType()/setScaleType(scaletype)、getSpeedFactor()/setSpeedFactor(speed)拉伸类型与播放速率getSeekTo()/setSeekTo(gifPosition)跳帧显示destroy()销毁配置——释放所有帧的PixelMap资源、清空帧数组并把各参数复位controller_options.cj页面退出时应调用以避免资源泄漏。文件工具类 FileUtilsfeature_api.md 的文件工具类章节给出了单例FileUtils.getInstance()下的文件能力createFile/createFileToID新建文件、deleteFile、copyFile/copyFileAsync异步拷贝、clearFile、writeData/writeDataAsync/writeNewFile/writeNewFileAsync写入其中writeNewFile覆盖式新建、exist、getFileSize、readFile/readFileAsync、createFolder(path, recursive!: Bool false)与existFolder。创建的File对象会默认打开使用完毕后需及时close否则会造成资源泄漏。网络下载数据源 Modelpublic class Model { public var url: String // 下载任务数据源路径 public var progressCallBack: ?((String) - Unit) None // 下载进度回调 [0%, 100%] public init() {} public init(url: String, progressCallBack!: Option(String) - Unit None) }MD5 与内部工具按需谨慎使用sparkmd5目录提供了SparkMD5与SparkMD5ArrayBufferappend/appendBinary/end(raw)/reset/getState/setState/destroy/ 静态hashSparkMD5、hashSparkMD5ArrayBuffer网络下载模块内部用它为 URL 生成缓存文件名。feature_api.md 明确指出encodeURIComponent、UnescapeBuffer等其他接口只在内部流程中使用无需调用者操作且可能随迭代修改实现请按需谨慎使用。命令行示例纯解析场景验证feature_api.md 的示例章节给出了一个不依赖 UI 的最小验证用例可直接在控制台运行以确认解码链路正确from std import fs.* from std import sync.* from gifdrawable4cj import gifdrawable4cj.* main (){ let filename: String ./dengdaitu.gif let byteData: ArrayUInt8 ResourceLoader.loadRawFile(filename) let gifs: ArrayGIFFrame parseBufferToFrame(byteData, None) println(gifs.size ${gifs.size}) return 0 }执行结果gifs.size 24示例说明对任意一个 24 帧的 GIF 文件loadRawFile读取字节后交给parseBufferToFrame即可得到 24 个GIFFrame帧对象验证字节流 → Schema → GIFFrame整条解码链工作正常。约束与限制README 说明本项目在以下版本组合下验证通过DevEco Studio 5.0.3 Release5.0.9.300Cangjie Support Plugin 5.0.9.100Cangjie Compiler0.53.18cjnative从 entry/src/main/cangjie/cjpm.toml 可以看到[package]中cjc-version 0.53.18与 README 标注一致构建目标覆盖aarch64-linux-ohos、x86_64-linux-ohos与x86_64-unknown-windows-gnu。若使用其他版本的工具链请以实际编译与运行结果为准。开源协议与参与贡献本项目基于 Apache License 2.0 开源可自由使用与参与贡献。欢迎提交 Pull Request 与 Issue或参与任何形式的贡献。赞分享OpenHarmonyUI组件图像处理【免费下载链接】gifdrawable4cj一个gif图像加载库项目地址https://gitcode.com/Cangjie-TPC/gifdrawable4cj点击查看免费下载相关推荐gifdrawable4cj v0.0.1 能力解析基于仓颉语言的 GIF 动图解码、播放控制与渲染实战指南gifdrawable4cj v0.0.1 能力解析基于仓颉语言的 GIF 动图解码、播放控制与渲染实战指南 gifdrawable4cj 是一个基于仓颉COpenHarmonyUI组件图像处理仓颉CangjieAPNG 动画解码渲染库 apng4cj接入配置、核心 API 与源码原理深度解析仓颉CangjieAPNG 动画解码渲染库 apng4cj接入配置、核心 API 与源码原理深度解析 本篇技术指南以开源仓库 apng4cj https:OpenHarmony图像处理仓颉图片处理库 image4cj 实战指南架构设计、JPEG/PNG/GIF 编解码与图像处理 API 全解析仓颉图片处理库 image4cj 实战指南架构设计、JPEG/PNG/GIF 编解码与图像处理 API 全解析 image4cj 是一个基于仓颉Cangji图像处理上一篇Megatron-LM终极指南如何用并行训练技术突破大模型训练瓶颈下一篇Jodit核心功能全解析从基础编辑到高级插件开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?