diff --git a/OAT.xml b/OAT.xml index f591c15689c4290b40f19e44855dfb7ea1dedc74..b24cb10361f245fe64cc9c218058c56e04bc82fe 100644 --- a/OAT.xml +++ b/OAT.xml @@ -1638,6 +1638,23 @@ Note:If the text contains special characters, please escape them according to th + + + + + + + + + + + + + + + + + diff --git a/code/UI/DecodeHEIFImage/.gitignore b/code/UI/DecodeHEIFImage/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..08d606210b3993e8f1f4535767bb3459b7b1d208 --- /dev/null +++ b/code/UI/DecodeHEIFImage/.gitignore @@ -0,0 +1,13 @@ +/node_modules +/oh_modules +/local.properties +/.idea +**/build +/.hvigor +.cxx +/.clangd +/.clang-format +/.clang-tidy +**/.test +/.appanalyzer +/oh-package-lock.json5 \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/AppScope/app.json5 b/code/UI/DecodeHEIFImage/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..675d85d508cf2eb660567801ca5e099b9e25bba4 --- /dev/null +++ b/code/UI/DecodeHEIFImage/AppScope/app.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "bundleName": "com.samples.decodeheifimage", + "vendor": "sample", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:app_icon", + "label": "$string:app_name" + } +} diff --git a/code/UI/DecodeHEIFImage/AppScope/resources/base/element/string.json b/code/UI/DecodeHEIFImage/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..4cce5d489ce585e025d5abd070208bd8b4dd0feb --- /dev/null +++ b/code/UI/DecodeHEIFImage/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "DecodeHEIFImage" + } + ] +} diff --git a/code/UI/DecodeHEIFImage/AppScope/resources/base/media/app_icon.png b/code/UI/DecodeHEIFImage/AppScope/resources/base/media/app_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..a39445dc87828b76fed6d2ec470dd455c45319e3 Binary files /dev/null and b/code/UI/DecodeHEIFImage/AppScope/resources/base/media/app_icon.png differ diff --git a/code/UI/DecodeHEIFImage/README.md b/code/UI/DecodeHEIFImage/README.md new file mode 100644 index 0000000000000000000000000000000000000000..4a61f64f001ea4ac18996aea23951a1ad22ab218 --- /dev/null +++ b/code/UI/DecodeHEIFImage/README.md @@ -0,0 +1,239 @@ +# HEIF软解码器案例 + +### 介绍 + +高效图像文件格式HEIF(High Efficiency Image File Format)具有更高的图像质量,更高效的压缩算法,在应用中大量使用,有些应用静态图90%以上都是HEIF图片(.heic后缀)。本示例介绍将[libheif](https://github.com/strukturag/libheif)编译移植到鸿蒙平台,通过网络库[curl](https://curl.se/)请求HEIF图片资源、libheif软解码HEIF图片,最后在瀑布流中加载解码后的HEIF图片的过程。本案例HEIF软解码方案可供开发者调试,硬解码不支持的设备也可以使用软解码方案。 + +### 效果图预览 + +![decode_heif_image](./decodeheifimage/src/main/resources/base/media/decode_heif_image.gif) + +进入本案例首页,开始加载HEIF网络图片的过程:在Taskpool子线程中,通过libcurl网络请求HEIF图片资源,然后通过libheif软解码出HEIF图片数据,调用OH_PixelMap_CreatePixelMap将HEIF图片数据转为PixelMap,主线程获取图片软解码结果后在WaterFlow中加载所有HEIF图片。 +### 实现思路 + +对于jpg、png和jpeg等系统支持硬解码的图片格式,开发者使用imageSource即可直接解码,创建PixelMap对象后,可以给上层UI组件展示。理论上,对于.heic这类系统暂不支持的图片格式,需要移植自定义解码器(二方库或者三四方库)到鸿蒙平台,然后调用解码器接口解码出原始像素数据,进行字节对齐、颜色变换等操作后,调用NDK的OH_PixelMap_CreatePixelMap函数即可创建PixelMap,给上层UI组件展示。 + +### 实现方案 + +#### 1.libheif移植 + +本文在Linux平台上编译libheif,下载sdk-linux并配置好环境变量,然后按照文档[libheif 集成到应用hap](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/thirdparty/libheif/docs/hap_integrate.md#libheif-%E9%9B%86%E6%88%90%E5%88%B0%E5%BA%94%E7%94%A8hap)的流程进行即可。 + +**注意事项** + +根据[libheif github源工程](https://github.com/strukturag/libheif),libheif解码依赖libde265/ffmpeg,所以还需要集成libd265/ffmpeg。 + +img + +libd265移植参考[ libde265 集成到应用hap](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/thirdparty/libde265/docs/hap_integrate.md), libde265文件夹与libheif保持同级目录。 + +修改thirdparty/libheif/HPKBUILD构建脚本,添加libde265依赖,libde265的编译选项由disable改为enable,这样就可以在libheif编译时链接到libde265。 + +img + +img + +最后编译成功的产物可在/lycium/usr下获取,可以看到thirdparty/libheif/HPKBUILD依赖的库都成功编译了,并且查看libheif.so的属性,运行时会依赖libde265.so。 + +img + +img + +#### 2.使用curl网络请求HEIF图片 + +本案例将[网络库curl集成到hap](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/thirdparty/curl/docs/hap_integrate.md),这样在Native侧就可以直接请求到HEIF图片,并在Native侧解码,减少跨语言调用开销。 + +#### 3.读取HEIF图片 + +libheif允许开发者从不同的来源(磁盘文件、内存、自定义Reader)读取HEIF图片文件,并将其加载到heif_context中,以便后续操作和处理HEIF内容。 + +本案例以`heif_context_read_from_memory_without_copy`读取网络请求到的HEIF图片(已在内存中)为例。 + +```c++ +// 创建HEIF上下文指针 +heif_context *ctx = heif_context_alloc(); + +/** +功能:从指定的磁盘文件中读取HEIF文件。 +参数: +struct heif_context*:指向HEIF上下文的指针,用于存储和管理HEIF文件的解码和处理信息。 +const char* filename:指向包含HEIF文件名的字符串的指针。 +const struct heif_reading_options*:指向读取选项的指针。目前应该设置为NULL,表示没有特殊的读取选项。 +*/ +struct heif_error heif_context_read_from_file(struct heif_context*, const char* filename, + const struct heif_reading_options*); + +/** +功能:从内存中读取HEIF文件,但提供的内存不会被复制。这意味着,只要使用heif_context,就必须保持内存区域有效。 +参数: +struct heif_context*:同上。 +const void* mem:指向存储HEIF文件数据的内存块的指针。 +size_t size:内存块的大小,以字节为单位。 +const struct heif_reading_options*:读取选项,同上。 +*/ +struct heif_error heif_context_read_from_memory_without_copy(struct heif_context*, + const void* mem, size_t size, + const struct heif_reading_options*); +/** +功能:从自定义的struct heif_reader(如网络流、加密文件等)中读取HEIF文件。 +参数: +struct heif_context*:同上。 +const struct heif_reader* reader:指向实现了特定读取函数的heif_reader结构的指针。 +void* userdata:传递给reader回调的用户定义数据。 +const struct heif_reading_options*:读取选项,同上 +*/ +struct heif_error heif_context_read_from_reader(struct heif_context*, + const struct heif_reader* reader, + void* userdata, + const struct heif_reading_options*); +``` + +#### 4.解码HEIF图片 + +解码函数(heif_decode_image)的主要作用是将HEIF图片处理句柄(heif_image_handle)解码为实际的像素图像,并可以设置colorspace和chroma参数来指定输出图像的色彩空间和色度采样方式,如果不需要更改,可以保持为默认值,解码选项参数option可以设置解码后的质量、缩放等。 + +目前OH_PixelMap_CreatePixelMap颜色编码格式只支持BGRA_8888,但是heif_decode_image不支持该颜色编码格式,所以本案例指定HEIF图片的编码格式为BGRA。 + +```cpp +// 获取主图像句柄 +heif_image_handle *handle; +heif_context_get_primary_image_handle(ctx, &handle); +// 从句柄中解码图像 +heif_image *heif_img; +heif_decode_image(handle, &heif_img, heif_colorspace_RGB, heif_chroma_interleaved_RGBA, nullptr); +``` + +#### 5.创建PixelMap + +##### 访问heif图像 + +```cpp +// 获取图像数据 +int stride; +uint8_t *data = heif_image_get_plane_readonly(heif_img, heif_channel_interleaved, &stride); +``` + +>在访问heif图像数据时,需要考虑stride,表示图像中每行像素数据在内存中所占的字节数。通常,图像数据在内存中是连续存储的,但是由于内存对齐等因素,每行的字节数可能会大于实际图像的实际宽度,即stride > width * bpp,width是图片的宽度,bpp(bytes per pixel)是每像素的字节数。 + +##### 字节对齐 + +RGBA格式下,如果stride > width * bpp,即每行的字节数可能会大于图像的实际宽度,此时需要字节对齐,参考如下代码。 + +```c++ +const size_t bpp = 4; // 颜色格式为BGRA,每个像素4个字节 +const size_t pixel_count = width * height; // 像素总数 +const size_t row_bytes = width * bpp; // 每一行的字节数,每个像素4个字节 +const size_t total_size = pixel_count * bpp; // 计算平面的总数据大小 + +uint8_t *new_data = data; // 默认指向原数据 +bool needAlignment = stride != row_bytes; // 是否需要字节对齐 +if (needAlignment) { + new_data = new uint8_t[total_size]; + // 字节对齐 + for (int row = 0; row < height; row++) { + memcpy(new_data + row * row_bytes, data + row * stride, row_bytes); + } +} +``` + +##### 颜色编码格式变换 + +目前OH_PixelMap_CreatePixelMap颜色编码格式只支持BGRA(API12开始会新增),而HEIF的颜色格式为RGBA,所以需要将RGBA转换为BGRA。 + +```c++ +// 定义颜色编码格式转换函数 +void swapRBChannels(uint8_t *pixels, int pixelCount) { + for (int i = 0; i < pixelCount; i++) { + std::swap(pixels[i * 4], pixels[i * 4 + 2]); + } +} +``` + +##### 创建PixelMap + +定义HEIF的宽高、颜色编码格式,调用NDK的OH_PixelMap_CreatePixelMap函数即可创建PixelMap。 + +```c++ +struct OhosPixelMapCreateOps createOps; +createOps.width = width; +createOps.height = height; +createOps.pixelFormat = 4; // BGRA +createOps.alphaType = 0; + +int32_t res = OH_PixelMap_CreatePixelMap(env, createOps, (void *)new_data, total_size, &pixel_map); +if (res != IMAGE_RESULT_SUCCESS || pixel_map == nullptr) { + OH_LOG_ERROR(LOG_APP, "创建pixelMap错误"); + return nullptr; +} +``` + +### 高性能知识点 + +1. 本示例使用了LazyForEach进行数据懒加载,WaterFlow布局时会根据可视区域按需创建FlowItem组件,并在FlowItem滑出可视区域外时销毁以降低内存占用。 +2. 本案例的图片软解码使用Taskpool来实现多线程并发能力,提升系统资源利用率,减少主线程负载,加快应用的启动速度和响应速度。 + +### 工程结构&模块类型 + +```txt +​``` +decodeheifimage // har类型 +|---libs\ +| |---arm64-v8a\libde265.so // arm64-v8a类型libde265库 +| |---arm64-v8a\libheif.so.1 // arm64-v8a类型libheif库 +| |---arm64-v8a\libnativedownloadheif.so // arm64-v8a类型基于libcurl的网络请求so +| |---arm64-v8a\libnativedecodeheif.so // arm64-v8a类型基于libheif的HEIF解码so +|---src\main\ets\components\ +| |---ReusableFlowItem.ets // 公共组件-瀑布流FlowItem组件 +|---src\main\ets\model\ // 模型层 +| |---WaterFlowData.ets // 瀑布流数据和操作类 +| |---TaskPool.ets // TaskPool子线程加载so库 +|---src\main\ets\ +| |---DecodeHEIFImageView.ets // 主页面 +|---src\main\cpp\ +| |--- CMakeLists.txt // C++编译和链接配置成 +| |--- decode_heif_image.cpp // 基于libheif的HEIF软解码实现 +| |--- download_heif_image.cpp // 基于libcurl的网络请求实现 +| |--- napi_init.cpp // native层HEIF软解码实现 +​``` +``` + +### 模块依赖 + +1. 依赖公共libs库中的[libcurl.so](./decodeheifimage/libs/arm64-v8a/libcurl.so),进行Native侧的网络请求HEIF图片资源。 + +### 参考资料 + +[高效并发编程](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/performance/efficient-concurrent-programming.md#/openharmony/docs/blob/master/zh-cn/application-dev/arkts-utils/cpu-intensive-task-development.md) + +[WaterFlow+LazyForEach详细用法可参考性能范例](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/performance/waterflow_optimization.md) + +[libheif github源工程](https://github.com/strukturag/libheif) + +[libheif 集成到应用hap](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/thirdparty/libheif/docs/hap_integrate.md#libheif-%E9%9B%86%E6%88%90%E5%88%B0%E5%BA%94%E7%94%A8hap) + +[libde265 集成到应用hap](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/thirdparty/libde265/docs/hap_integrate.md) + +[网络库curl集成到hap](https://gitee.com/openharmony-sig/tpc_c_cplusplus/blob/master/thirdparty/curl/docs/hap_integrate.md) + +### 相关权限 + +不涉及 + +### 约束与限制 + +1.本示例仅支持在标准系统上运行,支持设备:Phone。 + +2.本示例为Stage模型,支持API12版本SDK,SDK版本号(API Version 12 Release)。 + +3.本示例需要使用DevEco Studio 5.0.0 Release 才可编译运行。 + +### 下载 + +如需单独下载本工程,执行如下命令: +```javascript +git init +git config core.sparsecheckout true +echo code/UI/DecodeHEIFImage/ > .git/info/sparse-checkout +git remote add origin https://gitee.com/openharmony/applications_app_samples.git +git pull origin master +``` \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/build-profile.json5 b/code/UI/DecodeHEIFImage/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ccf80bde66d9150e6aee8fece6d6aa9af82b8c3b --- /dev/null +++ b/code/UI/DecodeHEIFImage/build-profile.json5 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "compatibleSdkVersion": 12, + "compileSdkVersion": 12, + "runtimeOS": "OpenHarmony", + "buildOption": { + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + }, + { + "name": "decodeheifimage", + "srcPath": "./decodeheifimage" + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/code-linter.json5 b/code/UI/DecodeHEIFImage/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..28586467ee7a761c737d8654a73aed6fddbc3c71 --- /dev/null +++ b/code/UI/DecodeHEIFImage/code-linter.json5 @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "files": [ + "**/*.ets" + ], + "ignore": [ + "**/src/ohosTest/**/*", + "**/src/test/**/*", + "**/src/mock/**/*", + "**/node_modules/**/*", + "**/oh_modules/**/*", + "**/build/**/*", + "**/.preview/**/*" + ], + "ruleSet": [ + "plugin:@performance/recommended", + "plugin:@typescript-eslint/recommended" + ], + "rules": { + } +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/.gitignore b/code/UI/DecodeHEIFImage/decodeheifimage/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..eadab4e1522296628f32a70228b2c758ecab4759 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/.gitignore @@ -0,0 +1,7 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test +/oh-package-lock.json5 \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/Index.ets b/code/UI/DecodeHEIFImage/decodeheifimage/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..8b97c5844c9f9a57c09e787b0dd2c165fca5b8dc --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/Index.ets @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export { DecodeHEIFImageView } from './src/main/ets/DecodeHEIFImageView'; diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/build-profile.json5 b/code/UI/DecodeHEIFImage/decodeheifimage/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c1fa46c55738ee34f48d4227b66acdc1d49079ca --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/build-profile.json5 @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "abiFilters": [ + "arm64-v8a" + ], + "arguments": "", + "cppFlags": "-s" + }, + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": true, + "files": [ + "./obfuscation-rules.txt" + ] + }, + "consumerFiles": [ + "./consumer-rules.txt" + ] + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [], + }, + } + }, + ], + "targets": [ + { + "name": "default" + } + ] +} diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/consumer-rules.txt b/code/UI/DecodeHEIFImage/decodeheifimage/consumer-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/hvigorfile.ts b/code/UI/DecodeHEIFImage/decodeheifimage/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..0785a511e1f806573e5208d382645d48719a0f06 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { harTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: harTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libcurl.so b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libcurl.so new file mode 100644 index 0000000000000000000000000000000000000000..a142c9eff002cd215988cd5a47507ead80262fdb --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libcurl.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:68513537d89347706a4f55a31a3139be3cdf09e110bb79fb7a1d3ceec8a6200d +size 1205712 diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libde265.so b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libde265.so new file mode 100644 index 0000000000000000000000000000000000000000..aab6fbaaa0ac32001cec496583992d7f751b5c4d --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libde265.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:923151aaafa7700dccdd77543b215306b2e63e5ffef453abe1dc7ad8d176a8d7 +size 911840 diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libheif.so.1 b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libheif.so.1 new file mode 100644 index 0000000000000000000000000000000000000000..d18105aba60cb6d2f593983e8da47603689233e3 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libheif.so.1 differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libnativedecodeheif.so b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libnativedecodeheif.so new file mode 100644 index 0000000000000000000000000000000000000000..700fad26048b8d22d845b1bdde65f5131690b4aa --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libnativedecodeheif.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4b1430e08775527e493009496cf4cd6e1618645b2d14ee827890ae8e57236e66 +size 50768 diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libnativedownloadheif.so b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libnativedownloadheif.so new file mode 100644 index 0000000000000000000000000000000000000000..995694fc4151d508b9f6477516dcca25a10e825e --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/libs/arm64-v8a/libnativedownloadheif.so @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3d2ac4e64235fcf5a9715d3fcf4345dd9ef742f24fd77ae4f091eea969756185 +size 49544 diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/obfuscation-rules.txt b/code/UI/DecodeHEIFImage/decodeheifimage/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/oh-package.json5 b/code/UI/DecodeHEIFImage/decodeheifimage/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..a026549463d92216294379a3e580843d868cf006 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/oh-package.json5 @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "decodeheifimage", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "Index.ets", + "author": "", + "license": "Apache-2.0", + "dependencies": { + "libdecodeheifimage.so": "file:./src/main/cpp/types/libdecodeheifimage" + } +} diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/CMakeLists.txt b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3c2d3e1d7ac6906a353474c1f9d7ae7350f24984 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/CMakeLists.txt @@ -0,0 +1,50 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.4.1) + +project(decodeheifimage) + +set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}) + +if(DEFINED PACKAGE_FIND_FILE) + include(${PACKAGE_FIND_FILE}) +endif() + +include_directories(${NATIVERENDER_ROOT_PATH} + ${NATIVERENDER_ROOT_PATH}/include) + +# TODO:知识点:定义一个变量 BUILD_FLAG_SO +# TODO:知识点:BUILD_FLAG_SO为0时生成封装基于libcurl的HEIF图片网络请求库libnativedownloadheif.so,将生成好的so文件放入根目录的libs目录下,供native接口调用。 +# TODO:知识点:BUILD_FLAG_SO为1时生成封装基于libheif的HEIF图片软解码库libnativedecodeheif.so,将生成好的so文件放入根目录的libs目录下,供native接口调用。 +# TODO:知识点:BUILD_FLAG_SO为2时,生成一个包含native侧的HEIF图片软解码接口decodeHeifImageFromInternet(该接口调用libnativedownloadheif.so和libnativedecodeheif.so导出的网络请求和软解码接口进行HEIF图片软解码)的库,接口decodeHeifImageFromInternet供ArkTS侧调用。 +set(BUILD_FLAG_SO 2) + +if(BUILD_FLAG_SO EQUAL 0) + # 生成封装libcurl库的libnativedownloadheif.so + add_library(nativedownloadheif SHARED download_heif_image.cpp) + + # 配置动态链接,将libcurl.so加入工程中 + target_link_libraries(nativedownloadheif PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../libs/${OHOS_ARCH}/libcurl.so) + # 将libcurl的头文件加入工程中 + target_include_directories(nativedownloadheif PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/curl/${OHOS_ARCH}/include) + target_include_directories(nativedownloadheif PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + # 导入napi、ndk相关库 + target_link_libraries(nativedownloadheif PUBLIC libace_napi.z.so libhilog_ndk.z.so) +elseif(BUILD_FLAG_SO EQUAL 1) + # 生成封装libheif库的libnativedecodeheif.so + add_library(nativedecodeheif SHARED decode_heif_image.cpp) + # 配置动态链接,将libheif.so加入工程中 + target_link_libraries(nativedecodeheif PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libheif/${OHOS_ARCH}/lib/libheif.so) + # 将libheif的头文件加入工程中 + target_include_directories(nativedecodeheif PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/libheif/${OHOS_ARCH}/include) + target_include_directories(nativedecodeheif PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + # 导入napi、ndk相关库 + target_link_libraries(nativedecodeheif PUBLIC libace_napi.z.so libhilog_ndk.z.so) +else() + # 生成native侧库,供ArkTS侧调用 + add_library(decodeheifimage SHARED napi_init.cpp) + # 导入引用的库路径 + target_link_directories(decodeheifimage PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/${OHOS_ARCH}/) + target_include_directories(decodeheifimage PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include) + # 导入napi、ndk相关库及libnativedownloadheif.so和libnativedecodeheif解码库 + target_link_libraries(decodeheifimage PUBLIC libace_napi.z.so libhilog_ndk.z.so libpixelmap_ndk.z.so libnativedownloadheif.so libnativedecodeheif.so) +endif() diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/decode_heif_image.cpp b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/decode_heif_image.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5831743c7c580303504a3310c71254392ad7ca69 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/decode_heif_image.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "decode_heif_image.h" +#include +#include +#include "common.h" +#include + +extern "C" { +#include "libheif/heif.h" + +DecodeHEIFImage::DecodeHEIFImage() {} // 构造函数 +DecodeHEIFImage::~DecodeHEIFImage() {} // 析构函数 + + +// 定义颜色编码格式转换函数 +void DecodeHEIFImage::swapRBChannels(uint8_t *pixels, int pixelCount) { + for (int i = 0; i < pixelCount; i++) { + std::swap(pixels[i * 4], pixels[i * 4 + 2]); + } +} + +DecodeResult *DecodeHEIFImage::decode_heif_image(MemoryStruct chunk) { + + OH_LOG_INFO(LOG_APP, "开始HEIF解码,chunk size: %{public}d", chunk.size); + // 创建 heif_context + struct heif_context *ctx = heif_context_alloc(); + if (!ctx) { + OH_LOG_ERROR(LOG_APP, "分配 heif_context 失败"); + return nullptr; + } + OH_LOG_INFO(LOG_APP, "开始从内存中读取 HEIC 图像"); + // 从内存中读取 HEIC 图像 + heif_error err = heif_context_read_from_memory_without_copy(ctx, chunk.memory, chunk.size, nullptr); + + if (err.code != heif_error_Ok) { + OH_LOG_ERROR(LOG_APP, "读取 heif 图片错误: %{public}s", err.message); + heif_context_free(ctx); + return nullptr; + } + OH_LOG_INFO(LOG_APP, "开始HEIC 图像句柄"); + + // 获取主图像句柄 + heif_image_handle *handle; + err = heif_context_get_primary_image_handle(ctx, &handle); + + if (err.code != heif_error_Ok) { + OH_LOG_ERROR(LOG_APP, "获取主图像句柄错误: %{public}s", err.message); + heif_image_handle_release(handle); + heif_context_free(ctx); + return nullptr; + } + OH_LOG_INFO(LOG_APP, "开始解码HEIC 图像"); + + // 从句柄中解码图像 + heif_image *heif_img; + err = heif_decode_image(handle, &heif_img, heif_colorspace_RGB, heif_chroma_interleaved_RGBA, nullptr); + + if (err.code != heif_error_Ok) { + OH_LOG_ERROR(LOG_APP, "从句柄中解码图像错误: %{public}s", err.message); + heif_image_handle_release(handle); + heif_context_free(ctx); + return nullptr; + } + + // 获取图像尺寸 + int width, height; + + width = heif_image_get_width(heif_img, heif_channel_interleaved); + height = heif_image_get_height(heif_img, heif_channel_interleaved); + OH_LOG_INFO(LOG_APP, "HEIC 图像 width: %{public}d height: %{public}d", width, height); + // 获取图像数据 + int stride; + OH_LOG_INFO(LOG_APP, "开始解码HEIC 图像data"); + uint8_t *data = heif_image_get_plane_readonly(heif_img, heif_channel_interleaved, &stride); + if (data == nullptr) { + OH_LOG_ERROR(LOG_APP, "读取到的图像数据为空"); + if (heif_img != nullptr) { + heif_image_release(heif_img); + heif_img = nullptr; + } + if (handle != nullptr) { + heif_image_handle_release(handle); + handle = nullptr; + } + if (ctx != nullptr) { + heif_context_free(ctx); + ctx = nullptr; + } + return nullptr; + } + + + if (!data) { + OH_LOG_ERROR(LOG_APP, "解码失败或图像数据为空"); + return nullptr; + } + + const size_t bpp = 4; + const size_t pixel_count = width * height; // 像素总数 + const size_t row_bytes = width * bpp; // 每一行的字节数,每个像素4个字节 + const size_t total_size = pixel_count * bpp; // 计算平面的总数据大小 + + uint8_t *new_data = data; // 默认指向原数据 + bool needAlignment = stride != row_bytes; // 是否需要字节对齐 + if (needAlignment) { + new_data = new (std::nothrow) uint8_t[total_size]; + if (new_data == nullptr) { + OH_LOG_ERROR(LOG_APP, "内存分配失败"); + return nullptr; + } + // 字节对齐 + for (int row = 0; row < height; row++) { + memcpy(new_data + row * row_bytes, data + row * stride, row_bytes); + } + } + if (new_data == nullptr) { + OH_LOG_ERROR(LOG_APP, "图像数据为空,无法进行通道转换"); + return nullptr; + } + + OH_LOG_INFO(LOG_APP, "开始颜色格式转换"); + // TODO: 知识点:OH_PixelMap_CreatePixelMap目前颜色编码格式只支持BGRA,需要转换颜色格式(RGBA to BRGA) + + swapRBChannels(new_data, pixel_count); + + DecodeResult *decodeResult = new DecodeResult(new_data, stride, width, height); + + return decodeResult; +} +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/download_heif_image.cpp b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/download_heif_image.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a6800167bb75791b37e9d2aaa652b701806f7122 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/download_heif_image.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "download_heif_image.h" +#ifndef COMMONAPPDEVELOPMENT_DOWNLOAD_HEIF_IMAGE_CPP +#define COMMONAPPDEVELOPMENT_DOWNLOAD_HEIF_IMAGE_CPP + +extern "C" { +#include "curl.h" +#include "easy.h" +/** + * 下载HEIF图像(.heic格式网络图片) + * @param imageUrl HEIF图像下载链接 + * @return 下载的HEIF图像数据 + */ + +DownloadHEIFImage::DownloadHEIFImage(){}; // 构造函数 +DownloadHEIFImage::~DownloadHEIFImage(){}; // 析构函数 +/** + * + * @param contents + * @param size + * @param nmemb + * @param userp + * @return + */ +size_t DownloadHEIFImage::HttpPostWriteBack(void *contents, size_t size, size_t nmemb, void *userp) { + size_t realsize = size * nmemb; // 一次回调返回的数据量 + auto *mem = static_cast(userp); + + char *ptr = (char *)realloc(mem->memory, mem->size + realsize + 1); // 增加1字节用于结束符 + if (ptr == nullptr) { + OH_LOG_ERROR(LOG_APP, "not enough memory (realloc returned NULL)\n"); + return 0; // 返回0表示错误 + } + + mem->memory = ptr; + memcpy(&(mem->memory[mem->size]), contents, realsize); + mem->size += realsize; + mem->memory[mem->size] = '\0'; // 确保以空字符结尾 + return realsize; +} + +MemoryStruct DownloadHEIFImage::get(std::string imageUrl) { + CURL *curl = curl_easy_init(); + // 获取数据 + MemoryStruct chunk; + if (!curl) { + OH_LOG_ERROR(LOG_APP, "Failed to initial Image"); + chunk.size = -1; + return chunk; + } + + // 支持https + curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); + // 访问网址 + curl_easy_setopt(curl, CURLOPT_URL, imageUrl.c_str()); + + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &DownloadHEIFImage::HttpPostWriteBack); + + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &chunk); + + // 运行 + CURLcode res = curl_easy_perform(curl); + if (res != CURLE_OK) { + OH_LOG_ERROR(LOG_APP, "curl_easy_perform() failed: %{public}s", curl_easy_strerror(res)); + free(chunk.memory); // 释放内存 + chunk.memory = nullptr; // 防止悬空指针 + chunk.size = 0; // 清空大小 + } + curl_easy_cleanup(curl); // 释放句柄 + + return chunk; +} +#endif +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/common.h b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/common.h new file mode 100644 index 0000000000000000000000000000000000000000..a7e1295ea2cb402167ebb20816eca4b50a730fdd --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/common.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef COMMONAPPDEVELOPMENT_MEMORYSTRUCT_H +#define COMMONAPPDEVELOPMENT_MEMORYSTRUCT_H + +#include "stdint.h" +#include +#include +#include +struct MemoryStruct { + char *memory; + size_t size; + + // 构造函数 + MemoryStruct() : memory(nullptr), size(0) { + memory = (char *)malloc(1); // 初始分配1字节 + if (memory) { + memory[0] = '\0'; // 确保字符串以空字符结尾 + } + } + + // 析构函数 + ~MemoryStruct() {} +}; + +struct DecodeResult { + uint8_t *data; + int heif_image_stride; + int heif_image_width; + int heif_image_height; + + DecodeResult(uint8_t *data, int stride, int width, int height) { + this->data = data; + this->heif_image_stride = stride; + this->heif_image_width = width; + this->heif_image_height = height; + } + + ~DecodeResult() { + this->data = nullptr; + OH_LOG_INFO(LOG_APP, "析构DecodeResult"); + } +}; + +#endif // COMMONAPPDEVELOPMENT_MEMORYSTRUCT_H diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/decode_heif_image.h b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/decode_heif_image.h new file mode 100644 index 0000000000000000000000000000000000000000..7b3e50ff4b9b4454b273450e5589b504d945ce12 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/decode_heif_image.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef COMMONAPPDEVELOPMENT_DECODE_HEIF_IMAGE_H +#define COMMONAPPDEVELOPMENT_DECODE_HEIF_IMAGE_H +#include "common.h" +#include + +class DecodeHEIFImage { +public: + DecodeHEIFImage(); // 构造函数 + ~DecodeHEIFImage(); // 析构函数 + + DecodeResult *decode_heif_image(MemoryStruct chunk); + +private: + void swapRBChannels(uint8_t *pixels, int pixelCount); +}; + +#endif // COMMONAPPDEVELOPMENT_DECODE_HEIF_IMAGE_H diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/download_heif_image.h b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/download_heif_image.h new file mode 100644 index 0000000000000000000000000000000000000000..5d0d259dec7a5278e6e1b15b45657171cbd710d5 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/include/download_heif_image.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "common.h" +#include + +#ifndef COMMONAPPDEVELOPMENT_DOWNLOAD_HEIF_IMAGE_H +#define COMMONAPPDEVELOPMENT_DOWNLOAD_HEIF_IMAGE_H + +class DownloadHEIFImage { +public: + DownloadHEIFImage(); // 构造函数 + ~DownloadHEIFImage(); // 析构函数 + + MemoryStruct get(std::string url); + static size_t HttpPostWriteBack(void *contents, size_t size, size_t nmemb, void *userp); + +private: +}; + +#endif // COMMONAPPDEVELOPMENT_DECODE_HEIF_IMAGE_H diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/napi_init.cpp b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0573b0316a2b50e7244f8667ce3f94c8c7511fa --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/napi_init.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "decode_heif_image.h" +#include "download_heif_image.h" +#include "napi/native_api.h" +#include +#include +#include + + +/** + * 通过libheif软解码HEIF网络图片 + * @param env + * @param info + * @return 解码后的HEIF图片数据 + */ +static napi_value DecodeHeifImageFromInternet(napi_env env, napi_callback_info info) { + napi_value pixel_map = nullptr; + + OH_LOG_INFO(LOG_APP, "Beginning DecodeInternetHeifImage!"); + + // 解析参数JS -> C++ + size_t argc = 1; + napi_value argv[1] = {nullptr}; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + + size_t filenameSize; + char filenameBuffer[512]; + napi_get_value_string_utf8(env, argv[0], filenameBuffer, sizeof(filenameBuffer), &filenameSize); + std::string imageUrl(filenameBuffer, filenameSize); + OH_LOG_INFO(LOG_APP, "url: %{public}s", imageUrl.c_str()); + + // 获取网络HEIF + DownloadHEIFImage downloadHEIFImage; + MemoryStruct chunk = downloadHEIFImage.get(imageUrl); + + if (chunk.size == -1) { + OH_LOG_ERROR(LOG_APP, "Fail to download!"); + return nullptr; + } + + OH_LOG_INFO(LOG_APP, "DownloadFromInternet sucess!%{public}d", chunk.size); + + DecodeHEIFImage decodeHEIFImage; + + DecodeResult *decodeResult = decodeHEIFImage.decode_heif_image(chunk); + + OH_LOG_INFO(LOG_APP, "DecodeHEIFImage sucess!%{public}d", decodeResult->heif_image_height); + + const size_t bpp = 4; + const size_t pixel_count = decodeResult->heif_image_width * decodeResult->heif_image_height; // 像素总数 + const size_t row_bytes = decodeResult->heif_image_width * bpp; // 每一行的字节数,每个像素4个字节 + const size_t total_size = pixel_count * bpp; // 计算平面的总数据大小 + + bool needAlignment = decodeResult->heif_image_stride != row_bytes; // 是否需要字节对齐 + struct OhosPixelMapCreateOps createOps; + createOps.width = decodeResult->heif_image_width; + createOps.height = decodeResult->heif_image_height; + createOps.pixelFormat = 4; // 目前颜色编码格式只支持BGRA + createOps.alphaType = 0; + + // TODO: 知识点:调用NDK接口OH_PixelMap_CreatePixelMap创建PixelMap + int32_t res = OH_PixelMap_CreatePixelMap(env, createOps, (void *)decodeResult->data, total_size, &pixel_map); + if (res != IMAGE_RESULT_SUCCESS || pixel_map == nullptr) { + OH_LOG_ERROR(LOG_APP, "创建pixelMap错误"); + return nullptr; + } + + const char *keys[] = {"data", "width", "height"}; + napi_value values[3]; + values[0] = pixel_map; + napi_create_int32(env, decodeResult->heif_image_width, &values[1]); + napi_create_int32(env, decodeResult->heif_image_height, &values[2]); + + napi_value result; + napi_create_object_with_named_properties(env, &result, 3, keys, values); + + OH_LOG_INFO(LOG_APP, "napi_create_object_with_named_properties success"); + // 清理资源 + if (needAlignment && decodeResult->data != nullptr) { + delete[] decodeResult->data; + } + + // 释放chunk + if (chunk.memory) { + OH_LOG_INFO(LOG_APP, "释放chunk"); + free(chunk.memory); + chunk.memory = nullptr; + chunk.size = 0; + } + + return result; +} + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) { + napi_property_descriptor desc[] = {{"decodeHeifImageFromInternet", nullptr, DecodeHeifImageFromInternet, nullptr, + nullptr, nullptr, napi_default, nullptr}}; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "decodeheifimage", + .nm_priv = ((void *)0), + .reserved = {0}, +}; + +extern "C" __attribute__((constructor)) void RegisterDecodeHEIFImageModule(void) { napi_module_register(&demoModule); } diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/types/libdecodeheifimage/index.d.ts b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/types/libdecodeheifimage/index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..2ba930f3560c76dc57f0d87ac955424d317f1e85 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/types/libdecodeheifimage/index.d.ts @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { image } from '@kit.ImageKit'; +export interface IHEIFInfo { + data: image.PixelMap; + width: number; + height: number; +} +export const decodeHeifImageFromInternet: (url: string) => IHEIFInfo; \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/types/libdecodeheifimage/oh-package.json5 b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/types/libdecodeheifimage/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..696706aeb464da88dc41be0ebacaca04b69089e8 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/cpp/types/libdecodeheifimage/oh-package.json5 @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "libdecodeheifimage.so", + "types": "./index.d.ts", + "version": "", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/DecodeHEIFImageView.ets b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/DecodeHEIFImageView.ets new file mode 100644 index 0000000000000000000000000000000000000000..60989c73f86da9c8e55f6d6bcac223d90c30df2b --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/DecodeHEIFImageView.ets @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/** + * 实现步骤: + * 1. 集成三方库libheif及其依赖库libde265来实现软解码,集成网络库curl,这样在Native侧就可以直接请求到HEIF图片,并在Native侧解码,减少跨语言调用开销 + * 2. 网络请求和HEIF图片软解码使用Taskpool来实现多线程并发能力 + * 3. 在HEIF软解码过程中 + * 3.1 通过heif_context_read_from_memory_without_copy读取网络请求到的HEIF资源(已存在内存中) + * 3.2 调用解码接口heif_decode_image解码HEIF图片 + * 3.3 调用heif_image_get_plane_readonly获取HEIF图片数据data + * 3.4 字节对齐和颜色编码格式转换 + * 3.5 定义HEIF的宽高、颜色编码格式,调用NDK的OH_PixelMap_CreatePixelMap函数即可创建PixelMap + * 4. WaterFlow + LazyForEach加载解码后的HEIF图片数据 + */ + +import { heifUrls, ImageInfo, WaterFlowDataSource } from './model/WaterFlowData'; +import { ReusableFlowItem } from './components/ReusableFlowItem'; +import { executeTasks } from './model/Taskpool'; + + +@Component +export struct DecodeHEIFImageView { + private dataSource: WaterFlowDataSource = new WaterFlowDataSource(); + + aboutToAppear(): void { + // TODO:知识点:在Taskpool中执行异步并发任务(网络请求和图片软解码) + executeTasks(heifUrls, this.dataSource); + } + + build() { + Column() { + WaterFlow() { + // TODO: 知识点: LazyForEach提供列表数据按需加载能力,解决一次性加载长列表数据耗时长、占用过多资源的问题,可以提升页面响应速度 + LazyForEach(this.dataSource, (item: ImageInfo) => { + FlowItem() { + ReusableFlowItem({ item }) + } + .width('100%') + .margin({ + top: $r("app.integer.decode_heif_image_flow_item_margin_top"), + bottom: $r("app.integer.decode_heif_image_flow_item_margin_bottom") + }) + }, (item: ImageInfo, index: number) => index + JSON.stringify(item)) + } + .cachedCount(1) // 当前案例数据量少设置为1,如果数据量较多可适当调整 + .columnsTemplate('1fr 1fr') + .columnsGap($r("app.integer.decode_heif_image_water_flow_column_gap")) + } + .width('100%') + .height('100%') + .padding($r("app.integer.decode_heif_image_padding")) + .backgroundColor($r("app.color.decode_heif_image_background_color")) + } +} diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/components/ReusableFlowItem.ets b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/components/ReusableFlowItem.ets new file mode 100644 index 0000000000000000000000000000000000000000..734597245d756add24f6d576b75b81c40f856b8d --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/components/ReusableFlowItem.ets @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { ImageInfo } from '../model/WaterFlowData'; + +@Reusable +@Component +export struct ReusableFlowItem { + @State item: ImageInfo | null = null; + + // TODO:知识点:从复用缓存中加入到组件树之前调用,可在此处更新组件的状态变量以展示正确的内容 + aboutToReuse(params: ESObject) { + this.item = params.item; + } + + build() { + Column() { + Image(this.item?.data) + .objectFit(ImageFit.Contain) + .width('100%') + .borderRadius({ + topLeft: $r("app.integer.decode_heif_image_flow_item_image_border_radius_top_left"), + topRight: $r("app.integer.decode_heif_image_flow_item_image_border_radius_top_right") + }) + + Text(this.item?.description) + .fontSize($r("app.integer.decode_heif_image_flow_item_text_font_size")) + .fontColor($r("app.color.decode_heif_image_flow_item_font_color")) + .margin({ + top: $r("app.integer.decode_heif_image_flow_item_text_margin_top"), + bottom: $r("app.integer.decode_heif_image_flow_item_text_margin_bottom") + }) + } + .width('100%') + .shadow(ShadowStyle.OUTER_DEFAULT_XS) + .borderRadius($r("app.integer.decode_heif_image_flow_item_border_radius")) + .backgroundColor(Color.White) + } +} diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/model/Taskpool.ets b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/model/Taskpool.ets new file mode 100644 index 0000000000000000000000000000000000000000..29c9bf738361d031fe67704728897833949ce95e --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/model/Taskpool.ets @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { taskpool } from '@kit.ArkTS'; +import testNapi, { IHEIFInfo } from 'libdecodeheifimage.so'; +import { WaterFlowDataSource, ImageInfo } from './WaterFlowData'; + +@Concurrent +export function decodeHeifImage(url: string): IHEIFInfo { + const result = testNapi.decodeHeifImageFromInternet(url); + return result; +} + +/** + * 获取taskpool异步任务列表 + * @param urls 图片资源链接数组 + * @returns taskpool.Task[] + */ +export function getTasks(urls: string[]): taskpool.Task[] { + const tasks: taskpool.Task[] = []; + for (let i = 0; i < urls.length; i++) { + tasks.push(new taskpool.Task(decodeHeifImage, urls[i])); + } + return tasks; +} + +/** + * 执行taskpool异步任务列表中的每一个任务 + * @param urls 图片资源链接数组 + * @param dataSource 瀑布流数据操作实例 + */ +export function executeTasks(urls: string[], dataSource: WaterFlowDataSource) { + const tasks = getTasks(urls); + for (let i = 0; i < tasks.length; i++) { + taskpool.execute(tasks[i], taskpool.Priority.HIGH) + .then(result => { + const imageInfo = result as ImageInfo; + if (result !== null) { + dataSource.addData(i, new ImageInfo(imageInfo.data, imageInfo.width, imageInfo.height, `image${i + 1}.heic`)); + } + }) + .catch((err: Error) => { + console.error(JSON.stringify(err)) + }) + } +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/model/WaterFlowData.ets b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/model/WaterFlowData.ets new file mode 100644 index 0000000000000000000000000000000000000000..fcf65368efe89757a883871a43a78cf2c847e667 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/ets/model/WaterFlowData.ets @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { image } from '@kit.ImageKit'; + +/** + * 图片信息类 + */ +export class ImageInfo { + data: image.PixelMap | null = null; + width: number = 0; + height: number = 0; + description: string | undefined = undefined; + + constructor(data: image.PixelMap | null, width: number, height: number, description?: string) { + this.data = data; + this.width = width; + this.height = height; + this.description = description; + } +} + +// HEIF图片资源链接 +export const heifUrls: string[] = [ + "https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/decodeheifimage/src/main/resources/base/media/image1.heic", + "https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/decodeheifimage/src/main/resources/base/media/image2.heic", + "https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/decodeheifimage/src/main/resources/base/media/image3.heic", + "https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/decodeheifimage/src/main/resources/base/media/image4.heic", + "https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/decodeheifimage/src/main/resources/base/media/image5.heic", + "https://gitee.com/harmonyos-cases/cases/raw/master/CommonAppDevelopment/feature/decodeheifimage/src/main/resources/base/media/image6.heic", +]; + +/** + * 实现IDataSource接口的对象,用于瀑布流组件加载数据 + */ +export class WaterFlowDataSource implements IDataSource { + private dataArray: ImageInfo[] = []; + private listeners: DataChangeListener[] = []; + + public totalCount(): number { + return this.dataArray.length; + } + + public getData(index: number): ImageInfo { + return this.dataArray[index]; + } + + public addData(index: number, data: ImageInfo): void { + this.dataArray.splice(index, 0, data); + this.notifyDataAdd(index); + } + + public clearData(): void { + this.dataArray = []; + this.notifyDataReload(); + } + + public pushData(data: ImageInfo): void { + this.dataArray.push(data); + this.notifyDataAdd(this.dataArray.length - 1); + } + + // 该方法为框架侧调用,为LazyForEach组件向其数据源处添加listener监听 + registerDataChangeListener(listener: DataChangeListener): void { + if (this.listeners.indexOf(listener) < 0) { + console.info('add listener'); + this.listeners.push(listener); + } + } + + // 该方法为框架侧调用,为对应的LazyForEach组件在数据源处去除listener监听 + unregisterDataChangeListener(listener: DataChangeListener): void { + const pos = this.listeners.indexOf(listener); + if (pos >= 0) { + console.info('remove listener'); + this.listeners.splice(pos, 1); + } + } + + // 通知LazyForEach组件需要重载所有子组件 + notifyDataReload(): void { + this.listeners.forEach(listener => { + listener.onDataReloaded(); + }) + } + + // 通知LazyForEach组件需要在index对应索引处添加子组件 + notifyDataAdd(index: number): void { + this.listeners.forEach(listener => { + listener.onDataAdd(index); + }) + } + + // 通知LazyForEach组件在index对应索引处数据有变化,需要重建该子组件 + notifyDataChange(index: number): void { + this.listeners.forEach(listener => { + listener.onDataChange(index); + }) + } + + // 通知LazyForEach组件需要在index对应索引处删除该子组件 + notifyDataDelete(index: number): void { + this.listeners.forEach(listener => { + listener.onDataDelete(index); + }) + } + + // 通知LazyForEach组件将from索引和to索引处的子组件进行交换 + notifyDataMove(from: number, to: number): void { + this.listeners.forEach(listener => { + listener.onDataMove(from, to); + }) + } +} + diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/module.json5 b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..7c96c8908558fbf4b4f2c1bd5526215f7b2dd0d0 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/module.json5 @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "decodeheifimage", + "type": "har", + "deviceTypes": [ + "default", + "tablet" + ], + "requestPermissions": [ + { + "name": "ohos.permission.INTERNET" + } + ] + } +} diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/color.json b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..aa1659e8030f1d34842e69003a4c4b0f605f7e26 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/color.json @@ -0,0 +1,12 @@ +{ + "color": [ + { + "name": "decode_heif_image_background_color", + "value": "#FFDBD9D9" + }, + { + "name": "decode_heif_image_flow_item_font_color", + "value": "#202020" + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/integer.json b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/integer.json new file mode 100644 index 0000000000000000000000000000000000000000..fecd347ff19eff21465975406a89aa16b0a6e22e --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/integer.json @@ -0,0 +1,60 @@ +{ + "integer": [ + { + "name": "decode_heif_image_button_width", + "value": 100 + }, + { + "name": "decode_heif_image_button_margin_top", + "value": 10 + }, + { + "name": "decode_heif_image_button_margin_bottom", + "value": 10 + }, + { + "name": "decode_heif_image_flow_item_margin_top", + "value": 5 + }, + { + "name": "decode_heif_image_flow_item_margin_bottom", + "value": 5 + }, + { + "name": "decode_heif_image_water_flow_cache_count", + "value": 5 + }, + { + "name": "decode_heif_image_water_flow_column_gap", + "value": 10 + }, + { + "name": "decode_heif_image_padding", + "value": 5 + }, + { + "name": "decode_heif_image_flow_item_image_border_radius_top_left", + "value": 6 + }, + { + "name": "decode_heif_image_flow_item_image_border_radius_top_right", + "value": 6 + }, + { + "name": "decode_heif_image_flow_item_border_radius", + "value": 6 + }, + { + "name": "decode_heif_image_flow_item_text_margin_top", + "value": 5 + }, + { + "name": "decode_heif_image_flow_item_text_margin_bottom", + "value": 5 + }, + { + "name": "decode_heif_image_flow_item_text_font_size", + "value": 16 + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/string.json b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..94e7f29774bdd361a7b67736d7f10fcb0b005127 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "decode_heif_image_title", + "value": "HEIF图片软解码" + }, + { + "name": "decode_heif_image_button_label", + "value": "展示HEIF网络图片" + } + ] +} diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/HPKBUILD1.png b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/HPKBUILD1.png new file mode 100644 index 0000000000000000000000000000000000000000..ce7c9e7ce912af1494710e8105326acda11a53dd Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/HPKBUILD1.png differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/HPKBUILD2.png b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/HPKBUILD2.png new file mode 100644 index 0000000000000000000000000000000000000000..bcd063d13ec3a38c4ba9b998ed9e76c58e74c9ef Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/HPKBUILD2.png differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/decode_heif_image.gif b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/decode_heif_image.gif new file mode 100644 index 0000000000000000000000000000000000000000..46d5cabbf0d8050bbb726c07b9fa41ee59865ff4 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/decode_heif_image.gif differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image1.heic b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image1.heic new file mode 100644 index 0000000000000000000000000000000000000000..fcf75f07aa850fcf04fe2de71952b2751c1d63d2 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image1.heic differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image2.heic b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image2.heic new file mode 100644 index 0000000000000000000000000000000000000000..eafd46c1a0dce545e18809231a8ebd54b88475be Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image2.heic differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image3.heic b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image3.heic new file mode 100644 index 0000000000000000000000000000000000000000..b55bf44782801aed589d3fc19bb041ce0ec20886 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image3.heic differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image4.heic b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image4.heic new file mode 100644 index 0000000000000000000000000000000000000000..4693e52b72fc84abf4a950c76f8d9c5fa5a6beb2 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image4.heic differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image5.heic b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image5.heic new file mode 100644 index 0000000000000000000000000000000000000000..887c1ed7b5d9ad41a1aded9a9236d33c496cf79d Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image5.heic differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image6.heic b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image6.heic new file mode 100644 index 0000000000000000000000000000000000000000..005df163523a13a65f593b693db20d9fb872f155 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/image6.heic differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_compile_result.png b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_compile_result.png new file mode 100644 index 0000000000000000000000000000000000000000..fbd446dba2c46279b63d46cbe060cf1c8cb3aed5 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_compile_result.png differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_dependency_so.png b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_dependency_so.png new file mode 100644 index 0000000000000000000000000000000000000000..9299e12649be8faecced38b2a1cb646eb945e048 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_dependency_so.png differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_symbol_info.png b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_symbol_info.png new file mode 100644 index 0000000000000000000000000000000000000000..df7c4d16439d4c77ad94a6dec99e4e4a2ff1c0c7 Binary files /dev/null and b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/base/media/libheif_symbol_info.png differ diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/rawfile/routerMap/decodeheifimage.json b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/rawfile/routerMap/decodeheifimage.json new file mode 100644 index 0000000000000000000000000000000000000000..42e16ca5bb26a6dc962fd62e00eb144bff71c203 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/rawfile/routerMap/decodeheifimage.json @@ -0,0 +1,10 @@ +{ + "routerMap": [ + { + "name": "decodeheifimage/DecodeHEIFImageView", + "pageModule": "decodeheifimage", + "pageSourceFile": "src/main/ets/generated/RouterBuilder.ets", + "registerFunction": "decodeHEIFImageViewRegister" + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/zh_CN/element/string.json b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/zh_CN/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..f51a9c8461a55f6312ef950344e3145b7f82d607 --- /dev/null +++ b/code/UI/DecodeHEIFImage/decodeheifimage/src/main/resources/zh_CN/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "page_show", + "value": "page from package" + } + ] +} diff --git a/code/UI/DecodeHEIFImage/entry/.gitignore b/code/UI/DecodeHEIFImage/entry/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..eadab4e1522296628f32a70228b2c758ecab4759 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/.gitignore @@ -0,0 +1,7 @@ +/node_modules +/oh_modules +/.preview +/build +/.cxx +/.test +/oh-package-lock.json5 \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/build-profile.json5 b/code/UI/DecodeHEIFImage/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e7569e3056e27af38e9991b7ea73ec10f3ba8a05 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/build-profile.json5 @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "apiType": "stageMode", + "buildOption": { + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/hvigorfile.ts b/code/UI/DecodeHEIFImage/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..e4f43d54667f8327c367c8096bd08bb8c75aff54 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hapTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/code/UI/DecodeHEIFImage/entry/obfuscation-rules.txt b/code/UI/DecodeHEIFImage/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/obfuscation-rules.txt @@ -0,0 +1,23 @@ +# Define project specific obfuscation rules here. +# You can include the obfuscation configuration files in the current module's build-profile.json5. +# +# For more details, see +# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5 + +# Obfuscation options: +# -disable-obfuscation: disable all obfuscations +# -enable-property-obfuscation: obfuscate the property names +# -enable-toplevel-obfuscation: obfuscate the names in the global scope +# -compact: remove unnecessary blank spaces and all line feeds +# -remove-log: remove all console.* statements +# -print-namecache: print the name cache that contains the mapping from the old names to new names +# -apply-namecache: reuse the given cache file + +# Keep options: +# -keep-property-name: specifies property names that you want to keep +# -keep-global-name: specifies names that you want to keep in the global scope + +-enable-property-obfuscation +-enable-toplevel-obfuscation +-enable-filename-obfuscation +-enable-export-obfuscation \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/oh-package.json5 b/code/UI/DecodeHEIFImage/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..aed9e7f4d342eff3d0f4d4a9305442cd815cc0f8 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/oh-package.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "decodeheifimage": "file:../decodeheifimage" + } +} + diff --git a/code/UI/DecodeHEIFImage/entry/src/main/ets/entryability/EntryAbility.ets b/code/UI/DecodeHEIFImage/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..edc2839f203ba057c186e19b0cbbbf80c8faa8b3 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { AbilityConstant, ConfigurationConstant, UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +export default class EntryAbility extends UIAbility { + onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void { + this.context.getApplicationContext().setColorMode(ConfigurationConstant.ColorMode.COLOR_MODE_NOT_SET); + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? ''); + return; + } + hilog.info(0x0000, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/UI/DecodeHEIFImage/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b1e212947256c5533c7b06285a597c94f840a6e3 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(0x0000, 'testTag', 'onBackup ok'); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(0x0000, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + } +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/ets/pages/Index.ets b/code/UI/DecodeHEIFImage/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..e7b290bc6276135c3b49218069c19d84647a2420 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { DecodeHEIFImageView } from "decodeheifimage"; + +@Entry +@Component +struct Index { + + build() { + Column() { + DecodeHEIFImageView() + } + .height('100%') + .width('100%') + } +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/module.json5 b/code/UI/DecodeHEIFImage/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4144486d1af4c03b0d767cce1cda86fc0d697f91 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/module.json5 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry", + "type": "entry", + "description": "$string:module_desc", + "mainElement": "EntryAbility", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false, + "pages": "$profile:main_pages", + "abilities": [ + { + "name": "EntryAbility", + "srcEntry": "./ets/entryability/EntryAbility.ets", + "description": "$string:EntryAbility_desc", + "icon": "$media:layered_image", + "label": "$string:EntryAbility_label", + "startWindowIcon": "$media:startIcon", + "startWindowBackground": "$color:start_window_background", + "exported": true, + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ] + } +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/element/color.json b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/element/string.json b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..1f484705f420ddf722e11d17ab5c5d94ac256061 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/element/string.json @@ -0,0 +1,16 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "decodeheifimage" + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/background.png b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..f939c9fa8cc8914832e602198745f592a0dfa34d Binary files /dev/null and b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/background.png differ diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/foreground.png b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..4483ddad1f079e1089d685bd204ee1cfe1d01902 Binary files /dev/null and b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/foreground.png differ diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/layered_image.json b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/layered_image.json @@ -0,0 +1,7 @@ +{ + "layered-image": + { + "background" : "$media:background", + "foreground" : "$media:foreground" + } +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/startIcon.png b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/media/startIcon.png differ diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/profile/backup_config.json b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/base/profile/main_pages.json b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,5 @@ +{ + "src": [ + "pages/Index" + ] +} diff --git a/code/UI/DecodeHEIFImage/entry/src/main/resources/dark/element/color.json b/code/UI/DecodeHEIFImage/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/main/resources/dark/element/color.json @@ -0,0 +1,8 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#000000" + } + ] +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/ohosTest/ets/test/Ability.test.ets b/code/UI/DecodeHEIFImage/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0f8ce9a2c012f8fe36114cef65216ef0b6254f41 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function abilityTest() { + describe('ActsAbilityTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }) + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }) + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }) + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }) + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + hilog.info(0x0000, 'testTag', '%{public}s', 'it begin'); + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }) + }) +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/ohosTest/ets/test/List.test.ets b/code/UI/DecodeHEIFImage/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1eac52fcebe8958e19a7b8fed2e8f39c520a3e42 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/ohosTest/ets/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import abilityTest from './Ability.test'; + +export default function testsuite() { + abilityTest(); +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/ohosTest/module.json5 b/code/UI/DecodeHEIFImage/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..c3fd9dda3040d888d9d8b0b62bcb5d3b6fbeb614 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/ohosTest/module.json5 @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default", + "tablet" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/code/UI/DecodeHEIFImage/entry/src/test/List.test.ets b/code/UI/DecodeHEIFImage/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f1186b1f53c3a70930921c5dbd1417332bec56c9 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/test/List.test.ets @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import localUnitTest from './LocalUnit.test'; + +export default function testsuite() { + localUnitTest(); +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/entry/src/test/LocalUnit.test.ets b/code/UI/DecodeHEIFImage/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7fc57c77dbf76d8df08a2b802a55b948e3fcf968 --- /dev/null +++ b/code/UI/DecodeHEIFImage/entry/src/test/LocalUnit.test.ets @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium'; + +export default function localUnitTest() { + describe('localUnitTest', () => { + // Defines a test suite. Two parameters are supported: test suite name and test suite function. + beforeAll(() => { + // Presets an action, which is performed only once before all test cases of the test suite start. + // This API supports only one parameter: preset action function. + }); + beforeEach(() => { + // Presets an action, which is performed before each unit test case starts. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: preset action function. + }); + afterEach(() => { + // Presets a clear action, which is performed after each unit test case ends. + // The number of execution times is the same as the number of test cases defined by **it**. + // This API supports only one parameter: clear action function. + }); + afterAll(() => { + // Presets a clear action, which is performed after all test cases of the test suite end. + // This API supports only one parameter: clear action function. + }); + it('assertContain', 0, () => { + // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function. + let a = 'abc'; + let b = 'b'; + // Defines a variety of assertion methods, which are used to declare expected boolean conditions. + expect(a).assertContain(b); + expect(a).assertEqual(a); + }); + }); +} \ No newline at end of file diff --git a/code/UI/DecodeHEIFImage/hvigor/hvigor-config.json5 b/code/UI/DecodeHEIFImage/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..d584c19c247db9a7caee4b606bb931aa9279c637 --- /dev/null +++ b/code/UI/DecodeHEIFImage/hvigor/hvigor-config.json5 @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */ + // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */ + // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */ + // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */ + // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */ + }, + "logging": { + // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */ + }, + "debugging": { + // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */ + }, + "nodeOptions": { + // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/ + // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/ + } +} diff --git a/code/UI/DecodeHEIFImage/hvigorfile.ts b/code/UI/DecodeHEIFImage/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..2a5e543f190732c159beb574dfc9fa37bc94e156 --- /dev/null +++ b/code/UI/DecodeHEIFImage/hvigorfile.ts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { appTasks } from '@ohos/hvigor-ohos-plugin'; + +export default { + system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */ + plugins:[] /* Custom plugin to extend the functionality of Hvigor. */ +} diff --git a/code/UI/DecodeHEIFImage/oh-package.json5 b/code/UI/DecodeHEIFImage/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..e41bae026aab3b50d0abb42fece08ba43b4a772b --- /dev/null +++ b/code/UI/DecodeHEIFImage/oh-package.json5 @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +{ + "modelVersion": "5.0.1", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.19", + "@ohos/hamock": "1.0.0" + } +} diff --git a/code/UI/DecodeHEIFImage/ohosTest.md b/code/UI/DecodeHEIFImage/ohosTest.md new file mode 100644 index 0000000000000000000000000000000000000000..952e44324d0546a05eb7950b502249fdf4207ef7 --- /dev/null +++ b/code/UI/DecodeHEIFImage/ohosTest.md @@ -0,0 +1,7 @@ +# HEIF软解码器案例测试用例 + +## 用例表 + +| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 | +|----------------|---------------------------|---------------|-------------------------------------|------|------| +| 正常加载所有HEIF网络图片 | 启动【HEIF软解码器案例】 | 访问【HEIF软解码器案例】 | 进入会出现【HEIF软解码器案例】页面,正常加载所有HEIF网络图片。 | 否 | Pass | \ No newline at end of file