# ImageKnifeC **Repository Path**: zhong-luping/image-knife-c ## Basic Information - **Project Name**: ImageKnifeC - **Description**: ImageKnifeC是一个OpenHarmony/HarmonyOS图片加载缓存库 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 10 - **Created**: 2025-02-07 - **Last Updated**: 2025-05-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ImageKnifePro 专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单 ## 简介 ImageKnifePro是OpenHarmony上的一个图片加载缓存库,是[ImageKnife](https://gitcode.com/openharmony-tpc/ImageKnife)的C化实现,特点如下: * 支持自定义内存缓存策略,支持设置内存缓存的大小(默认LRU策略)。 * 支持磁盘二级缓存,对于下载图片会保存一份至磁盘当中。 * 支持自定义实现图片获取/网络下载 * 支持自定义解码 * 支持自定义文件缓存 * 支持监听网络下载回调进度 * 继承Image的能力,支持option传入border,设置边框,圆角 * 继承Image的能力,支持option传入objectFit设置图片缩放,包括objectFit为auto时根据图片自适应高度 * 并发请求数量,支持请求排队队列的优先级 * 支持生命周期已销毁的图片,不再发起请求 * 自定义缓存key生成策略 * 自定义http网络请求头 * 支持writeCacheStrategy控制缓存的存入策略(只存入内存或文件缓存,或不使用缓存) * 支持preLoad预加载图片 * 支持onlyRetrieveFromCache仅用缓存加载 待实现特性: * 默认解码支持图片降采样加载 * 支持使用一个或多个图片变换,如模糊,高亮等 * 支持通过设置transform缩放图片 相较ImageKnife ArkTs版本,主要体现在: - 提供ArkTs API和C API两种使用方式:既提供ArkTs组件方式给ArkTs原生应用使用,也提供Native组件的方式给RN等框架映射使用。 - 内置使用系统网络KIT CAPI下载和系统Image CAPI渲染,图片加载更快。 - (**目前仅提供capi自定义拓展**)支持通过拦截器的方式,自定义网络下载,解码,文件缓存,内存缓存。通过责任链-拦截器模式,图片加载任务可以同时应用多个自定义加载方式。 ## 下载安装 ```shell ohpm install @ohos/imageknifepro // 如果需要用文件缓存,需要提前初始化文件缓存 await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024) ``` ## 使用说明 ### 1.显示本地资源图片 ``` ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.app_icon"), placeholderSrc: $r("app.media.loading"), errorSrc: $r("app.media.app_icon"), objectFit: ImageFit.Auto } }).width(100).height(100) ``` ### 2.显示本地context files下文件 ``` ImageKnifeComponent({ ImageKnifeOption: { loadSrc: this.localFile, placeholderSrc: $r("app.media.loading"), errorSrc: $r("app.media.app_icon"), objectFit: ImageFit.Auto } }).width(100).height(100) ``` ### 3.显示网络图片 ``` ImageKnifeComponent({ ImageKnifeOption: { loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", placeholderSrc: $r("app.media.loading"), errorSrc: $r("app.media.app_icon"), objectFit: ImageFit.Auto } }).width(100).height(100) ``` ### 4.监听网络下载进度 ``` ImageKnifeComponent({ ImageKnifeOption: { loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)} } }).width(100).height(100) ``` ### 5.支持option传入border,设置边框,圆角 暂时实现了border width与radius的支持,设置的数据类型为number,**其他数据类型尚未实现暂不支持** **border color与style 尚未实现暂不支持** ``` ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), border: {radius:50} } }).width(100).height(100) ``` ### 6.监听图片加载成功与失败 ``` ImageKnifeComponent({ ImageKnifeOption: { loadSrc: $r("app.media.rabbit"), onLoadListener:{ onLoadStart:(imageInfo)=>{ this.starTime = new Date().getTime() console.info("Load start: "); }, onLoadFailed: (err, imageInfo) => { console.error("Load Failed Reason: " + err + " cost " + (new Date().getTime() - this.starTime) + " milliseconds"); }, onLoadSuccess: (imageInfo) => { console.info("Load Successful: cost " + (new Date().getTime() - this.starTime) + " milliseconds"); return data; }, onLoadCancel(reason, imageInfo){ console.info(reason) } } } }).width(100).height(100) ``` ### 7.同步加载ImageKnifeComponent - syncLoad 设置是否同步加载图片,默认是异步加载。建议只将加载尺寸较小的Resource图片时将syncLoad设为true,因为耗时较短,在主线程上执行亦可。 ``` ImageKnifeComponent({ imageKnifeOption:{ loadSrc:$r("app.media.pngSample"), placeholderSrc:$r("app.media.loading") },syncLoad:true }) ``` ### 8.动图组件ImageKnifeAnimatorComponent 示例 ``` ImageKnifeAnimatorComponent({ imageKnifeOption: { loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", placeholderSrc:$r('app.media.loading'), errorSrc:$r('app.media.failed') },animatorOption:this.animatorOption }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) ``` 可以通过`animatorOption`来控制动图的播放,暂停,播放次数,以及监听相应的事件。 ``` @State animatorOption: AnimatorOption = { state: AnimationStatus.Running, iterations: -1, onFinish: () => { LogUtil.info('ImageKnifeAnimatorComponent animatorOption onFinish') }, onStart: () => { LogUtil.info('ImageKnifeAnimatorComponent animatorOption onStart') }, onPause: () => { LogUtil.info('ImageKnifeAnimatorComponent animatorOption onPause') }, onCancel: () => { LogUtil.info('ImageKnifeAnimatorComponent animatorOption onCancel') }, onRepeat: () => { LogUtil.info('ImageKnifeAnimatorComponent animatorOption onRepeat') } } ``` ### 9.加载图片回调信息数据 示例 ``` ImageKnifeComponent({ ImageKnifeOption: = { loadSrc: $r('app.media.pngSample'), objectFit: ImageFit.Contain, onLoadListener: { onLoadStart: (imageInfo) => { let startCallBackData = JSON.stringify(imageInfo); }, onLoadFailed: (err, imageInfo) => { let failedBackData = err + ";" + JSON.stringify(imageInfo); }, onLoadSuccess: (imageInfo) => { let successBackData = JSON.stringify(imageInfo); }, onLoadCancel: (reason) => { let cancelBackData = reason + ";" + JSON.stringify(imageInfo); } }, border: { radius: 50 }, onComplete: (event) => { if (event && event.loadingStatus == 0) { let render_success = JSON.stringify(Date.now()) } } } }).width(100).height(100) ``` ### 10.图片降采样示例 ```shell ``` ### 11.自定义网络请求 **注意:因为无法在c++子线程里执行ArkTs自定义下载,缓存,图形变化等方法,所以目前只能在c++侧进行自定义实现** C侧实现的自定义网络拦截器请参考[示例](./library/src/main/cpp/README.md#c自定义图片下载). ### 复用场景 在aboutToRecycle生命周期清空组件内容;通过watch监听触发图片的加载。 ## 接口说明 ### ImageKnife组件 | 组件名称 | 入参内容 | 功能简介 | |-----------------------------|---------------------------------|--------| | ImageKnifeComponent | ImageKnifeOption | 图片显示组件 | | ImageKnifeAnimatorComponent | ImageKnifeOption、AnimatorOption | 动图控制组件 | ### AnimatorOption成员列表 | 成员名称 | 类型 | 功能简介 | |------------|-----------------|----------| | state | AnimationStatus | 播放状态(可选) | | iterations | number | 播放次数(可选) | | reverse | boolean | 播放顺序(可选) | | onStart | ()=>void | 动画开始播放时触发(可选) | | onFinish | ()=>void | 动画播放完成时或者停止播放时触发(可选) | | onPause | ()=>void | 动画暂停播放时触发(可选) | | onCancel | ()=>void | 动画返回最初状态时触发(可选) | | onRepeat | ()=>void | 动画重复播放时触发(可选) | ### ImageKnifeOption成员列表 | 成员名称 | 类型 | 功能简介 | |-----------------------|-----------------------------------------|-----------------| | loadSrc | string \| PixelMap \| Resource | 主图展示 | | placeholderSrc | string \| PixelMap \| Resource | 占位图图展示(可选) | | errorSrc | string \| PixelMap \| Resource | 错误图展示(可选) | | objectFit | ImageFit | 主图填充效果(可选) | | placeholderObjectFit | ImageFit | 占位图填充效果(可选) | | errorObjectFit | ImageFit | 错误图填充效果(可选) | | writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) | | onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) | | border | BorderOptions | 边框圆角(可选)(暂部分实现) | | priority | Priority | 加载优先级(可选) | | context | common.UIAbilityContext | 上下文(可选) | | progressListener | (progress: number)=>void | 下载回调进度(可选) | | signature | String | 自定义缓存关键字(可选) | | headerOption | Array | 设置请求头(可选) | | transformation | PixelMapTransformation | 图片变换(可选)(待实现) | | drawingColorFilter | (common2D.Color,drawing.BlendMode) | 图片变换(可选) | | onComplete | (event:EventImage \| undefined) => voi | 图片加载完成回调(可选) | | onLoadListener | OnLoadCallBack | 监听图片加载成功与失败 | | imageKnifeLoader | string | 监听图片加载成功与失败 | ### ImageInfo成员列表 | 成员名称 | 类型 | 功能简介 | |-------------|--------|-------------| | requestId | string | 图片加载请求的ID标识 | | imageWidth | number | 原始图片宽度 | | imageHeight | number | 原始图片高度 | | bufSize | number | 原始图片字节数 | | type | ImageFormat | 原始图片格式 | | httpCode | number | 网络请求状态码 | | frameCount | number | 图片帧数 | | decodeImages | Array | 解码后的图片信息 | | timeInfo | TimeInfo | 加载图片的各个时间点 | | errorInfo | ErrorInfo | 加载图片的错误信息 | ### ImageFormat枚举 | 枚举名称 | 值 | |------|---| |UNKNOWN| 0 | |JPG| 1 | |PNG| 2 | |WEBP| 3 | |BMP| 4 | |GIF| 5 | |SVG| 6 | |TIFF| 7 | |HEIC| 8 | |ICO| 9 | ### DecodeImageInfo成员列表 | 成员名称 | 类型 | 功能简介 | |-------------|--------|----------| | contentWidth | number | 解码后的图片宽度 | | contentHeight | number | 解码后的图片高度 | ### ErrorInfo成员列表 | 成员名称 | 类型 | 功能简介 | |-------------|--------|----------| | phase | string | 图片加载阶段信息 | | code | number | 错误码 | ### TimeInfo | 成员名称 | 类型 | 功能简介 | |-------------|--------|-----------------------| | executeTime | number | 请求创建完成,开始处理的时间 | | requestStartTime | number | 请求开始加载的时间 | | requestEndTime | number | 请求结束时间 | | requestCancelTime | number | 请求取消时间 | | memoryCheckStartTime | number | 内存缓存责任链读缓存任务开始时间 | | memoryCheckEndTime | number | 内存缓存责任链读缓存任务结束时间 | | diskCheckStartTime | number | 文件缓存责任链读缓存任务开始时间 | | diskCheckEndTime | number | 文件缓存责任链读缓存任务结束时间 | | loadImageStartTime | number | 图片加载责任链开始时间 | | loadImageEndTime | number | 图片加载责任链结束时间 | | decodeStartTime | number | 图片解码责任链开始时间 | | decodeEndTime | number | 图片解码责任链结束时间 | ### CacheStrategy枚举 | 枚举名称 | 值 | 说明 | |------|---|-----------| |DEFAULT| 0 | 使用内存和文件缓存 | |MEMORY| 1 | 只使用内存缓存 | |FILE| 2 | 只使用文件缓存 | |NONE| 3 | 不使用缓存 | ### ImageKnife接口 | 接口名称 | 入参内容 | 功能简介 | |----------------------|----------------------------------------------------------------------------------------------------------------------|--------------------------------------| | setMaxRequests | concurrency: number | 设置请求最大的并发数量 | | setCacheLimit | strategy: CacheStrategy, maxSize: number, maxUsage: number | 设置磁盘或者内存缓存的使用上限 | | initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 | | isFileCacheInit | | 判断文件缓存初始化是否完成 | | getCacheLimitSize | cacheStrategy?: CacheStrategy | 获取磁盘或者内存缓存上限 | | getCurrentCacheNum | cacheStrategy?: CacheStrategy | 获取磁盘或者内存缓存当前缓存的图片数量 | | getCurrentCacheSize | cacheStrategy?: CacheStrategy | 获取磁盘或者内存已用空间大小,获取内存使用量功能在相关系统接口上线后更新 | | removeMemoryCache | url: string \| ImageKnifeOption | 清理指定内存缓存 | | removeAllMemoryCache | | 清理所有磁盘缓存 | | removeMemoryCache | | 清理所有内存缓存 | | removeAllFileCache | url: string \| ImageKnifeOption | 清理指定磁盘缓存 | | preload | loadSrc: string \| ImageKnifeOption | 图片预加载 | | cancel | request: ImageKnifeRequest | 取消图片预加载 | | reaload | requestId: string | 重新加载请求 | | preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 | | getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature: string = "", animator: boolean = false | 从内存或文件缓存中获取资源 | | addHeader | key: string, value: Object | 全局添加http请求头 | | setHeaderOptions | Array | 全局设置http请求头 | | deleteHeader | key: string | 全局删除http请求头 | | putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 (待实现) | ### 回调接口说明 | 回调接口 | 回调字段 | 回调描述 | |--------------|--------------------------|------------------------------------------------------------------------------------------| |onLoadStart | imageInfo:ImageInfo | imageInfo返回字段中包含了图片请求的信息,详情参照**ImageInfo成员列表** | |onLoadSuccess | imageInfo:ImageInfo | imageInfo返回字段中包含了图片请求的信息,详情参照**ImageInfo成员列表** | |onLoadFailed | err: string, imageInfo: ImageInfo | err:错误信息描述;imageInfo返回字段中包含了图片请求的信息,详情参照**ImageInfo成员列表** | |onLoadCancel | reason: string, imageInfo: ImageInfo | reason:取消回调原因;imageInfo返回字段中包含了图片请求的信息,详情参照**ImageInfo成员列表** | ### 图形变换类型 | 类型 | 相关描述 | |-----------------------------|----------------------------| | BlurTransformation | 模糊处理 | | BrightnessTransformation | 亮度滤波器 | | CropSquareTransformation | 正方形剪裁 | | CropTransformation | 自定义矩形剪裁 | | GrayScaleTransformation | 灰度级滤波器 | | InvertTransformation | 反转滤波器 | | KuwaharaTransformation | 桑原滤波器 | | MaskTransformation | 遮罩 | | PixelationTransformation | 像素化滤波器 | | SepiaTransformation | 乌墨色滤波器 | | SketchTransformation | 素描滤波器 | | SwirlTransformation | 扭曲滤波器 | | ToonTransformation | 动画滤波器 | | VignetterTransformation | 装饰滤波器 | ## 与ImageKnife3.x特性对比 #### ImageKnifeOption | 属性 | ImageKnife3.x(js api) | ImageKnifePro(js api) | ImageKnifePro(c api) | |-----------|---------------------------------------------------|--------------------------------|-------------| | 主图 | loadSrc:string, PixelMap, Resource | 一致 | | | 占位图 | placeholderSrc?: string,PixelMap,Resource | 一致 | | | 错误图 | errorholderSrc?: string,PixelMap,Resource | errorSrc?: string,PixelMap,Resource | | | http请求头 | headerOption?: Array | 一致(待实现) | | | 自定义关键字 | signature?: string | 一致 | | | 主图缩放效果 | objectFit?: ImageFit | 一致 | | | 占位图缩放效果 | placeholderObjectFit?: ImageFit | 一致 | | | 错误图缩放效果 | errorholderObjectFit?: ImageFit | errorObjectFit?: ImageFit | | | 自定义下载方法 | customGetImage:function | 不一致,成员移除 | 拦截器实现 | | 圆角边框 | border?: BorderOptions | 一致(暂实现了number类型的radius与border width) | | | 写缓存策略 | writeCacheStrategy?: CacheStrategy | 一致 | | | 仅使用缓存加载 | onlyRetrieveFromCache?: boolean | 一致 | | | 请求优先级 | priority?: taskpool.Priority | priority?: Priority | | | 页面上下文 | context?: common.UIAbilityContext | 一致 | 使用C API 无效 | | 下载进度监听 | progressListener?: (progress: number) => void | 一致,但有跨线程延迟 | | | 图形变化 | transformation?: PixelMapTransformation | 不一致(待C侧实现) | | | 请求回调 | onLoadListener?: OnLoadCallBack \| undefined | 不一致,内部回调函数使用ImageInfo入参 | | | 渲染完成回调 | onComplete?:(event:EventImage,undefined) => void | 一致 | | | 颜色修改 | drawingColorFilter?: (common2D.Color,drawing.BlendMode) | 不一致 | | | 降采样策略 | downsampleOf?: DownsampleStrategy | 一致(待实现) | | | http ca证书 | caPath?: string | 一致(待实现) | | #### ImageKnife全局方法 | 方法 | ImageKnife3.x(js api) | ImageKnifePro(js api) | ImageKnifePro(c api) | | --------------------- |----------------------------------------------------------------------------------------------------------------------|----------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | 初始化文件缓存 | InitFileCache(context: Context, size: number = 256, memory: number = 256 * 1024 * 1024,path?: string) | 一致 | InitFileCacheAsync(std::string cachePath, size_t size, size_t memory, std::string path) | | 判断文件缓存是否已完成初始化 | isFileCacheInit(): boolean | 一致 | bool IsFileCacheInit() | | 重新加载 | reload(request: ImageKnifeRequest) | reload(requestId: string) | void reload(std::string requestId) | | 全局添加单个请求头header | addHeader(key: string, value: Object) | 一致 | void AddHeader(std::string, std::string) | | 全局设置请求头header | setHeaderOptions(options) | 一致 | 使用AddHeader接口 | | 删除单个请求头header | deleteHeader(key: string) | 一致 | void DeleteHeader(std::string key) | | 设置自定义的内存缓存 | initMemoryCache(newMemoryCache: IMemoryCache) | 不一致(拦截器实现) | | | 预加载 | preload(loadSrc:string \| ImageKnifeOption) | 一致 | std::shared_ptr Preload(std::shared_ptr imageKnifeOption) | | 取消图片请求 | Cancel(request:ImageKnifeRequest) | 一致 | Cancel(std::shared_ptr request) | | 预加载图片到文件缓存,返回文件路径 | preLoadCache(loadSrc: string \| ImageKnifeOption) | 一致 | std::shared_future PreloadCache(std::shared_ptr option) | | 从内存或文件缓存中获取图片数据 | getCacheImage(loadSrc: string,cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature: string = "", animator: boolean = false) | std::shared_future> GetCacheImage(std::string loadSrc, CacheStrategy cacheType = CacheStrategy::DEFAULT, std::string signature = "", bool animator = false) | | 预加载缓存(用于外部已获取pixelmap,需要加入imageknife缓存的场景) | PutCacheImage(url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 一致(待确认) | | | 清除所有文件缓存 | removeAllFileCache() | 一致 | RemoveAllFileAsync(void) | | 清除指定文件缓存 | removeFileCache(url: string \| ImageKnifeOption) | 一致 | RemoveFileAsync(std::string &url),RemoveFileAsync(std::shared_ptr option) | | 清除所有内存缓存 | removeAllMemoryCache() | 一致 | RemoveAllMemoryCache() | | 清除指定内存缓存 | removeMemoryCache(url: string \| ImageKnifeOption) | 一致 | RemoveMemoryCache(std::string url),RemoveMemoryCache(std::shared_ptr imageKnifeOption) | | 设置请求并发数量 | setMaxRequests(concurrency: number) | 一致 | SetMaxRequests(int concurrency) | | 获取缓存限制的大小 | getCacheLimitSize(cacheType?: CacheStrategy) | 一致 | GetCacheLimitSize(CacheStrategy cacheStrategy) | | 获取缓存限制的数量 | getCurrentCacheNum(cacheType: CacheStrategy) | 一致 | GetCurrentCacheNum(CacheStrategy cacheStrategy) | | 获取当前缓存大小 | getCurrentCacheSize(cacheType: CacheStrategy) | 一致 | GetCurrentCacheSize(CacheStrategy cacheStrategy) | | 自定义缓存key生成方法 | SetEngineKeyImpl(impl: IEngineKey) | 不一致 | SetCacheKeyGenerator(CacheKeyGenerator *keyPtr) | | 全局设置自定义下载 | setCustomGetImage(...) | 不一致 | 拦截器实现 | | 全局获取自定义下载 | getCustomGetImage() | 不一致 | 拦截器实现 | #### 其它属性 | 属性 | ImageKnife3.x(js api) | ImageKnifePro(js api) |ImageKnifePro(c api) | | --------------------- | ----------------------------------------------------- | ------------------------------ |------------------------------ | | 同步加载 | syncLoad: boolean | 一致 | | | 动图控制及回调 | animatorOption: AnimatorOption | 一致 | | | 放大缩小等组件缩放 | Transform(matrix:object) | 一致(待实现) | | | 组件自适应图片宽高 | ImageFit.Auto | 一致 | | ### C化代码使用说明 请参照[imageknifepro C化使用说明](./library/src/main/cpp/README.md) ## 约束与限制 在以下版本验证通过: - DevEco Studio:5.0.5.315;SDK:5.0.1(API 13) ## 关于混淆 - 代码混淆,请查看[代码混淆简介](https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/arkts-utils/source-obfuscation.md) - 如果希望imageknifepro库在代码混淆过程中不会被混淆,需要在混淆规则配置文件obfuscation-rules.txt中添加相应的排除规则: ```shell -keep ./oh_modules/@ohos/imageknifepro ``` ## Benchmark 待测试比较imageknife3.x,imageknifepro,系统image,安卓fresco/glide 加载图片速度和白块率。 ## 开源协议 本项目基于 [Apache License 2.0](https://gitee.com/openharmony-tpc/ImageKnife/blob/master/LICENSE) ,请自由的享受和参与开源。