diff --git a/ImageKit/ImageNativeSample/AppScope/app.json5 b/ImageKit/ImageNativeSample/AppScope/app.json5 new file mode 100644 index 0000000000000000000000000000000000000000..1d2fc51809a58986cc8094e23fe818ffafd770e8 --- /dev/null +++ b/ImageKit/ImageNativeSample/AppScope/app.json5 @@ -0,0 +1,24 @@ +/* + * 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.sample.ndkImage", + "vendor": "example", + "versionCode": 1000000, + "versionName": "1.0.0", + "icon": "$media:layered_image", + "label": "$string:app_name" + } +} diff --git a/ImageKit/ImageNativeSample/AppScope/resources/base/element/string.json b/ImageKit/ImageNativeSample/AppScope/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..855db12a53377cadd556962d4a54635794d24020 --- /dev/null +++ b/ImageKit/ImageNativeSample/AppScope/resources/base/element/string.json @@ -0,0 +1,8 @@ +{ + "string": [ + { + "name": "app_name", + "value": "ImageNativeSample" + } + ] +} diff --git a/ImageKit/ImageNativeSample/AppScope/resources/base/media/background.png b/ImageKit/ImageNativeSample/AppScope/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ImageKit/ImageNativeSample/AppScope/resources/base/media/background.png differ diff --git a/ImageKit/ImageNativeSample/AppScope/resources/base/media/foreground.png b/ImageKit/ImageNativeSample/AppScope/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..eb9427585b36d14b12477435b6419d1f07b3e0bb Binary files /dev/null and b/ImageKit/ImageNativeSample/AppScope/resources/base/media/foreground.png differ diff --git a/ImageKit/ImageNativeSample/AppScope/resources/base/media/layered_image.json b/ImageKit/ImageNativeSample/AppScope/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ImageKit/ImageNativeSample/AppScope/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/ImageKit/ImageNativeSample/README.md b/ImageKit/ImageNativeSample/README.md new file mode 100644 index 0000000000000000000000000000000000000000..893e63b0819df8ae66d95ef7ab6bfc8991702ac5 --- /dev/null +++ b/ImageKit/ImageNativeSample/README.md @@ -0,0 +1,123 @@ +# Image开发指导(C/C++) + +### 介绍 + +此Sample为开发指南中**图片开发指导(C/C++)**章节中部分示例代码的工程。包含图片编解码,图片接收,内存分配,以及图片Exif信息的相关操作。 + +### 效果预览 + +| index页面 | 图片解码页面示例 | Exif信息编辑页面示例 | +|-----------------------------------|-----------------------------------|----------------------------------| +| ![Image](./screenShots/index.png) | ![Image](./screenShots/codec.png) | ![Image](./screenShots/Exif.png) | + +使用说明: + +1.安装应用,弹出权限允许界面,点击“允许”按钮,弹出菜单后,根据需要点击按钮跳转到不同功能的界面。 + +2.从菜单页面,点击“跳转到图片编解码操作页面”按钮,进入图片编解码页面,首先点击“CreateImageSource”按钮解码创建ImageSource对象,然后点击“packToFileFromImageSource”按钮 +对ImageSource对象进行编码,点击“GetImageInfo”按钮获取ImageInfo的width。在编解码操作结束后点击“ReleaseImageSource”按钮进行资源的释放。 + +3.从菜单页面,点击“跳转到图片编解码操作页面”按钮,进入图片编解码页面,首先点击“CreateImageSource”按钮解码创建ImageSource对象,然后点击“createPixelMap”按钮 +解码创建PixelMap对象,点击“packToFileFromPixelmap”按钮对PixelMap对象进行编码。在编解码操作结束后点击“ReleaseImageSource”按钮进行资源的释放。 + +4.从菜单页面,点击“跳转到图片编解码操作页面”按钮,进入图片编解码页面,首先点击“CreateImageSource”按钮解码创建ImageSource对象, +然后点击“CreatePixelmapUsingAllocator”按钮申请图片解码内存解码创建PixelMap对象,在解码结束后点击“ReleaseImageSource”按钮进行资源的释放。 + +5.从菜单页面,点击“跳转到Gif编解码操作页面”按钮进入Gif编解码操作页面,首先点击“CreateImageSource”按钮解码创建ImageSource对象,然后点击“CreatePixelmapList”按钮 +创建Pixelmap列表,点击“GetDelayTimeList”按钮获取图像延迟时间列表,在解码结束后点击“ReleaseImageSource”按钮进行资源的释放。 + +6.从菜单页面,点击“跳转到Picture编解码演示页面”按钮,进入多图编解码演示页面,首先点击“SetDesiredAuxiliaryPictures”按钮设置解码参数,然后点击“CreateImageSource”按钮 +解码创建ImageSource对象,点击“packToDataFromPicture”按钮将Picture对象进编码进data,点击“packToFileFromPicture”按钮将Picture对象进编码进file, +在编解码操作结束后点击“ReleasePictureSource”按钮进行资源的释放。 + +7.从菜单页面,点击“跳转到读取和修改Exif信息页面”按钮,进入Exif信息编辑页面,首先点击“CreateImageSource”按钮解码创建ImageSource对象,然后点击“ChoosePropertyKey”按钮 +选择PropertyKey,点击“GetImageProperty”按钮获取其Exif信息。在操作结束后点击“ReleaseImageSource”按钮进行资源的释放。 + +8.从菜单页面,点击“跳转到读取和修改Exif信息页面”按钮,进入Exif信息编辑页面,首先点击“CreateImageSource”按钮解码创建ImageSource对象,然后点击“ChoosePropertyKey”按钮 +选择PropertyKey,在输入栏输入要修改value值,点击"ModifyImageProperty"按钮修改Exif信息。在操作结束后点击“资源释放”按钮进行资源的释放。 + +9.从菜单页面,点击“跳转到图片接收页面”按钮,进入图片接收页面,首先点击“initImageReceiver”按钮初始化ImageReceiver,注册回调函数,点击"takePhoto"按钮触发回调,并获取image信息。 +在操作结束后点击“releaseImageReceiver”按钮进行资源的释放。 + +### 工程目录 + +``` +NdkPicture +entry/src/main/cpp/ +├── types +│ └── libentry +│ └── Index.d.ts (声明Napi接口,供ts调用) +├── imageKits.txt (声明文件) +├── loadAllocator.txt (内存分配接口调用文件) +├── loadImageSource.txt (ImageSource接口调用文件) +├── loadPicture.txt (Picture接口调用文件) +├── loadReceiver.txt (Receiver接口调用文件) +├── loadReceiver.h (Receiver接口导出文件) +└── napi_init.cpp (初始化Napi接口) +entry/src/main/ets/ +├── utils +│ └── FunctionUtility.ets (辅助功能函数) +│ └── Logger.ets (logger日志类) +│ └── MyButton.ets (自定义Button按钮类) +│ └── PictureFunctions.ets (Picture函数类) +│ └── ReceiverFunctions.ets (Receiver函数类) +│ └── SourceFunctions.ets (ImageSource函数类) +└── pages + └── EditExif.ets (Exif编辑界面) + └── GifCodec.ets (Gif编解码界面) + └── ImageCodec.ets (ImageSource操作界面) + └── ImageReceiver.ets (Receiver操作界面) + └── Index.ets (菜单界面) + └── PictureCodec.ets (Picture编解码操作界面) +entry/src/main/resources/ +└── rawfile + └── test.jpeg(单图资源) + └── test.gif(Gif资源) + └── allAux.jpg(Picture资源) +entry/src/ohosTest/ets/ +└── test + ├── Ability.test.ets (UI测试样例代码) + ├── Exif.test.ets (Exif UI测试代码) + ├── Gif.test.ets (Gif UI测试代码) + ├── ImageSource.test.ets (ImageSource UI测试代码) + ├── Picture.test.ets (Picture UI测试代码) + ├── Receiver.test.ets (Receiver UI测试代码) + └── List.test.ets (测试套件列表) +``` + +### 具体实现 + ++ 图片编解码,部分ImageSource操作,Exif信息获取与修改功能和内存申请等功能的接口调用均封装在SourceFunctions中实现, +源码参考[SourceFunctions.ets](./entry/src/main/ets/utils/SourceFunctions.ets)。 ++ 多图编解码相关操作的接口调用均封装在PictureFunctions中实现,源码参考[PictureFunctions.ets](./entry/src/main/ets/utils/PictureFunctions.ets)。 ++ 图片接收功能的接口调用封装在ReceiverFunctions中实现,源码参考[ReceiverFunctions.ets](./entry/src/main/ets/utils/ReceiverFunctions.ets)。 + +### 相关权限 + +相机权限。 + +### 依赖 + +不涉及。 + +### 约束与限制 + +1. 本示例仅支持标准系统上运行, 支持设备:华为手机。 + +2. HarmonyOS系统:HarmonyOS 5.0.5 Release及以上。 + +3. DevEco Studio版本:6.0.0 Release及以上。 + +4. HarmonyOS SDK版本:HarmonyOS 6.0.0 Release SDK及以上。 + +### 下载 + +如需单独下载本工程,执行如下命令: + +```` +git init +git config core.sparsecheckout true +echo ImageKit/ImageNativeSample > .git/info/sparse-checkout +git remote add origin https://gitee.com/harmonyos_samples/guide-snippets.git +git pull origin master +```` \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/build-profile.json5 b/ImageKit/ImageNativeSample/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..4b0b0ecbad91eda4b2148029b14bc61ed347c30d --- /dev/null +++ b/ImageKit/ImageNativeSample/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. + */ +{ + "app": { + "signingConfigs": [], + "products": [ + { + "name": "default", + "signingConfig": "default", + "targetSdkVersion": "6.0.0(20)", + "compatibleSdkVersion": "6.0.0(20)", + "runtimeOS": "HarmonyOS", + "buildOption": { + "nativeCompiler": "BiSheng", + "strictMode": { + "caseSensitiveCheck": true, + "useNormalizedOHMUrl": true + } + } + } + ], + "buildModeSet": [ + { + "name": "debug", + }, + { + "name": "release" + } + ] + }, + "modules": [ + { + "name": "entry", + "srcPath": "./entry", + "targets": [ + { + "name": "default", + "applyToProducts": [ + "default" + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/code-linter.json5 b/ImageKit/ImageNativeSample/code-linter.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5c4682f8164874ec7e9cb8f99ff8b3228ffbc126 --- /dev/null +++ b/ImageKit/ImageNativeSample/code-linter.json5 @@ -0,0 +1,46 @@ +/* + * 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": { + "@security/no-unsafe-aes": "error", + "@security/no-unsafe-hash": "error", + "@security/no-unsafe-mac": "warn", + "@security/no-unsafe-dh": "error", + "@security/no-unsafe-dsa": "error", + "@security/no-unsafe-ecdsa": "error", + "@security/no-unsafe-rsa-encrypt": "error", + "@security/no-unsafe-rsa-sign": "error", + "@security/no-unsafe-rsa-key": "error", + "@security/no-unsafe-dsa-key": "error", + "@security/no-unsafe-dh-key": "error", + "@security/no-unsafe-3des": "error" + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/build-profile.json5 b/ImageKit/ImageNativeSample/entry/build-profile.json5 new file mode 100644 index 0000000000000000000000000000000000000000..586cca71074831025224098a04acbed76ccdb6ce --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/build-profile.json5 @@ -0,0 +1,62 @@ +/* + * 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": { + "resOptions": { + "copyCodeResource": { + "enable": true, + } + }, + "externalNativeOptions": { + "path": "./src/main/cpp/CMakeLists.txt", + "arguments": "", + "cppFlags": "", + "abiFilters": [ + "x86_64", + "arm64-v8a" + ] + } + }, + "buildOptionSet": [ + { + "name": "release", + "arkOptions": { + "obfuscation": { + "ruleOptions": { + "enable": false, + "files": [ + "./obfuscation-rules.txt" + ] + } + } + }, + "nativeLib": { + "debugSymbol": { + "strip": true, + "exclude": [] + } + } + }, + ], + "targets": [ + { + "name": "default" + }, + { + "name": "ohosTest", + } + ] +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/hvigorfile.ts b/ImageKit/ImageNativeSample/entry/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..f8b117a17af3b2d7cb87a7680e29e2bb8ccd5b46 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/hvigorfile.ts @@ -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 { 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. */ +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/obfuscation-rules.txt b/ImageKit/ImageNativeSample/entry/obfuscation-rules.txt new file mode 100644 index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b --- /dev/null +++ b/ImageKit/ImageNativeSample/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/ImageKit/ImageNativeSample/entry/oh-package.json5 b/ImageKit/ImageNativeSample/entry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..5b21e253af246edab8b6ef4f10938f4417e8bc25 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/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. + */ +{ + "name": "entry", + "version": "1.0.0", + "description": "Please describe the basic information.", + "main": "", + "author": "", + "license": "", + "dependencies": { + "libentry.so": "file:./src/main/cpp/types/libentry" + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/CMakeLists.txt b/ImageKit/ImageNativeSample/entry/src/main/cpp/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..2d5c09404d43a4fe1cb687974681c4520bc6e604 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/CMakeLists.txt @@ -0,0 +1,34 @@ +# the minimum version of CMake. +cmake_minimum_required(VERSION 3.5.0) +project(ImageNativeModuleSample) + +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) +add_library(entry SHARED + napi_init.cpp + loadPicture.cpp + loadAllocator.cpp + loadImageSource.cpp + loadReceiver.cpp + ) +target_link_libraries( + entry PUBLIC + libace_napi.z.so + libhilog_ndk.z.so + libimage_source.so + libpixelmap.so + libimage_packer.so + libohimage.so + libpicture.so + libimage_common.so + libimage_receiver_ndk.z.so + libimage_receiver.so + libnative_buffer.so + libohcamera.so + libohfileuri.so) \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/imageKits.h b/ImageKit/ImageNativeSample/entry/src/main/cpp/imageKits.h new file mode 100644 index 0000000000000000000000000000000000000000..2c87fa7e948007e1572f63592f121a8e58795a7b --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/imageKits.h @@ -0,0 +1,95 @@ +#ifndef IMAGEKITS_H +#define IMAGEKITS_H +/* + * 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 +#include +#include +#include +#include + +#undef LOG_DOMAIN +#undef LOG_TAG +#define LOG_DOMAIN 0x00000 // 全局domain宏,标识业务领域。 +#define LOG_TAG "IMAGE_SAMPLE" // 全局tag宏,标识模块日志tag。 + +// decodingPixelMap +extern napi_value GetJsResult(napi_env env, int result); +extern napi_value ReturnErrorCode(napi_env env, Image_ErrorCode errCode, std::string funcName); +extern napi_value GetSupportedFormats(napi_env env, napi_callback_info info); +extern napi_value CreateImageSource(napi_env env, napi_callback_info info); +extern napi_value GetImageInfo(napi_env env, napi_callback_info info); +extern napi_value GetImageProperty(napi_env env, napi_callback_info info); +extern napi_value ModifyImageProperty(napi_env env, napi_callback_info info); +extern napi_value CreatePixelMap(napi_env env, napi_callback_info info); +extern napi_value GetFrameCount(napi_env env, napi_callback_info info); +extern napi_value CreatePixelmapList(napi_env env, napi_callback_info info); +extern napi_value GetDelayTimeList(napi_env env, napi_callback_info info); +extern napi_value ReleaseImageSource(napi_env env, napi_callback_info info); +extern void ShowPixelMap(OH_PixelmapNative *pixelmap, uint8_t *buffer, size_t pixelsBufferSize); +napi_value TestStrideWithAllocatorType(napi_env env, napi_callback_info info); +// decodingPicture +extern napi_value ReleasePictureSource(napi_env env, napi_callback_info info); +extern napi_value SetDesiredAuxiliaryPictures(napi_env env, napi_callback_info info); +extern napi_value CreatePictureByImageSource(napi_env env, napi_callback_info info); +// encodingPixelMap +extern Image_ErrorCode packToFileFromImageSourceTest(int fd); +extern Image_MimeType GetMimeTypeIfEncodable(const char *format); +extern Image_ErrorCode packToFileFromPixelmapTest(uint8_t *buffer, size_t bufferSize, int fd); +extern napi_value PackToFileFromImageSourceTestJs(napi_env env, napi_callback_info info); +extern napi_value PackToFileFromPixelmapTestJs(napi_env env, napi_callback_info info); +// encodingPicture +extern napi_value PackToDataFromPicture(napi_env env, napi_callback_info info); +extern napi_value PackToFileFromPicture(napi_env env, napi_callback_info info); +// [Start define_sourceClass] +class ImageSourceNative { +public: + OH_ImageSource_Info *imageInfo; + OH_ImageSourceNative *source = nullptr; + OH_PixelmapNative *resPixMap = nullptr; + OH_Pixelmap_ImageInfo *pixelmapImageInfo = nullptr; + uint32_t frameCnt = 0; + ImageSourceNative() {} + ~ImageSourceNative() {} +}; +// [End define_sourceClass] + +// [Start define_pictureClass] +class ImagePictureNative { +public: + Image_ErrorCode errorCode = IMAGE_SUCCESS; + OH_DecodingOptionsForPicture *options = nullptr; + OH_ImagePackerNative *imagePacker = nullptr; + OH_PackingOptions *packerOptions = nullptr; + OH_PictureNative *picture = nullptr; + OH_ImageSourceNative *source = nullptr; + ImagePictureNative() {} + ~ImagePictureNative() {} +}; +// [End define_pictureClass] + +// [Start define_auxPictureClass] +class ImageAuxiliaryPictureNative { +public: + Image_ErrorCode errorCode = IMAGE_SUCCESS; + Image_AuxiliaryPictureType type = AUXILIARY_PICTURE_TYPE_GAINMAP; + OH_AuxiliaryPictureNative *auxiliaryPicture = nullptr; + size_t buffSize = 640 * 480 * 4; // 辅助图size:`长 * 宽 * 每个像素占用的字节数`。 + ImageAuxiliaryPictureNative() {} + ~ImageAuxiliaryPictureNative() {} +}; +// [End define_auxPictureClass] +#endif // IMAGEKITS_H diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/loadAllocator.cpp b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadAllocator.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c4f62cec360b85755622fe14cc6dface450eb8c0 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadAllocator.cpp @@ -0,0 +1,154 @@ +/* + * 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. + */ +// [Start allocator_operations] +#include +#include +#include +#include +#include +// [StartExclude allocator_operations_import] +#include +// [EndExclude allocator_operations_import] + +// 根据像素格式返回每像素的字节数 +int32_t GetPixelFormatBytes(int32_t pixelFormat) +{ + switch (pixelFormat) { + case PIXEL_FORMAT_RGB_565: + return 2; // 每像素2字节。 + case PIXEL_FORMAT_RGBA_8888: + case PIXEL_FORMAT_BGRA_8888: + return 4; // 每像素4字节。 + case PIXEL_FORMAT_RGB_888: + return 3; // 每像素3字节。 + case PIXEL_FORMAT_ALPHA_8: + return 1; // 每像素1字节。 + case PIXEL_FORMAT_RGBA_F16: + return 8; // 每通道16位浮点数,共4通道,合计8字节。 + case PIXEL_FORMAT_NV21: + case PIXEL_FORMAT_NV12: + // NV21和NV12格式是YUV 4:2:0半平面格式,返回2作为每像素字节。 + return 2; // 每像素2字节(简化处理)。 + case PIXEL_FORMAT_RGBA_1010102: + return 4; // 每像素4字节。 + case PIXEL_FORMAT_YCBCR_P010: + case PIXEL_FORMAT_YCRCB_P010: + return 2; // 每像素2字节。 + default: + return 0; // 如果像素格式未知,返回0。 + } +} + +struct PixelmapInfo { + uint32_t width = 0; + uint32_t height = 0; + uint32_t rowStride = 0; + int32_t pixelFormat = 0; + uint32_t byteCount = 0; + uint32_t allocationByteCount = 0; +}; + +static void GetPixelmapInfo(OH_PixelmapNative *pixelmap, PixelmapInfo *info) +{ + OH_Pixelmap_ImageInfo *srcInfo = nullptr; + OH_PixelmapImageInfo_Create(&srcInfo); + OH_PixelmapNative_GetImageInfo(pixelmap, srcInfo); + OH_PixelmapImageInfo_GetWidth(srcInfo, &info->width); + OH_PixelmapImageInfo_GetHeight(srcInfo, &info->height); + OH_PixelmapImageInfo_GetRowStride(srcInfo, &info->rowStride); + OH_PixelmapImageInfo_GetPixelFormat(srcInfo, &info->pixelFormat); + OH_PixelmapImageInfo_Release(srcInfo); + srcInfo = nullptr; + return; +} + +static void GetPixelmapAddrInfo(OH_PixelmapNative *pixelmap, PixelmapInfo *info) +{ + OH_PixelmapNative_GetByteCount(pixelmap, &info->byteCount); + OH_PixelmapNative_GetAllocationByteCount(pixelmap, &info->allocationByteCount); + return; +} + +void DataCopy(OH_PixelmapNative *pixelmap, OH_ImageSourceNative* imageSource, OH_DecodingOptions *options, + IMAGE_ALLOCATOR_TYPE allocatorType) +{ + PixelmapInfo srcInfo; + GetPixelmapInfo(pixelmap, &srcInfo); + GetPixelmapAddrInfo(pixelmap, &srcInfo); + + void *pixels = nullptr; + OH_PixelmapNative_AccessPixels(pixelmap, &pixels); + OH_PixelmapNative *newPixelmap = nullptr; + OH_ImageSourceNative_CreatePixelmap(imageSource, options, &newPixelmap); + uint32_t dstRowStride = srcInfo.width * GetPixelFormatBytes(srcInfo.pixelFormat); + void *newPixels = nullptr; + OH_PixelmapNative_AccessPixels(newPixelmap, &newPixels); + uint8_t *src = reinterpret_cast(pixels); + uint8_t *dst = reinterpret_cast(newPixels); + uint32_t dstSize = srcInfo.byteCount; + uint32_t rowSize; + if (allocatorType == IMAGE_ALLOCATOR_TYPE::IMAGE_ALLOCATOR_TYPE_DMA) { + rowSize = srcInfo.rowStride; + } else { + rowSize = dstRowStride; + } + for (uint32_t i = 0; i < srcInfo.height; ++i) { + if (dstSize >= dstRowStride) { + std::copy(src, src + dstRowStride, dst); + } else { + break; + } + src += rowSize; + dst += dstRowStride; + dstSize -= dstRowStride; + } + OH_PixelmapNative_UnaccessPixels(newPixelmap); + OH_PixelmapNative_UnaccessPixels(pixelmap); + OH_DecodingOptions_Release(options); + options =nullptr; + OH_ImageSourceNative_Release(imageSource); + imageSource = nullptr; + OH_PixelmapNative_Release(pixelmap); + pixelmap = nullptr; + OH_PixelmapNative_Release(newPixelmap); + newPixelmap = nullptr; +} + +napi_value TestStrideWithAllocatorType(napi_env env, napi_callback_info info) +{ + napi_value argValue[1] = {nullptr}; + size_t argCount = 1; + if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < 1 || + argValue[0] == nullptr) { + OH_LOG_ERROR(LOG_APP, "CreateImageSource napi_get_cb_info failed!"); + return GetJsResult(env, IMAGE_BAD_PARAMETER); + } + + const size_t maxPathLength = 1024; + char filePath[maxPathLength]; + size_t pathSize = maxPathLength; + napi_get_value_string_utf8(env, argValue[0], filePath, maxPathLength, &pathSize); + + OH_ImageSourceNative* imageSource = nullptr; + Image_ErrorCode image_ErrorCode = OH_ImageSourceNative_CreateFromUri(filePath, pathSize, &imageSource); + OH_DecodingOptions *options = nullptr; + OH_DecodingOptions_Create(&options); + IMAGE_ALLOCATOR_TYPE allocatorType = IMAGE_ALLOCATOR_TYPE::IMAGE_ALLOCATOR_TYPE_DMA; // 使用DMA创建pixelMap。 + OH_PixelmapNative *pixelmap = nullptr; + image_ErrorCode = OH_ImageSourceNative_CreatePixelmapUsingAllocator(imageSource, options, allocatorType, &pixelmap); + DataCopy(pixelmap, imageSource, options, allocatorType); + return GetJsResult(env, image_ErrorCode); +} +// [End allocator_operations] diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/loadImageSource.cpp b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadImageSource.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5e3919ffaa3461718c851efb977543b108ed051f --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadImageSource.cpp @@ -0,0 +1,419 @@ +/* + * 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. + */ +// [Start packSource_import] +// [Start decodingPixel_import] +// [Start editExif_operations_import] +#include +#include +#include +// [End editExif_operations_import] +#include +#include +// [End decodingPixel_import] +#include +#include +// [End packSource_import] +#include +#include "napi/native_api.h" + +// [Start define_logInfo] +#undef LOG_DOMAIN +#undef LOG_TAG +#define LOG_DOMAIN 0x3200 +#define LOG_TAG "IMAGE_SAMPLE" +// [End define_logInfo] + +// [Start packSource_supportedFormats] +static std::set g_encodeSupportedFormats; +// [End packSource_supportedFormats] +// [Start create_sourceClass] +static ImageSourceNative *g_thisImageSource = new ImageSourceNative(); +// [End create_sourceClass] + +// [Start decodingPixel_operations] +const int MAX_STRING_LENGTH = 1024; +// 处理napi返回值。 +napi_value ReturnErrorCode(napi_env env, Image_ErrorCode errCode, std::string funcName) +{ + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "%{public}s failed, errCode: %{public}d.", funcName.c_str(), errCode); + return GetJsResult(env, errCode); + } + return GetJsResult(env, errCode); +} + +// 获取解码能力范围。 +napi_value GetSupportedFormats(napi_env env, napi_callback_info info) +{ + Image_MimeType* mimeType = nullptr; + size_t length = 10; + Image_ErrorCode errCode = OH_ImageSourceNative_GetSupportedFormats(&mimeType, &length); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImageSourceNative_GetSupportedFormats failed, " + "errCode: %{public}d.", errCode); + return GetJsResult(env, errCode); + } + for (size_t count = 0; count < length; count++) { + OH_LOG_INFO(LOG_APP, "Decode supportedFormats: %{public}s", mimeType[count].data); + } + return GetJsResult(env, errCode); +} + +// 创建ImageSource实例。 +napi_value CreateImageSource(napi_env env, napi_callback_info info) +{ + napi_value argValue[1] = {nullptr}; + size_t argCount = 1; + if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < 1 || + argValue[0] == nullptr) { + OH_LOG_ERROR(LOG_APP, "CreateImageSource napi_get_cb_info failed!"); + return GetJsResult(env, IMAGE_BAD_PARAMETER); + } + + char name[MAX_STRING_LENGTH]; + size_t nameSize = MAX_STRING_LENGTH; + napi_get_value_string_utf8(env, argValue[0], name, MAX_STRING_LENGTH, &nameSize); + + Image_ErrorCode errCode = OH_ImageSourceNative_CreateFromUri(name, nameSize, &g_thisImageSource->source); + return ReturnErrorCode(env, errCode, "OH_ImageSourceNative_CreateFromUri"); +} + +// 创建定义图片信息的结构体对象,并获取图片信息。 +napi_value GetImageInfo(napi_env env, napi_callback_info info) +{ + OH_ImageSourceInfo_Create(&g_thisImageSource->imageInfo); + Image_ErrorCode errCode = OH_ImageSourceNative_GetImageInfo(g_thisImageSource->source, + 0, g_thisImageSource->imageInfo); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImageSourceInfo_Create failed, errCode: %{public}d.", errCode); + return GetJsResult(env, errCode); + } + + uint32_t width; + uint32_t height; + OH_ImageSourceInfo_GetWidth(g_thisImageSource->imageInfo, &width); + OH_ImageSourceInfo_GetHeight(g_thisImageSource->imageInfo, &height); + OH_LOG_INFO(LOG_APP, "OH_ImageSourceNative_GetImageInfo success," + "width: %{public}d, height: %{public}d.", width, height); + OH_ImageSourceInfo_Release(g_thisImageSource->imageInfo); + g_thisImageSource->imageInfo = nullptr; + return GetJsResult(env, width); // 返回获取到info信息的width。 +} + +// [Start editExif_operations] +// 获取指定property的value值。 +napi_value GetImageProperty(napi_env env, napi_callback_info info) +{ + napi_value argValue[1] = {nullptr}; + size_t argCount = 1; + if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < 1 || + argValue[0] == nullptr) { + OH_LOG_ERROR(LOG_APP, "GetImageProperty napi_get_cb_info failed!"); + return GetJsResult(env, IMAGE_BAD_PARAMETER); + } + // 修改指定属性键的值。 + char key[MAX_STRING_LENGTH]; + size_t keySize = MAX_STRING_LENGTH; + napi_get_value_string_utf8(env, argValue[0], (char *)key, sizeof(key), &keySize); + Image_String getKey; + getKey.data = key; + getKey.size = keySize; + Image_String getValue; + OH_LOG_INFO(LOG_APP, "OH_ImageSourceNative_GetImageProperty key: %{public}s.", getKey.data); + Image_ErrorCode errCode = OH_ImageSourceNative_GetImageProperty(g_thisImageSource->source, &getKey, &getValue); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImageSourceNative_GetImageProperty failed, errCode: %{public}d.", errCode); + return GetJsResult(env, errCode); + } + napi_value resultNapi = nullptr; + napi_create_string_utf8(env, getValue.data, getValue.size, &resultNapi); + return resultNapi; +} + +// 修改指定property的value值。 +napi_value ModifyImageProperty(napi_env env, napi_callback_info info) +{ + napi_value argValue[2] = {nullptr}; + size_t argCount = 2; + const size_t minCount = 2; + if (napi_get_cb_info(env, info, &argCount, argValue, nullptr, nullptr) != napi_ok || argCount < minCount || + argValue[0] == nullptr || argValue[1] == nullptr) { + OH_LOG_ERROR(LOG_APP, "ModifyImageProperty napi_get_cb_info failed!"); + return GetJsResult(env, IMAGE_BAD_PARAMETER); + } + + // 获取要修改的key值。 + char key[MAX_STRING_LENGTH]; + size_t keySize = MAX_STRING_LENGTH; + napi_get_value_string_utf8(env, argValue[0], (char *)key, sizeof(key), &keySize); + Image_String setKey; + setKey.data = key; + setKey.size = keySize; + OH_LOG_INFO(LOG_APP, "ModifyImageProperty key: %{public}s.", setKey.data); + + // 获取要修改的value值。 + char value[MAX_STRING_LENGTH]; + size_t valueSize; + napi_get_value_string_utf8(env, argValue[1], (char *)value, MAX_STRING_LENGTH, &valueSize); + Image_String setValue; + setValue.data = value; + setValue.size = valueSize; + OH_LOG_INFO(LOG_APP, "ModifyImageProperty value: %{public}s.", setValue.data); + + Image_ErrorCode errCode = OH_ImageSourceNative_ModifyImageProperty(g_thisImageSource->source, &setKey, &setValue); + return ReturnErrorCode(env, errCode, "OH_ImageSourceNative_ModifyImageProperty"); +} +// [End editExif_operations] + +// 通过图片解码参数创建PixelMap对象。 +napi_value CreatePixelMap(napi_env env, napi_callback_info info) +{ + // ops参数支持传入nullptr, 当不需要设置解码参数时,不用创建。 + OH_DecodingOptions *ops = nullptr; + OH_DecodingOptions_Create(&ops); + // 设置为AUTO会根据图片资源格式和设备支持情况进行解码,如果图片资源为HDR资源且设备支持HDR解码则会解码为HDR的pixelmap。 + OH_DecodingOptions_SetDesiredDynamicRange(ops, IMAGE_DYNAMIC_RANGE_AUTO); + + OH_PixelmapNative_Release(g_thisImageSource->resPixMap); + g_thisImageSource->resPixMap = nullptr; + + Image_ErrorCode errCode = OH_ImageSourceNative_CreatePixelmap(g_thisImageSource->source, + ops, &g_thisImageSource->resPixMap); + OH_DecodingOptions_Release(ops); + ops = nullptr; + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImageSourceNative_CreatePixelmap failed, errCode: %{public}d.", errCode); + return GetJsResult(env, errCode); + } + + // 判断pixelmap是否为HDR内容。 + OH_PixelmapImageInfo_Create(&g_thisImageSource->pixelmapImageInfo); + OH_PixelmapNative_GetImageInfo(g_thisImageSource->resPixMap, g_thisImageSource->pixelmapImageInfo); + bool pixelmapIsHdr; + OH_PixelmapImageInfo_GetDynamicRange(g_thisImageSource->pixelmapImageInfo, &pixelmapIsHdr); + if (pixelmapIsHdr) { + OH_LOG_INFO(LOG_APP, "The pixelMap's dynamicRange is HDR."); + } + OH_PixelmapImageInfo_Release(g_thisImageSource->pixelmapImageInfo); + g_thisImageSource->pixelmapImageInfo = nullptr; + return GetJsResult(env, errCode); +} + +// 获取图像帧数。 +napi_value GetFrameCount(napi_env env, napi_callback_info info) +{ + Image_ErrorCode errCode = OH_ImageSourceNative_GetFrameCount(g_thisImageSource->source, + &g_thisImageSource->frameCnt); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImageSourceNative_GetFrameCount failed, errCode: %{public}d.", errCode); + return GetJsResult(env, errCode); + } + return GetJsResult(env, g_thisImageSource->frameCnt); // 返回获取到的图像帧数。 +} + +// 通过图片解码参数创建Pixelmap列表。 +napi_value CreatePixelmapList(napi_env env, napi_callback_info info) +{ + OH_DecodingOptions *opts = nullptr; + OH_DecodingOptions_Create(&opts); + OH_PixelmapNative** resVecPixMap = new OH_PixelmapNative* [g_thisImageSource->frameCnt]; + size_t outSize = g_thisImageSource->frameCnt; + Image_ErrorCode errCode = OH_ImageSourceNative_CreatePixelmapList(g_thisImageSource->source, + opts, resVecPixMap, outSize); + OH_DecodingOptions_Release(opts); + opts = nullptr; + delete[] resVecPixMap; + return ReturnErrorCode(env, errCode, "OH_ImageSourceNative_CreatePixelmapList"); +} + +// 获取图像延迟时间列表。 +napi_value GetDelayTimeList(napi_env env, napi_callback_info info) +{ + int32_t *delayTimeList = new int32_t[g_thisImageSource->frameCnt]; + size_t size = g_thisImageSource->frameCnt; + OH_LOG_INFO(LOG_APP, "GetDelayTimeList size: %{public}zu.", size); + Image_ErrorCode errCode = OH_ImageSourceNative_GetDelayTimeList(g_thisImageSource->source, delayTimeList, size); + delete[] delayTimeList; + return ReturnErrorCode(env, errCode, "OH_ImageSourceNative_GetDelayTimeList"); +} + +// 释放资源。 +napi_value ReleaseImageSource(napi_env env, napi_callback_info info) +{ + Image_ErrorCode errCode = OH_ImageSourceNative_Release(g_thisImageSource->source); + g_thisImageSource->source = nullptr; + OH_PixelmapNative_Release(g_thisImageSource->resPixMap); + g_thisImageSource->resPixMap = nullptr; + return ReturnErrorCode(env, errCode, "OH_ImageSourceNative_Release"); +} +// [End decodingPixel_operations] + +// [Start pack_source] +Image_MimeType GetMimeTypeIfEncodable(const char *format) +{ + auto it = g_encodeSupportedFormats.find(format); + if (it == g_encodeSupportedFormats.end()) { + return {const_cast(""), 0}; + } + return {const_cast(format), strlen(format)}; +} + +Image_ErrorCode packToFileFromImageSourceTest(int fd, OH_ImageSourceNative* imageSource) +{ + //创建ImagePacker实例。 + OH_ImagePackerNative *testPacker = nullptr; + Image_ErrorCode errCode = OH_ImagePackerNative_Create(&testPacker); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromImageSourceTest OH_ImagePackerNative_Create failed," + "errCode: %{public}d.", errCode); + return errCode; + } + + // 获取编码能力范围。 + Image_MimeType* mimeType = nullptr; + size_t length = 0; + errCode = OH_ImagePackerNative_GetSupportedFormats(&mimeType, &length); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromImageSourceTest OH_ImagePackerNative_GetSupportedFormats failed," + "errCode: %{public}d.", errCode); + return errCode; + } + for (size_t count = 0; count < length; count++) { + OH_LOG_INFO(LOG_APP, "Encode supportedFormats:%{public}s", mimeType[count].data); + if (mimeType[count].data != nullptr) { + g_encodeSupportedFormats.insert(std::string(mimeType[count].data)); + } + } + + // 指定编码参数,将ImageSource直接编码进文件。 + OH_PackingOptions *option = nullptr; + OH_PackingOptions_Create(&option); + Image_MimeType image_MimeType = GetMimeTypeIfEncodable(MIME_TYPE_JPEG); + if (image_MimeType.data == nullptr || image_MimeType.size == 0) { + OH_LOG_ERROR(LOG_APP, "packToFileFromImageSourceTest GetMimeTypeIfEncodable failed," + "format can't support encode."); + return IMAGE_BAD_PARAMETER; + } + OH_PackingOptions_SetMimeType(option, &image_MimeType); + // 当设备支持HDR编码,资源本身为HDR图且图片资源的格式为jpeg时,编码产物才能为HDR内容。 + OH_PackingOptions_SetDesiredDynamicRange(option, IMAGE_PACKER_DYNAMIC_RANGE_AUTO); + + // 释放ImagePacker实例。 + errCode = OH_ImagePackerNative_Release(testPacker); + testPacker = nullptr; + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromImageSourceTest OH_ImagePackerNative_Release failed," + "errCode: %{public}d.", errCode); + return errCode; + } + + // 释放PackingOptions实例。 + errCode = OH_PackingOptions_Release(option); + option = nullptr; + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromImageSourceTest OH_PackingOptions_Release failed," + "errCode: %{public}d.", errCode); + return errCode; + } + return IMAGE_SUCCESS; +} + +Image_ErrorCode packToFileFromPixelmapTest(int fd, OH_PixelmapNative *pixelmap) +{ + // 创建ImagePacker实例。 + OH_ImagePackerNative *testPacker = nullptr; + Image_ErrorCode errCode = OH_ImagePackerNative_Create(&testPacker); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromPixelmapTest CreatePacker OH_ImagePackerNative_Create failed," + "errCode: %{public}d.", errCode); + return errCode; + } + + // 指定编码参数,将PixelMap直接编码进文件。 + OH_PackingOptions *option = nullptr; + OH_PackingOptions_Create(&option); + char type[] = "image/jpeg"; + Image_MimeType image_MimeType = {type, strlen(type)}; + OH_PackingOptions_SetMimeType(option, &image_MimeType); + errCode = OH_ImagePackerNative_PackToFileFromPixelmap(testPacker, option, pixelmap, fd); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromPixelmapTest OH_ImagePackerNative_PackToFileFromPixelmap failed," + "errCode: %{public}d.", errCode); + return errCode; + } + + // 释放ImagePacker实例。 + errCode = OH_ImagePackerNative_Release(testPacker); + testPacker = nullptr; + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromPixelmapTest ReleasePacker OH_ImagePackerNative_Release failed," + "errCode: %{public}d.", errCode); + return errCode; + } + + // 释放PackingOptions实例。 + errCode = OH_PackingOptions_Release(option); + option = nullptr; + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromPixelmapTest OH_PackingOptions_Release failed," + "errCode: %{public}d.", errCode); + return errCode; + } + + return IMAGE_SUCCESS; +} + +napi_value PackToFileFromImageSourceTestJs(napi_env env, napi_callback_info info) +{ + napi_value argv[1] = {0}; + size_t argc = 1; + if (napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok) { + OH_LOG_ERROR(LOG_APP, "PackToFileFromImageSourceTestJs napi_get_cb_info failed."); + return nullptr; + } + + int fd; + napi_get_value_int32(env, argv[0], &fd); + + Image_ErrorCode errCode = packToFileFromImageSourceTest(fd, g_thisImageSource->source); + if (errCode == IMAGE_SUCCESS) { + OH_LOG_INFO(LOG_APP, "ImagePackerNativeCTest PackToFileFromImageSourceTestJs successfully."); + } + return GetJsResult(env, errCode); +} + +napi_value PackToFileFromPixelmapTestJs(napi_env env, napi_callback_info info) +{ + napi_value argv[1] = {0}; + size_t argc = 1; + if (napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr) != napi_ok) { + OH_LOG_ERROR(LOG_APP, "PackToFileFromImageSourceTestJs napi_get_cb_info failed."); + return nullptr; + } + + int fd; + napi_get_value_int32(env, argv[0], &fd); + + Image_ErrorCode errCode = packToFileFromPixelmapTest(fd, g_thisImageSource->resPixMap); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "packToFileFromPixelmapTest failed," + "errCode: %{public}d.", errCode); + return GetJsResult(env, errCode); + } else { + OH_LOG_INFO(LOG_APP, "PackToFileFromPixelmapTestJs successfully."); + } + return GetJsResult(env, errCode); +} +// [End pack_source] diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/loadPicture.cpp b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadPicture.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5b01c879df19160ab5c92df203074bd27b7b85f4 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadPicture.cpp @@ -0,0 +1,288 @@ +/* + * 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. + */ +// [Start decodingPicture_import] +#include +#include +#include +#include +#include +#include +// [End decodingPicture_import] +// [Start define_const] +#define AUTO 0 +#define SDR 1 +const int MAX_SIZE = 1024; +const int MAX_FORMAT_LENGTH = 20; +// [End define_const] +#include +// [Start create_pictureClass] +static ImagePictureNative *g_thisPicture = new ImagePictureNative(); +// [End create_pictureClass] +// [Start create_auxPictureClass] +static ImageAuxiliaryPictureNative *g_thisAuxiliaryPicture = new ImageAuxiliaryPictureNative(); +// [End create_auxPictureClass] + +// [Start picture_operations] +// 释放ImageSource。 +napi_value ReleasePictureSource(napi_env env, napi_callback_info info) +{ + if (g_thisPicture->source != nullptr) { + g_thisPicture->errorCode = OH_ImageSourceNative_Release(g_thisPicture->source); + g_thisPicture->source = nullptr; + return GetJsResult(env, g_thisPicture->errorCode); + } + + if (g_thisPicture->picture != nullptr) { + g_thisPicture->errorCode = OH_PictureNative_Release(g_thisPicture->picture); + g_thisPicture->picture = nullptr; + return GetJsResult(env, g_thisPicture->errorCode); + } + + OH_LOG_DEBUG(LOG_APP, "ReleasePictureSource source is null !"); + return GetJsResult(env, g_thisPicture->errorCode); +} + +// 创造解码参数。 +napi_value CreateDecodingOptions(napi_env env, napi_callback_info info) +{ + g_thisPicture->errorCode = OH_DecodingOptionsForPicture_Create(&g_thisPicture->options); + + if (g_thisPicture->errorCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_DecodingOptionsForPicture_Create failed, errCode: %{public}d.", + g_thisPicture->errorCode); + return GetJsResult(env, g_thisPicture->errorCode); + } else { + OH_LOG_DEBUG(LOG_APP, "OH_DecodingOptionsForPicture_Create success !"); + } + + return GetJsResult(env, g_thisPicture->errorCode); +} + +// 配置解码参数 从应用层传入。 +napi_value SetDesiredAuxiliaryPictures(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok || argc < 1 || args[0] == nullptr) { + OH_LOG_ERROR(LOG_APP, "napi_get_cb_info failed !"); + return GetJsResult(env, IMAGE_BAD_PARAMETER); + } + + uint32_t length = 0; + napi_get_array_length(env, args[0], &length); + if (length <= 0) { + OH_LOG_ERROR(LOG_APP, "napi_get_array_length failed !"); + return GetJsResult(env, IMAGE_UNKNOWN_ERROR); + } + Image_AuxiliaryPictureType typeList[length]; + for (int index = 0; index < length; index++) { + napi_value element; + uint32_t ulType = 0; + napi_get_element(env, args[0], index, &element); + napi_get_value_uint32(env, element, &ulType); + typeList[index] = static_cast(ulType); + OH_LOG_DEBUG(LOG_APP, "ulType is :%{public}d", ulType); + } + + // 调用OH_DecodingOptionsForPicture_Create接口创建DecodingOptions。 + CreateDecodingOptions(env, info); + g_thisPicture->errorCode = + OH_DecodingOptionsForPicture_SetDesiredAuxiliaryPictures(g_thisPicture->options, typeList, length); + if (g_thisPicture->errorCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_DecodingOptionsForPicture_SetDesiredAuxiliaryPictures failed,errCode: %{public}d.", + g_thisPicture->errorCode); + return GetJsResult(env, g_thisPicture->errorCode); + } else { + OH_LOG_DEBUG(LOG_APP, "OH_DecodingOptionsForPicture_SetDesiredAuxiliaryPictures success !"); + } + + return GetJsResult(env, g_thisPicture->errorCode); +} + +// 解码。 +napi_value CreatePictureByImageSource(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok || argc < 1 || args[0] == nullptr) { + OH_LOG_ERROR(LOG_APP, "CreatePicture_ napi_get_cb_info failed !"); + return GetJsResult(env, IMAGE_BAD_PARAMETER); + } + + char filePath[MAX_SIZE]; + size_t pathSize; + napi_get_value_string_utf8(env, args[0], filePath, MAX_SIZE, &pathSize); + + g_thisPicture->errorCode = OH_ImageSourceNative_CreateFromUri(filePath, pathSize, &g_thisPicture->source); + if (g_thisPicture->errorCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImageSourceNative_CreateFromUri failed, errCode: %{public}d.", + g_thisPicture->errorCode); + return GetJsResult(env, g_thisPicture->errorCode); + } else { + OH_LOG_DEBUG(LOG_APP, "OH_ImageSourceNative_CreateFromUri success !"); + } + + // 先创建解码参数,再进行解码,此处创建解码参数的接口在SetDesiredAuxiliaryPictures实现。 + g_thisPicture->errorCode = + OH_ImageSourceNative_CreatePicture(g_thisPicture->source, g_thisPicture->options, &g_thisPicture->picture); + + // 释放options。 + OH_DecodingOptionsForPicture_Release(g_thisPicture->options); + g_thisPicture->options = nullptr; + + g_thisAuxiliaryPicture ->errorCode = OH_PictureNative_GetAuxiliaryPicture(g_thisPicture->picture, + g_thisAuxiliaryPicture ->type, &g_thisAuxiliaryPicture ->auxiliaryPicture); + if (g_thisAuxiliaryPicture ->errorCode == IMAGE_SUCCESS) { + uint8_t* buff = new uint8_t[g_thisAuxiliaryPicture ->buffSize]; + OH_AuxiliaryPictureNative_ReadPixels(g_thisAuxiliaryPicture ->auxiliaryPicture, buff, + &g_thisAuxiliaryPicture ->buffSize); + OH_AuxiliaryPictureNative_Release(g_thisAuxiliaryPicture ->auxiliaryPicture); + g_thisAuxiliaryPicture ->auxiliaryPicture = nullptr; + delete []buff; + } + + if (g_thisPicture->errorCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "ImageSourceNative_CreatePicture failed, errCode: %{public}d.", + g_thisPicture->errorCode); + return GetJsResult(env, g_thisPicture->errorCode); + } else { + OH_LOG_DEBUG(LOG_APP, "ImageSourceNative_CreatePicture success !"); + } + + return GetJsResult(env, g_thisPicture->errorCode); +} +// [End picture_operations] + +// [Start pack_picture] +// 设置编码参数。 +void SetPackOptions(OH_PackingOptions *packerOptions, + Image_MimeType format, + uint32_t quality, + bool needsPackProperties, + int32_t desiredDynamicRange) +{ + OH_PackingOptions_SetMimeType(packerOptions, &format); + OH_PackingOptions_SetQuality(packerOptions, quality); + OH_PackingOptions_SetNeedsPackProperties(packerOptions, needsPackProperties); + OH_PackingOptions_SetDesiredDynamicRange(packerOptions, desiredDynamicRange); +} + +// PackToData。 +napi_value PackToDataFromPicture(napi_env env, napi_callback_info info) +{ + size_t argc = 1; + napi_value args[1] = {nullptr}; + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { + OH_LOG_ERROR(LOG_APP, "napi_get_cb_info failed!"); + return GetJsResult(env, g_thisPicture->errorCode); + } + + size_t outDataSize = 10000 * 10000; + uint8_t *outData = new uint8_t[outDataSize]; + + if (g_thisPicture->packerOptions == nullptr) { + g_thisPicture->errorCode = OH_PackingOptions_Create(&g_thisPicture->packerOptions); + } + if (g_thisPicture->imagePacker == nullptr) { + g_thisPicture->errorCode = OH_ImagePackerNative_Create(&g_thisPicture->imagePacker); + } + + char strFormat[MAX_FORMAT_LENGTH]; + size_t strFormatSize; + napi_get_value_string_utf8(env, args[0], strFormat, MAX_FORMAT_LENGTH, &strFormatSize); + OH_LOG_DEBUG(LOG_APP, "PackToDataFromPicture format: %{public}s", strFormat); + + Image_MimeType format; + format.size = strFormatSize; + format.data = const_cast(strFormat); + uint32_t quality = 95; + bool needsPackProperties = true; + int32_t desiredDynamicRange = AUTO; + SetPackOptions(g_thisPicture->packerOptions, format, quality, needsPackProperties, desiredDynamicRange); + // 确保picture对象已被创建。 + g_thisPicture->errorCode = OH_ImagePackerNative_PackToDataFromPicture( + g_thisPicture->imagePacker, g_thisPicture->packerOptions, g_thisPicture->picture, outData, &outDataSize); + + // 释放imagePacker和packerOptions。 + OH_PackingOptions_Release(g_thisPicture->packerOptions); + g_thisPicture->packerOptions = nullptr; + OH_ImagePackerNative_Release(g_thisPicture->imagePacker); + g_thisPicture->imagePacker = nullptr; + + if (g_thisPicture->errorCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImagePackerNative_PackToDataFromPicture failed, errCode: %{public}d.", + g_thisPicture->errorCode); + delete[] outData; + return GetJsResult(env, g_thisPicture->errorCode); + } else { + OH_LOG_DEBUG(LOG_APP, "OH_ImagePackerNative_PackToDataFromPicture success !"); + } + delete[] outData; + return GetJsResult(env, g_thisPicture->errorCode); +} + +// PackToFile。 +napi_value PackToFileFromPicture(napi_env env, napi_callback_info info) +{ + size_t argc = 2; + napi_value args[2] = {nullptr}; + if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) { + OH_LOG_ERROR(LOG_APP, "napi_get_cb_info failed!"); + return GetJsResult(env, g_thisPicture->errorCode); + } + uint32_t fd = 0; + napi_get_value_uint32(env, args[0], &fd); + + if (g_thisPicture->packerOptions == nullptr) { + g_thisPicture->errorCode = OH_PackingOptions_Create(&g_thisPicture->packerOptions); + } + if (g_thisPicture->imagePacker == nullptr) { + g_thisPicture->errorCode = OH_ImagePackerNative_Create(&g_thisPicture->imagePacker); + } + + char strFormat[MAX_FORMAT_LENGTH]; + size_t strFormatSize; + napi_get_value_string_utf8(env, args[1], strFormat, MAX_FORMAT_LENGTH, &strFormatSize); + OH_LOG_INFO(LOG_APP, "PackToFileFromPicture format: %{public}s", strFormat); + + Image_MimeType format; + format.size = strFormatSize; + format.data = const_cast(strFormat); + uint32_t quality = 95; + bool needsPackProperties = false; + int32_t desiredDynamicRange = SDR; + SetPackOptions(g_thisPicture->packerOptions, format, quality, needsPackProperties, desiredDynamicRange); + // 确保picture对象已被创建。 + g_thisPicture->errorCode = OH_ImagePackerNative_PackToFileFromPicture( + g_thisPicture->imagePacker, g_thisPicture->packerOptions, g_thisPicture->picture, fd); + + // 释放imagePacker和packerOptions。 + OH_PackingOptions_Release(g_thisPicture->packerOptions); + g_thisPicture->packerOptions = nullptr; + OH_ImagePackerNative_Release(g_thisPicture->imagePacker); + g_thisPicture->imagePacker = nullptr; + + if (g_thisPicture->errorCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "OH_ImagePackerNative_PackToFileFromPicture failed," + "errCode: %{public}d.", g_thisPicture->errorCode); + return GetJsResult(env, g_thisPicture->errorCode); + } else { + OH_LOG_DEBUG(LOG_APP, "OH_ImagePackerNative_PackToFileFromPicture success !"); + } + + return GetJsResult(env, g_thisPicture->errorCode); +} +// [End pack_picture] diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/loadReceiver.cpp b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadReceiver.cpp new file mode 100644 index 0000000000000000000000000000000000000000..12ed1e149175985f1a6b9704fe11512b54a42af0 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadReceiver.cpp @@ -0,0 +1,567 @@ +/* + * 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. + */ +// [Start receiver_import] +#include +#include "napi/native_api.h" +#include +#include +#include + +#include "ohcamera/camera.h" +#include "ohcamera/camera_input.h" +#include "ohcamera/capture_session.h" +#include "ohcamera/photo_output.h" +#include "ohcamera/preview_output.h" +#include "ohcamera/video_output.h" +#include "ohcamera/camera_manager.h" + +#include +#include + +#undef LOG_DOMAIN +#define LOG_DOMAIN 0x3200 + +#undef LOG_TAG +#define LOG_TAG "MY_TAG" + +#define IMAGE_WIDTH 320 +#define IMAGE_HEIGHT 480 +#define IMAGE_CAPACITY 2 + +static OH_ImageReceiverNative* g_receiver = nullptr; + +static std::mutex g_mutex; +static std::condition_variable g_condVar; +static bool g_imageReady = false; +static OH_ImageNative* g_imageInfoResult = nullptr; + +napi_value GetJsResultDemo(napi_env env, int result) +{ + napi_value resultNapi = nullptr; + napi_create_int32(env, result, &resultNapi); + return resultNapi; +} + +std::unique_ptr ConvertUint64ToCharTemp(uint64_t value) +{ + std::string strValue = std::to_string(value); + auto charBuffer = std::make_unique(strValue.size() + 1); + std::copy(strValue.begin(), strValue.end(), charBuffer.get()); + charBuffer[strValue.size()] = '\0'; + + return charBuffer; +} + +// 获取图像大小。 +static napi_value GetImageSizeInfo(napi_env env, OH_ImageNative* image) +{ + OH_LOG_INFO(LOG_APP, "GetImageSizeInfo: enter, image=%{public}p", image); + + Image_Size imgSizeRead; + Image_ErrorCode errCode = OH_ImageNative_GetImageSize(image, &imgSizeRead); + OH_LOG_INFO(LOG_APP, "GetImageSizeInfo: GetImageSize errCode=%{public}d, width=%{public}d, height=%{public}d", + errCode, imgSizeRead.width, imgSizeRead.height); + + if (errCode == IMAGE_SUCCESS) { + napi_value resultObj; + napi_create_object(env, &resultObj); + + napi_value width; + napi_value height; + napi_create_int32(env, imgSizeRead.width, &width); + napi_create_int32(env, imgSizeRead.height, &height); + + napi_set_named_property(env, resultObj, "width", width); + napi_set_named_property(env, resultObj, "height", height); + + OH_LOG_INFO(LOG_APP, "GetImageSizeInfo: exit"); + return resultObj; + } + + OH_LOG_ERROR(LOG_APP, "GetImageSizeInfo: Failed to get image size"); + return nullptr; +} + +// 封装获取组件类型的函数。 +static size_t GetComponentTypeSize(OH_ImageNative* image, size_t& componentTypeSize) +{ + OH_LOG_INFO(LOG_APP, "GetComponentTypeSize: enter, image=%{public}p", image); + // 获取组件类型的大小。 + Image_ErrorCode errCode = OH_ImageNative_GetComponentTypes(image, nullptr, &componentTypeSize); + OH_LOG_INFO(LOG_APP, "GetComponentTypeSize: GetComponentTypes (query size) errCode=%{public}d," + "componentTypeSize=%{public}zu", errCode, componentTypeSize); + return componentTypeSize; +} + +// 获取组件信息。 +static napi_value GetComponentInfo(napi_env env, size_t componentTypeSize, OH_ImageNative* image, napi_value resultObj) +{ + if (componentTypeSize > 0) { + uint32_t* components = new uint32_t[componentTypeSize]; + Image_ErrorCode errCode = OH_ImageNative_GetComponentTypes(image, &components, &componentTypeSize); + OH_LOG_INFO(LOG_APP, "GetImageInfoObject: GetComponentTypes (get types) errCode=%{public}d," + "firstComponent=%{public}u", errCode, componentTypeSize > 0 ? components[0] : 0); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "GetImageInfoObject: GetComponentTypes (get types) failed"); + delete [] components; + return resultObj; + } + + OH_NativeBuffer* nativeBuffer = nullptr; + errCode = OH_ImageNative_GetByteBuffer(image, components[0], &nativeBuffer); + if (errCode == IMAGE_SUCCESS) { + OH_LOG_INFO(LOG_APP, "Get native buffer success."); + } + + size_t nativeBufferSize = 0; + errCode = OH_ImageNative_GetBufferSize(image, components[0], &nativeBufferSize); + OH_LOG_INFO(LOG_APP, "GetImageInfoObject: GetBufferSize errCode=%{public}d, nativeBufferSize=%{public}zu", + errCode, nativeBufferSize); + if (errCode == IMAGE_SUCCESS) { + napi_value bufSize; + napi_create_int32(env, static_cast(nativeBufferSize), &bufSize); + napi_set_named_property(env, resultObj, "bufferSize", bufSize); + } + + int32_t rowStride = 0; + errCode = OH_ImageNative_GetRowStride(image, components[0], &rowStride); + OH_LOG_INFO(LOG_APP, "GetImageInfoObject: GetRowStride errCode=%{public}d," + "rowStride=%{public}d", errCode, rowStride); + if (errCode == IMAGE_SUCCESS) { + napi_value jsRowStride; + napi_create_int32(env, rowStride, &jsRowStride); + napi_set_named_property(env, resultObj, "rowStride", jsRowStride); + } + + int32_t pixelStride = 0; + errCode = OH_ImageNative_GetPixelStride(image, components[0], &pixelStride); + OH_LOG_INFO(LOG_APP, "GetImageInfoObject: GetPixelStride errCode=%{public}d, pixelStride=%{public}d", + errCode, pixelStride); + if (errCode == IMAGE_SUCCESS) { + napi_value jsPixelStride; + napi_create_int32(env, pixelStride, &jsPixelStride); + napi_set_named_property(env, resultObj, "pixelStride", jsPixelStride); + } + delete [] components; + } + return resultObj; +} + +// 获取图像属性并封装为JS对象。 +static napi_value GetImageInfoObject(napi_env env, OH_ImageNative* image) +{ + OH_LOG_INFO(LOG_APP, "GetImageInfoObject: enter, image=%{public}p", image); + napi_value resultObj; + napi_create_object(env, &resultObj); + resultObj = GetImageSizeInfo(env, image); + + size_t componentTypeSize = 0; + componentTypeSize = GetComponentTypeSize(image, componentTypeSize); + if (componentTypeSize > 0) { + resultObj = GetComponentInfo(env, componentTypeSize, image, resultObj); + } + + int64_t timestamp = 0; + Image_ErrorCode errCode = OH_ImageNative_GetTimestamp(image, ×tamp); + OH_LOG_INFO(LOG_APP, "GetImageInfoObject: GetTimestamp errCode=%{public}d, timestamp=%{public}ld", + errCode, timestamp); + if (errCode == IMAGE_SUCCESS) { + napi_value jsTimestamp; + napi_create_int64(env, timestamp, &jsTimestamp); + napi_set_named_property(env, resultObj, "timestamp", jsTimestamp); + } + + OH_LOG_INFO(LOG_APP, "GetImageInfoObject: exit"); + return resultObj; +} + +// 同步等待。 +static OH_ImageNative* NotifyJsImageInfoSync() +{ + std::unique_lock lock(g_mutex); + g_imageReady = false; + g_imageInfoResult = nullptr; + + // 等待 OnCallback 回调通知 + bool ret = g_condVar.wait_for(lock, std::chrono::seconds(1), [] { + OH_LOG_INFO(LOG_APP, "NotifyJsImageInfoSync: wait_for wakeup, g_imageReady=%{public}d", g_imageReady); + return g_imageReady; + }); + if (!ret) { + OH_LOG_ERROR(LOG_APP, "NotifyJsImageInfoSync: wait_for timeout."); + return nullptr; + } + return g_imageInfoResult; +} + +static void OnCallback(OH_ImageReceiverNative* receiver) +{ + OH_LOG_INFO(LOG_APP, "ImageReceiverNativeCTest buffer available."); + + OH_ImageNative* image = nullptr; + Image_ErrorCode errCode = OH_ImageReceiverNative_ReadNextImage(receiver, &image); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "ImageReceiverNativeCTest get image receiver next image failed," + "errCode: %{public}d.", errCode); + OH_ImageNative_Release(image); + return; + } + + { + std::lock_guard lock(g_mutex); + g_imageInfoResult = image; + g_imageReady = true; + } + g_condVar.notify_one(); +} + +static Image_ErrorCode CreateReceiver(OH_ImageReceiverOptions* options, OH_ImageReceiverNative** receiver) +{ + Image_ErrorCode errCode = OH_ImageReceiverNative_Create(options, receiver); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Create image receiver failed, errCode: %{public}d.", errCode); + return errCode; + } + return IMAGE_SUCCESS; +} + +static Image_ErrorCode CreateAndConfigOptions(OH_ImageReceiverOptions** options) +{ + Image_ErrorCode errCode = OH_ImageReceiverOptions_Create(options); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Create image receiver options failed, errCode: %{public}d.", errCode); + return errCode; + } + Image_Size imgSize = {IMAGE_WIDTH, IMAGE_HEIGHT}; + errCode = OH_ImageReceiverOptions_SetSize(*options, imgSize); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Set image receiver options size failed, errCode: %{public}d.", errCode); + OH_ImageReceiverOptions_Release(*options); + return errCode; + } + errCode = OH_ImageReceiverOptions_SetCapacity(*options, IMAGE_CAPACITY); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Set image receiver options capacity failed, errCode: %{public}d.", errCode); + OH_ImageReceiverOptions_Release(*options); + return errCode; + } + return IMAGE_SUCCESS; +} + +static Image_ErrorCode ValidateOptions(OH_ImageReceiverOptions* options) +{ + Image_Size imgSizeRead; + Image_ErrorCode errCode = OH_ImageReceiverOptions_GetSize(options, &imgSizeRead); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Get image receiver options size failed, errCode: %{public}d.", errCode); + return errCode; + } + if (imgSizeRead.width != IMAGE_WIDTH || imgSizeRead.height != IMAGE_HEIGHT) { + OH_LOG_ERROR(LOG_APP, "Get image receiver options size failed," + "width: %{public}d, height: %{public}d.", imgSizeRead.width, imgSizeRead.height); + return IMAGE_BAD_PARAMETER; + } + int32_t capacity = 0; + errCode = OH_ImageReceiverOptions_GetCapacity(options, &capacity); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Get image receiver options capacity failed, errCode: %{public}d.", errCode); + return errCode; + } + if (capacity != IMAGE_CAPACITY) { + OH_LOG_ERROR(LOG_APP, "Get image receiver options capacity failed, capacity: %{public}d.", capacity); + return IMAGE_BAD_PARAMETER; + } + return IMAGE_SUCCESS; +} + +static Image_ErrorCode RegisterCallbackAndQuery(OH_ImageReceiverNative* receiver) +{ + uint64_t surfaceID = 0; + Image_ErrorCode errCode = OH_ImageReceiverNative_On(receiver, OnCallback); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Image receiver on failed, errCode: %{public}d.", errCode); + return errCode; + } + errCode = OH_ImageReceiverNative_GetReceivingSurfaceId(receiver, &surfaceID); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Get image receiver surfaceID failed, errCode: %{public}d.", errCode); + return errCode; + } + OH_LOG_INFO(LOG_APP, "Get image receiver surfaceID: %{public}lu.", surfaceID); + Image_Size imgSizeRead; + errCode = OH_ImageReceiverNative_GetSize(receiver, &imgSizeRead); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Get image receiver size failed, errCode: %{public}d.", errCode); + return errCode; + } + OH_LOG_INFO(LOG_APP, "Get image receiver size: width = %{public}d, height = %{public}d.", + imgSizeRead.width, imgSizeRead.height); + int32_t capacity = 0; + errCode = OH_ImageReceiverNative_GetCapacity(receiver, &capacity); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Get image receiver capacity failed, errCode: %{public}d.", errCode); + return errCode; + } + OH_LOG_INFO(LOG_APP, "Get image receiver capacity: %{public}d.", capacity); + return IMAGE_SUCCESS; +} + +Camera_ErrorCode InitCameraManagerAndInput(Camera_Manager*& cameraManager, + Camera_Device*& cameras, + uint32_t& size, + Camera_Input*& cameraInput) +{ + cameraManager = nullptr; + cameras = nullptr; + size = 0; + cameraInput = nullptr; + Camera_ErrorCode ret = OH_Camera_GetCameraManager(&cameraManager); + if (cameraManager == nullptr || ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_Camera_GetCameraManager failed."); + return ret; + } + ret = OH_CameraManager_GetSupportedCameras(cameraManager, &cameras, &size); + if (cameras == nullptr || size < 1 || ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameras failed."); + return ret; + } + + for (uint32_t i = 0; i < size; ++i) { + OH_LOG_INFO(LOG_APP, "Camera[%{public}u]: id=%{public}s, position=%{public}d, type=%{public}d, " + "connectionType=%{public}d", i, cameras[i].cameraId, cameras[i].cameraPosition, cameras[i].cameraType, + cameras[i].connectionType); + } + + ret = OH_CameraManager_CreateCameraInput(cameraManager, &cameras[0], &cameraInput); + if (cameraInput == nullptr || ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCameraInput failed.ret:%{public}d", ret); + return ret; + } + return CAMERA_OK; +} + +Camera_ErrorCode GetCameraOutputCapability(Camera_Manager* cameraManager, + Camera_Device* cameras, + uint32_t cameraDeviceIndex, + Camera_OutputCapability*& capability) +{ + capability = nullptr; + Camera_ErrorCode ret = OH_CameraManager_GetSupportedCameraOutputCapability(cameraManager, + &cameras[cameraDeviceIndex], + &capability); + if (capability == nullptr || ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CameraManager_GetSupportedCameraOutputCapability failed."); + } + return ret; +} + +Camera_CaptureSession* CreateAndStartSession(Camera_Manager* cameraManager, Camera_Input* cameraInput, int sessionMode) +{ + Camera_CaptureSession* captureSession = nullptr; + Camera_ErrorCode ret = OH_CameraManager_CreateCaptureSession(cameraManager, &captureSession); + if (captureSession == nullptr || ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreateCaptureSession failed."); + return nullptr; + } + ret = OH_CaptureSession_SetSessionMode(captureSession, static_cast(sessionMode)); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_SetSessionMode failed."); + return nullptr; + } + ret = OH_CaptureSession_BeginConfig(captureSession); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_BeginConfig failed."); + return nullptr; + } + ret = OH_CaptureSession_AddInput(captureSession, cameraInput); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddInput failed."); + return nullptr; + } + return captureSession; +} + +static Camera_ErrorCode StartPhotoSession(Camera_Manager* mgr, Camera_Input* input, Camera_PhotoOutput* photoOutput, + Camera_CaptureSession** sessionOut) +{ + *sessionOut = CreateAndStartSession(mgr, input, NORMAL_PHOTO); + if (*sessionOut == nullptr) { + OH_LOG_ERROR(LOG_APP, "CreateAndStartSession failed."); + return CAMERA_INVALID_ARGUMENT; + } + + Camera_ErrorCode ret = OH_CaptureSession_AddPhotoOutput(*sessionOut, photoOutput); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_AddPhotoOutput failed."); + return ret; + } + + ret = OH_CaptureSession_CommitConfig(*sessionOut); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_CommitConfig failed."); + return ret; + } + + ret = OH_CaptureSession_Start(*sessionOut); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CaptureSession_Start failed."); + } + return ret; +} + +Camera_ErrorCode NDKCameraPhotoOutput(char* str) +{ + Camera_Manager* cameraManager = nullptr; + Camera_Device* cameras = nullptr; + uint32_t size = 0; + Camera_Input* cameraInput = nullptr; + Camera_ErrorCode ret = InitCameraManagerAndInput(cameraManager, cameras, size, cameraInput); + if (ret != CAMERA_OK) return ret; + + Camera_OutputCapability* cameraOutputCapability = nullptr; + ret = GetCameraOutputCapability(cameraManager, cameras, 0, cameraOutputCapability); + if (ret != CAMERA_OK) return ret; + const Camera_Profile* photoProfile = cameraOutputCapability->photoProfiles[0]; + Camera_PhotoOutput* photoOutput = nullptr; + ret = OH_CameraManager_CreatePhotoOutput(cameraManager, photoProfile, str, &photoOutput); + if (photoProfile == nullptr || photoOutput == nullptr || ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CameraManager_CreatePhotoOutput failed."); + return ret; + } + + ret = OH_CameraInput_Open(cameraInput); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_CameraInput_open failed."); + return ret; + } + + Camera_CaptureSession* captureSession = nullptr; + ret = StartPhotoSession(cameraManager, cameraInput, photoOutput, &captureSession); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "StartPhotoSession failed."); + return ret; + } + + ret = OH_PhotoOutput_Capture(photoOutput); + if (ret != CAMERA_OK) { + OH_LOG_ERROR(LOG_APP, "OH_PhotoOutput_Capture failed."); + return ret; + } + return CAMERA_OK; +} + +static napi_value TakePhoto(napi_env env, napi_callback_info info) +{ + if (g_receiver == nullptr) { + OH_LOG_ERROR(LOG_APP, "ImageReceiver not initialized."); + return GetJsResultDemo(env, IMAGE_BAD_PARAMETER); + } + uint64_t surfaceId = 0; + Image_ErrorCode errCode = OH_ImageReceiverNative_GetReceivingSurfaceId(g_receiver, &surfaceId); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Get surfaceId failed."); + return GetJsResultDemo(env, errCode); + } + + auto surfaceId_c = ConvertUint64ToCharTemp(surfaceId); + Camera_ErrorCode photoRet = NDKCameraPhotoOutput(surfaceId_c.get()); + return GetJsResultDemo(env, photoRet); +} + +static napi_value ImageReceiverNativeCTest(napi_env env, napi_callback_info info) +{ + if (g_receiver != nullptr) { + OH_ImageReceiverNative_Off(g_receiver); + OH_ImageReceiverNative_Release(g_receiver); + g_receiver = nullptr; + } + + OH_ImageReceiverOptions* options = nullptr; + Image_ErrorCode errCode = CreateAndConfigOptions(&options); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "CreateAndConfigOptions failed errCode=%{public}d", errCode); + return GetJsResultDemo(env, errCode); + } + errCode = ValidateOptions(options); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "ValidateOptions failed errCode=%{public}d", errCode); + OH_ImageReceiverOptions_Release(options); + return GetJsResultDemo(env, errCode); + } + errCode = CreateReceiver(options, &g_receiver); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "CreateReceiver failed errCode=%{public}d", errCode); + OH_ImageReceiverOptions_Release(options); + return GetJsResultDemo(env, errCode); + } + errCode = RegisterCallbackAndQuery(g_receiver); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "RegisterCallbackAndQuery failed errCode=%{public}d", errCode); + OH_ImageReceiverOptions_Release(options); + OH_ImageReceiverNative_Release(g_receiver); + g_receiver = nullptr; + return GetJsResultDemo(env, errCode); + } + OH_LOG_INFO(LOG_APP, "ImageReceiverNativeCTest create and config success."); + OH_ImageReceiverOptions_Release(options); + return GetJsResultDemo(env, IMAGE_SUCCESS); +} + +static napi_value GetReceiverImageInfo(napi_env env, napi_callback_info info) +{ + OH_ImageNative* image = NotifyJsImageInfoSync(); + if (!image) { + napi_value undefined; + napi_get_undefined(env, &undefined); + return undefined; + } + napi_value resultObj = GetImageInfoObject(env, image); + OH_ImageNative_Release(image); + return resultObj; +} + +static napi_value ReleaseImageReceiver(napi_env env, napi_callback_info info) +{ + if (g_receiver == nullptr) { + OH_LOG_INFO(LOG_APP, "No image receiver to release."); + return nullptr; + } + Image_ErrorCode errCode = OH_ImageReceiverNative_Off(g_receiver); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "ImageReceiverNativeCTest image receiver off failed, errCode: %{public}d.", errCode); + } + errCode = OH_ImageReceiverNative_Release(g_receiver); + if (errCode != IMAGE_SUCCESS) { + OH_LOG_ERROR(LOG_APP, "Release image receiver failed, errCode: %{public}d.", errCode); + } + g_receiver = nullptr; + + return GetJsResultDemo(env, errCode); +} +// [End receiver_import] + +EXTERN_C_START +napi_value InitReceiverDemo(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "initImageReceiver", nullptr, ImageReceiverNativeCTest, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "takePhoto", nullptr, TakePhoto, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "getReceiverImageInfo", nullptr, GetReceiverImageInfo, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "releaseImageReceiver", nullptr, ReleaseImageReceiver, nullptr, nullptr, nullptr, napi_default, nullptr } + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + return exports; +} +EXTERN_C_END \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/loadReceiver.h b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadReceiver.h new file mode 100644 index 0000000000000000000000000000000000000000..420026b01f2f1d6de92be3e79454086e4c641f6d --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/loadReceiver.h @@ -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. + */ +#ifndef RECEIVER_DEMO_TEST_H +#define RECEIVER_DEMO_TEST_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +napi_value InitReceiverDemo(napi_env env, napi_value exports); + +#ifdef __cplusplus +} +#endif + +#endif // RECEIVER_DEMO_TEST_H \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/napi_init.cpp b/ImageKit/ImageNativeSample/entry/src/main/cpp/napi_init.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3f23e3d3546d9d881ca4d2c43666a0afdf88cb07 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/napi_init.cpp @@ -0,0 +1,79 @@ +/* + * 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 "napi/native_api.h" +#include "loadReceiver.h" +#include +#include +#include +#include +// [Start get_returnValue] +// 处理napi返回值。 +napi_value GetJsResult(napi_env env, int result) +{ + napi_value resultNapi = nullptr; + napi_create_int32(env, result, &resultNapi); + return resultNapi; +} +// [End get_returnValue] + +EXTERN_C_START +static napi_value Init(napi_env env, napi_value exports) +{ + napi_property_descriptor desc[] = { + { "createImageSource", nullptr, CreateImageSource, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "getImageInfo", nullptr, GetImageInfo, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "getImageProperty", nullptr, GetImageProperty, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "modifyImageProperty", nullptr, ModifyImageProperty, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "createPixelMap", nullptr, CreatePixelMap, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "getFrameCount", nullptr, GetFrameCount, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "createPixelmapList", nullptr, CreatePixelmapList, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "getDelayTimeList", nullptr, GetDelayTimeList, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "releaseImageSource", nullptr, ReleaseImageSource, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "setDesiredAuxiliaryPictures", nullptr, SetDesiredAuxiliaryPictures, + nullptr, nullptr, nullptr, napi_default, nullptr }, + { "createPictureByImageSource", nullptr, CreatePictureByImageSource, + nullptr, nullptr, nullptr, napi_default, nullptr }, + { "releasePictureSource", nullptr, ReleasePictureSource, nullptr, nullptr, nullptr, napi_default, nullptr }, + { "testStrideWithAllocatorType", nullptr, TestStrideWithAllocatorType, + nullptr, nullptr, nullptr, napi_default, nullptr }, + { "packToFileFromImageSourceTestJs", nullptr, PackToFileFromImageSourceTestJs, + nullptr, nullptr, nullptr, napi_default, nullptr }, + { "packToFileFromPixelmapTestJs", nullptr, PackToFileFromPixelmapTestJs, + nullptr, nullptr, nullptr, napi_default, nullptr }, + { "packToDataFromPicture", nullptr, PackToDataFromPicture, + nullptr, nullptr, nullptr, napi_default, nullptr }, + { "packToFileFromPicture", nullptr, PackToFileFromPicture, + nullptr, nullptr, nullptr, napi_default, nullptr }, + }; + napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc); + InitReceiverDemo(env, exports); + return exports; +} +EXTERN_C_END + +static napi_module demoModule = { + .nm_version = 1, + .nm_flags = 0, + .nm_filename = nullptr, + .nm_register_func = Init, + .nm_modname = "entry", + .nm_priv = ((void*)0), + .reserved = { 0 }, +}; + +extern "C" __attribute__((constructor)) void RegisterEntryModule(void) +{ + napi_module_register(&demoModule); +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/types/libentry/Index.d.ts b/ImageKit/ImageNativeSample/entry/src/main/cpp/types/libentry/Index.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..c6ab094d243f91de6adf38ed3170cd258bc149c9 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/types/libentry/Index.d.ts @@ -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 { image } from "@kit.ImageKit"; + +interface ImageInfo { + width: number; + height: number; + bufferSize?: number; + rowStride?: number; + pixelStride?: number; + timestamp?: number | bigint; +} +// sourceTest +export const createImageSource: (filePath: string) => number; +export const getImageInfo: () => number; +export const createPixelMap: () => number; +export const getFrameCount: () => number; +export const createPixelmapList: () => number; +export const getDelayTimeList: () => number; +export const releaseImageSource: () => number; +// editExif +export const getImageProperty: (key: string) => string | number; +export const modifyImageProperty: (key: string, value: string) => number; +// decodingPicture +export const setDesiredAuxiliaryPictures: (auxTypeList: image.AuxiliaryPictureType[]) => number; +export const createPictureByImageSource: (filePath: string) => number; +export const releasePictureSource: () => number; +// allocator +export const testStrideWithAllocatorType: (filePath: string) => number; +// packer +export const packToFileFromImageSourceTestJs: (fd: number) => number; +export const packToFileFromPixelmapTestJs: (fd: number) => number; +export const packToDataFromPicture: (format: string) => number; +export const packToFileFromPicture: (fd: number, format: string) => number; +// receiver +export const initImageReceiver: () => number; +export const releaseImageReceiver: () => number; +export const getReceiverImageInfo: () => Promise; +export const takePhoto: () => number; \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/cpp/types/libentry/oh-package.json5 b/ImageKit/ImageNativeSample/entry/src/main/cpp/types/libentry/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..77052c679533e45a066030a9fc21cdbf9cbcf995 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/cpp/types/libentry/oh-package.json5 @@ -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. + */ +{ + "name": "libentry.so", + "types": "./Index.d.ts", + "version": "1.0.0", + "description": "Please describe the basic information." +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/entryability/EntryAbility.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/entryability/EntryAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..72ffbc83ca9da0d07a6f517579181b5efa335131 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/entryability/EntryAbility.ets @@ -0,0 +1,77 @@ +/* + * 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 { abilityAccessCtrl, AbilityConstant, ConfigurationConstant, + PermissionRequestResult, + Permissions, + UIAbility, Want } from '@kit.AbilityKit'; +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { window } from '@kit.ArkUI'; + +const DOMAIN = 0x0000; + +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(DOMAIN, 'testTag', '%{public}s', 'Ability onCreate'); + } + + onDestroy(): void { + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onDestroy'); + } + + onWindowStageCreate(windowStage: window.WindowStage): void { + // Main window is created, set main page for this ability + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageCreate'); + let atManager = abilityAccessCtrl.createAtManager(); + try { + let permissions: Permissions[] = [ + 'ohos.permission.CAMERA', + 'ohos.permission.MICROPHONE', + 'ohos.permission.MEDIA_LOCATION', + 'ohos.permission.READ_MEDIA', + 'ohos.permission.WRITE_MEDIA', + ]; + atManager.requestPermissionsFromUser(this.context, permissions).then((data: PermissionRequestResult) => { + hilog.info(0x00000, 'testTag', 'data:' + JSON.stringify(data)) + hilog.info(0x00000, 'testTag', 'data permissions:' + data.permissions) + }) + } catch(err) { + hilog.info(0x00000, 'testTag', 'get permissions failed. err is ' + err); + } + + windowStage.loadContent('pages/Index', (err) => { + if (err.code) { + hilog.error(DOMAIN, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err)); + return; + } + hilog.info(DOMAIN, 'testTag', 'Succeeded in loading the content.'); + }); + } + + onWindowStageDestroy(): void { + // Main window is destroyed, release UI related resources + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onWindowStageDestroy'); + } + + onForeground(): void { + // Ability has brought to foreground + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onForeground'); + } + + onBackground(): void { + // Ability has back to background + hilog.info(DOMAIN, 'testTag', '%{public}s', 'Ability onBackground'); + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets new file mode 100644 index 0000000000000000000000000000000000000000..4ce6449f0e91914e73d4502c9f2e8e9a395ea4b1 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets @@ -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. + */ +import { hilog } from '@kit.PerformanceAnalysisKit'; +import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit'; + +const DOMAIN = 0x0000; + +export default class EntryBackupAbility extends BackupExtensionAbility { + async onBackup() { + hilog.info(DOMAIN, 'testTag', 'onBackup ok'); + await Promise.resolve(); + } + + async onRestore(bundleVersion: BundleVersion) { + hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion)); + await Promise.resolve(); + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/pages/EditExif.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/EditExif.ets new file mode 100644 index 0000000000000000000000000000000000000000..eab16965b46027703c093885e2e8a1a8ec7280d2 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/EditExif.ets @@ -0,0 +1,145 @@ +/* + * 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'; +import { GotoButton, MyButton } from '../utils/MyButton' +import { SourceFunctions } from '../utils/SourceFunctions' +import { common } from '@kit.AbilityKit'; + +@Entry +@Component +struct EditExif { + @State message: number = 0; + @State picture: image.Picture | null = null; + @State returnMessage: string = 'No'; + @State fileName: string = 'test.jpeg'; + private test = new SourceFunctions(); + @State context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; + @State isOpen: boolean = false; + @State propertyKey: image.PropertyKey = image.PropertyKey.F_NUMBER; + @State value: string = ''; + @State keyOptions: image.PropertyKey[] = [ + image.PropertyKey.ORIENTATION, + image.PropertyKey.ROLL_ANGLE, + image.PropertyKey.GPS_LATITUDE, + image.PropertyKey.EXPOSURE_TIME, + image.PropertyKey.GPS_LONGITUDE, + image.PropertyKey.MAKER_NOTE, + image.PropertyKey.FOCUS_MODE, + image.PropertyKey.PHOTOGRAPHIC_SENSITIVITY, + image.PropertyKey.EXPOSURE_TIME, + image.PropertyKey.F_NUMBER + ]; + + build() { + Row() { + Column() { + Text('请先创建ImageSource!') + MyButton({ text: 'CreateImageSource', context: this.context, fileName: this.fileName, + chooseFun: 'fun1', fun1: this.test.createImageSource}) + Button('ChoosePropertyKey') + .labelStyle({ + overflow: TextOverflow.Clip, + maxLines: 2, + minFontSize: 20, + maxFontSize: 20, + font: { + size: 20, + weight: FontWeight.Bolder, + family: 'cursive', + style: FontStyle.Italic + } + }) + .margin({ top: 5 }) + .onClick(() => { + this.isOpen = !this.isOpen; + }) + Blank().height(20); + Divider(); + if (this.isOpen) { + Column() { + ForEach(this.keyOptions, (item: image.PropertyKey) => { + Text(item) + .onClick(() => { + this.propertyKey = item; + this.isOpen = !this.isOpen; + }) + .border({ width: 1, color: Color.Blue }) + .width('100%') + .padding(10) + .zIndex(999) + }) + } + .margin({ top: 5 }) + .width('100%') + .height('100%') + .backgroundColor(Color.Pink) + .border({ width: 1, color: Color.Blue }) + } + Button('GetImageProperty') + .labelStyle({ + overflow: TextOverflow.Clip, + maxLines: 2, + minFontSize: 20, + maxFontSize: 20, + font: { + size: 20, + weight: FontWeight.Bolder, + family: 'cursive', + style: FontStyle.Italic + } + }) + .margin({ top: 5 }) + .onClick(() => { + this.test.getImageProperty(this.propertyKey); + }) + Blank().height(20); + Divider(); + Text('输入指定property的key值') + .margin({ top: 5 }) + TextInput() + .onChange((value: string) => { + this.value = value; + console.log(`this.value ${this.value}`); + }) + .margin({ top: 5 }) + .id('valueInput') + Button('ModifyImageProperty') + .labelStyle({ + overflow: TextOverflow.Clip, + maxLines: 2, + minFontSize: 20, + maxFontSize: 20, + font: { + size: 20, + weight: FontWeight.Bolder, + family: 'cursive', + style: FontStyle.Italic + } + }) + .margin({ top: 5 }) + .onClick(() => { + this.test.modifyImageProperty(this.propertyKey, this.value); + }) + Blank().height(20); + Divider(); + Text('资源释放后再进行其他操作会引起崩溃,请重新创建后再进行具体操作!') + MyButton({ text: 'ReleaseImageSource', chooseFun: 'fun', fun: this.test.releaseImageSource }) + GotoButton({ text: 'back', dstUri: 'pages/Index'}) + } + .width('100%') + .height('100%') + } + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/pages/GifCodec.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/GifCodec.ets new file mode 100644 index 0000000000000000000000000000000000000000..09ec78b20f6cd014c38c1c0645bed381c7d85114 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/GifCodec.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 { image } from '@kit.ImageKit'; +import { GotoButton, MyButton } from '../utils/MyButton' +import { SourceFunctions } from '../utils/SourceFunctions' +import { common } from '@kit.AbilityKit'; + +@Entry +@Component +struct GifCodec { + @State message: number = 0; + @State picture: image.Picture | null = null; + @State returnMessage: string = 'No'; + @State gifName: string = 'test.gif'; + private test = new SourceFunctions(); + @State context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; + + build() { + Row() { + Column() { + Text('请先创建ImageSource!') + MyButton({ text: 'CreateImageSource', context: this.context, fileName: this.gifName, + chooseFun: 'fun1', fun1: this.test.createImageSource}) + MyButton({ text: 'CreatePixelmapList', chooseFun: 'funGroup1', fun: this.test.getFrameCount, + fun4: this.test.createPixelmapList}) + MyButton({ text: 'GetDelayTimeList', chooseFun: 'funGroup1', fun: this.test.getFrameCount, + fun4: this.test.getDelayTimeList}) + Text('资源释放后再进行其他操作会引起崩溃,请重新创建后再进行具体操作!') + MyButton({ text: 'ReleaseImageSource', chooseFun: 'fun', fun: this.test.releaseImageSource }) + GotoButton({ text: 'back', dstUri: 'pages/Index'}) + } + .width('100%') + .height('100%') + } + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/pages/ImageCodec.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/ImageCodec.ets new file mode 100644 index 0000000000000000000000000000000000000000..d24e451a9f13cd6675a30f70902da8896a8606f3 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/ImageCodec.ets @@ -0,0 +1,70 @@ +/* + * 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'; +import { MyButton } from '../utils/MyButton' +import { SourceFunctions } from '../utils/SourceFunctions' +import { common } from '@kit.AbilityKit'; +import { GotoButton } from '../utils/MyButton' + +@Entry +@Component +struct ImageCodec { + @State message: number = 0; + @State picture: image.Picture | null = null; + @State returnMessage: string = 'No'; + @State fileName: string = 'test.jpeg'; + @State gifName: string = 'test.gif'; + @State packSourceName: string = 'packToFileFromImageSource.jpg'; + @State packPixelName: string = 'packToFileFromPixelMap.jpg'; + private test = new SourceFunctions(); + @State context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; + @State isOpen: boolean = false; + @State propertyKey: image.PropertyKey = image.PropertyKey.F_NUMBER; + @State value: string = ''; + @State keyOptions: image.PropertyKey[] = [ + image.PropertyKey.ROLL_ANGLE, + image.PropertyKey.GPS_LATITUDE, + image.PropertyKey.EXPOSURE_TIME, + image.PropertyKey.GPS_LONGITUDE, + image.PropertyKey.MAKER_NOTE, + image.PropertyKey.FOCUS_MODE, + image.PropertyKey.PHOTOGRAPHIC_SENSITIVITY, + image.PropertyKey.EXPOSURE_TIME, + image.PropertyKey.F_NUMBER + ]; + + build() { + Row() { + Column() { + Text('请先创建ImageSource!') + MyButton({ text: 'CreateImageSource', context: this.context, fileName: this.fileName, + chooseFun: 'fun1', fun1: this.test.createImageSource}) + MyButton({ text: 'packToFileFromImageSource', context: this.context, fileName: this.packSourceName, + chooseFun: 'fun5', fun5: this.test.packToFileFromImageSourceTestJs}) + MyButton({ text: 'GetImageInfo', chooseFun: 'fun', fun: this.test.getImageInfo}) + MyButton({ text: 'createPixelMap', chooseFun: 'fun', fun: this.test.createPixelMap}) + MyButton({ text: 'packToFileFromPixelmap', context: this.context, fileName: this.packPixelName, + chooseFun: 'fun5', fun5: this.test.packToFileFromPixelmapTestJs}) + MyButton({ text: 'CreatePixelmapUsingAllocator', context: this.context, fileName: this.fileName, + chooseFun: 'fun1', fun1: this.test.createPixelmapUsingAllocator }) + Text('资源释放后再进行其他操作会引起崩溃,请重新创建后再进行具体操作!') + MyButton({ text: 'ReleaseImageSource', chooseFun: 'fun', fun: this.test.releaseImageSource }) + GotoButton({ text: 'back', dstUri: 'pages/Index'}) + } + .width('100%') + .height('100%') + } + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/pages/ImageReceiver.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/ImageReceiver.ets new file mode 100644 index 0000000000000000000000000000000000000000..8250bd15b5e06389da13c93fa9157a91c016f5f8 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/ImageReceiver.ets @@ -0,0 +1,44 @@ +/* + * 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'; +import { GotoButton, MyButton } from '../utils/MyButton' +import { ReceiverFunctions } from '../utils/ReceiverFunctions' +import { common } from '@kit.AbilityKit'; + +@Entry +@Component +struct ImageReceiver { + @State message: number = 0; + @State picture: image.Picture | null = null; + @State returnMessage: string = 'No'; + private test = new ReceiverFunctions(); + + build() { + Row() { + Column() { + Text('请先初始化ImageReceiver,注册回调函数!') + MyButton({ text: 'initImageReceiver', chooseFun: 'fun', fun: this.test.initImageReceiver}) + Text('点击takePhoto按钮,会触发回调,并获取image信息!') + MyButton({ text: 'takePhoto', chooseFun: 'funGroup1', + fun: this.test.takePhoto, fun4: this.test.getReceiverImageInfo}) + Text('资源释放后再进行其他操作会引起崩溃,请重新创建后再进行具体操作!') + MyButton({ text: 'releaseImageReceiver', chooseFun: 'fun', fun: this.test.releaseImageReceiver}) + GotoButton({ text: 'back', dstUri: 'pages/Index'}) + } + .width('100%') + .height('100%') + } + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/pages/Index.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/Index.ets new file mode 100644 index 0000000000000000000000000000000000000000..8aabd92c611413f7dae5b91ee15985f85d419c1a --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/Index.ets @@ -0,0 +1,54 @@ +/* + * 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 '@ohos.multimedia.image'; +import { GotoButton } from '../utils/MyButton' + +@Entry +@Component +struct Index { + @State message: number = 0; + @State picture: image.Picture | null = null; + @State returnMessage: string = 'No'; + + build() { + Row() { + Column() { + List() { + ListItem() { + GotoButton({ text: '跳转到图片编解码操作页面', dstUri: 'pages/ImageCodec'}) + } + + ListItem() { + GotoButton({ text: '跳转到Gif编解码操作页面', dstUri: 'pages/GifCodec'}) + } + + ListItem() { + GotoButton({ text: '跳转到Picture编解码演示页面', dstUri: 'pages/PictureCodec'}) + } + + ListItem() { + GotoButton({ text: '跳转到读取和修改Exif信息页面', dstUri: 'pages/EditExif'}) + } + + ListItem() { + GotoButton({ text: '跳转到图片接收页面', dstUri: 'pages/ImageReceiver'}) + } + } + .width('%100') + .height('%100') + } + } + } +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/pages/PictureCodec.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/PictureCodec.ets new file mode 100644 index 0000000000000000000000000000000000000000..61baf0e5c2fd6c6a0a94a0cd9668fa6982cac51a --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/pages/PictureCodec.ets @@ -0,0 +1,49 @@ +/* + * 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'; +import { GotoButton, MyButton } from '../utils/MyButton' +import { PictureFunctions } from '../utils/PictureFunctions'; +import { common } from '@kit.AbilityKit'; + +@Entry +@Component +struct PictureCodec { + @State message: number = 0; + @State picture: image.Picture | null = null; + @State returnMessage: string = 'No'; + @State fileName: string = 'allAux.jpg'; + @State packFileName: string = 'packToFileFromPicture.jpg'; + @State context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; + private test = new PictureFunctions(); + + build() { + Row() { + Column() { + Text('请先配置解码参数,再进行解码!') + MyButton({ text: 'SetDesiredAuxiliaryPictures', fun: this.test.setDesiredAuxiliaryPictures }) + MyButton({ text: 'CreatePictureByImageSource', context: this.context, fileName: this.fileName, + chooseFun: 'fun1', fun1: this.test.createPictureByImageSource }) + MyButton({ text: 'packToDataFromPicture', fun: this.test.packToDataFromPicture }) + MyButton({ text: 'packToFileFromPicture', context: this.context, fileName: this.packFileName, + chooseFun: 'fun5', fun5: this.test.packToFileFromPicture }) + Text('资源释放后再进行其他操作会引起崩溃,请重新创建后再进行具体操作!') + MyButton({ text: 'ReleasePictureSource', fun: this.test.releasePictureSource }) + GotoButton({ text: 'back', dstUri: 'pages/Index'}) + } + .width('%100') + .height('%100') + } + } +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/utils/FunctionUtility.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/FunctionUtility.ets new file mode 100644 index 0000000000000000000000000000000000000000..b39d4df40596502bf6bd944f2129c955714f4982 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/FunctionUtility.ets @@ -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. + */ +import { common } from '@kit.AbilityKit'; +import fs from '@ohos.file.fs'; + +// 将rawFile中的文件写到沙箱里。 +export async function pushSourceToBox(context: common.UIAbilityContext, fileName: string) { + let value = await context.resourceManager.getRawFileContent(fileName); + let myBuffer: ArrayBufferLike = value.buffer; + let filePath = context.filesDir + '/' + fileName; + let file = await fs.open(filePath, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE); + let writLen = await fs.write(file.fd, myBuffer); + console.log(`Push ${fileName} to box's writLen is ${writLen}.`); + fs.closeSync(file); +} + +// 获取文件fd。 +export function getFileFd(context: Context, fileName: string): number | undefined { + const filePath: string = context.cacheDir + '/' + fileName; + const file: fs.File = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); + const fd: number = file?.fd; + return fd; +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/utils/Logger.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/Logger.ets new file mode 100644 index 0000000000000000000000000000000000000000..ac5191d85585eae4717d6d849b3ebf1c029fe5e2 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/Logger.ets @@ -0,0 +1,38 @@ +/* + * 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 class AppLog { + constructor(tag: string) { + this.tagName = tag; + } + prefix : string = '[IMAGE_SAMPLE_NDK]'; + tagName: string; + log = (msg: string) => { + console.info(this.prefix + this.tagName + ' ' + msg); + }; + check_result = (msg: string, res: object | number) => { + if (typeof res === 'object') { + this.log(msg + `object result success :${res}`); + } else if (typeof res === 'number') { + if (res == 0) { + this.log(msg + `: errorcode result success: ${res}`); + } else { + this.log(msg + `: errorcode result failed: ${res}`); + } + } else { + this.log(msg + `unknown result type: ${res}`); + } + }; +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/utils/MyButton.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/MyButton.ets new file mode 100644 index 0000000000000000000000000000000000000000..360abd1afe7aebd9d040a4b1b8feadc89d6e4bef --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/MyButton.ets @@ -0,0 +1,140 @@ +/* + * 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 { AppLog } from '../utils/Logger' +import {Router} from '@ohos.arkui.UIContext'; +import { common } from '@kit.AbilityKit'; +import { image } from '@kit.ImageKit'; + +const router = new Router(); +const TAG: string = 'DEBUG TEST'; + +@Component +export struct MyButton { + //自定义button。 + public logger = new AppLog(TAG); + public context: common.UIAbilityContext = this.getUIContext().getHostContext() as common.UIAbilityContext; + public isOpen = false; + public propertyKey = image.PropertyKey.BITS_PER_SAMPLE; + public value = ''; + public chooseFun = 'fun'; + public fileName: string = 'test.jpeg'; + public fun: () => void = () => {}; + public fun1: (context: common.UIAbilityContext, fileName: string) => Promise = () => { + return new Promise(() => {}); + }; + public fun2: (propertyKey: string) => void = () => {}; + public fun3: (propertyKey: string, value: string) => void = () => {}; + public fun4: () => void = () => {}; + public fun5: (context: common.UIAbilityContext, fileName: string) => void = () => {}; + public text = 'This is a button'; + @State returnMessage: string = 'No'; + + build() { + Row() { + Column() { + Blank().height(20); + Button(`${this.text}`) + .labelStyle({ + overflow: TextOverflow.Clip, + maxLines: 2, + minFontSize: 20, + maxFontSize: 20, + font: { + size: 20, + weight: FontWeight.Bolder, + family: 'cursive', + style: FontStyle.Italic + } + }) + .onClick(async () => { + this.logger.log('\n start->>>>>>>>>>>>>>>>>>>>>>'); + switch(this.chooseFun) { + case 'fun': + this.fun(); + break; + case 'fun1': + await this.fun1(this.context, this.fileName); + break; + case 'fun2': + console.log(`this.propertyKey ${this.propertyKey}`); + this.fun2(this.propertyKey); + break; + case 'fun3': + console.log(`fun3 this.value ${this.value}`); + this.fun3(this.propertyKey, this.value); + break; + case 'fun5': + this.fun5(this.context, this.fileName); + break; + case 'funGroup': + await this.fun1(this.context, this.fileName); + this.fun(); + this.fun4(); + break; + case 'funGroup1': + this.fun(); + this.fun4(); + break; + case 'noFun': + this.fileName = this.fileName; + break; + } + this.logger.log((this.fun.toString()) + '\n end:->>>>>>>>>>>>>>>>>>>>>>'); + this.returnMessage = 'Yes'; + }) + Blank().height(20); + Divider(); + } + } + } +} + +@Component +export struct GotoButton { + public logger = new AppLog(TAG); + public dstUri: string = ''; + public text = 'This is a goto button'; + @State returnMessage: string = 'No'; + + build() { + Row() { + Column() { + Blank().height(40); + Button(`${this.text}`) + .labelStyle({ + overflow: TextOverflow.Clip, + maxLines: 2, + minFontSize: 20, + maxFontSize: 20, + font: { + size: 20, + weight: FontWeight.Bolder, + family: 'cursive', + style: FontStyle.Italic + } + }) + .onClick( () => { + this.logger.log(`\n start goto ${this.dstUri}->>>>>>>>>>>>>>>>>>>>>>`); + router.pushUrl({ url: this.dstUri }); + this.logger.log(`\n end goto ${this.dstUri}->>>>>>>>>>>>>>>>>>>>>>`); + this.returnMessage = 'Yes'; + }) + Blank().height(40); + Divider(); + } + } + } +} + diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/utils/PictureFunctions.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/PictureFunctions.ets new file mode 100644 index 0000000000000000000000000000000000000000..2cdc44e95b3c7b1ed412ac26ffafdf7463f52d8e --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/PictureFunctions.ets @@ -0,0 +1,94 @@ +/* + * 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 testNapi from 'libentry.so'; +import {AppLog } from '../utils/Logger' +import { promptAction } from '@kit.ArkUI'; +import { common } from '@kit.AbilityKit'; +import { pushSourceToBox } from './FunctionUtility'; +import { image } from '@kit.ImageKit'; +import { fileIo as fs } from '@kit.CoreFileKit'; + +const TAG: string = 'PictureFunctions'; +export class PictureFunctions { + constructor() { + } + + private logger = new AppLog(TAG); + + async createPictureByImageSource(context: common.UIAbilityContext, fileName: string): Promise { + console.log(`fileName: ${fileName}`); + let filePath = context.filesDir + '/' + fileName; + await pushSourceToBox(context, fileName); + let errorCode = testNapi.createPictureByImageSource(filePath); + this.logger.check_result('CreatePictureByImageSource' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'CreatePicture success.'}); + } else { + this.logger.log('CreatePicture error is: ' + errorCode); + promptAction.showToast({ message: 'CreatePicture error is: ' + errorCode}); + } + } + + setDesiredAuxiliaryPictures() { + // 根据所需解码的辅助图类型设置解码参数。 + let typeList: image.AuxiliaryPictureType[] = [image.AuxiliaryPictureType.GAINMAP]; + let errorCode = testNapi.setDesiredAuxiliaryPictures(typeList); + if(errorCode === 0) { + promptAction.showToast({ message: 'SetDesiredAuxiliaryPictures success.'}); + } else { + promptAction.showToast({ message: `SetDesiredAuxiliaryPictures failed with ${errorCode}.`}); + this.logger.log(`SetDesiredAuxiliaryPictures failed with ${errorCode}.`); + } + } + + releasePictureSource() { + let errorCode = testNapi.releasePictureSource(); + this.logger.check_result('ReleasePicture' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'ReleasePicture success.'}); + } else { + promptAction.showToast({ message: `ReleasePicture failed with ${errorCode}.`}); + this.logger.log(`ReleasePicture failed with ${errorCode}.`); + } + } + + packToDataFromPicture() { + let errorCode = testNapi.packToDataFromPicture('image/jpeg'); + this.logger.check_result('PackToDataFromPicture' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'PackToDataFromPicture success.'}); + } else { + promptAction.showToast({ message: `PackToDataFromPicture failed with ${errorCode}.`}); + this.logger.log(`PackToDataFromPicture failed with ${errorCode}.`); + } + } + + packToFileFromPicture(context: Context, fileName: string) { + this.logger.log(`PackToFileFromPicture start with ${fileName}.`); + const filePath: string = context.filesDir + '/' + fileName; + this.logger.log(`PackToFileFromPicture start with ${filePath}.`); + const file: fs.File = fs.openSync(filePath, fs.OpenMode.CREATE | fs.OpenMode.READ_WRITE); + let fd: number = file?.fd; + this.logger.log(`PackToFileFromPicture start with ${fd}.`); + let errorCode = testNapi.packToFileFromPicture(fd, 'image/jpeg'); + this.logger.check_result('PackToFileFromPicture' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'PackToFileFromPicture success.'}); + } else { + promptAction.showToast({ message: `PackToFileFromPicture failed with ${errorCode}.`}); + this.logger.log(`PackToFileFromPicture failed with ${errorCode}.`); + } + } +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/utils/ReceiverFunctions.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/ReceiverFunctions.ets new file mode 100644 index 0000000000000000000000000000000000000000..1467dd4916ae04e9dbcf91d25f2d197073170843 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/ReceiverFunctions.ets @@ -0,0 +1,68 @@ +/* + * 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 distributed on an "AS " 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 testNapi from 'libentry.so'; +import {AppLog } from '../utils/Logger' +import { promptAction } from '@kit.ArkUI'; + +const TAG: string = 'ReceiverFunctions'; +export class ReceiverFunctions { + constructor() { + } + + private logger = new AppLog(TAG); + + initImageReceiver() { + let errorCode = testNapi.initImageReceiver(); + if(errorCode === 0) { + promptAction.showToast({ message: 'InitImageReceiver success.'}); + } else { + promptAction.showToast({ message: `InitImageReceiver failed with ${errorCode}.`}); + this.logger.log(`InitImageReceiver failed with ${errorCode}.`); + } + } + + takePhoto() { + let errorCode = testNapi.takePhoto(); + this.logger.check_result('TakePhoto' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'TakePhoto success.'}); + } else { + promptAction.showToast({ message: `TakePhoto failed with ${errorCode}.`}); + this.logger.log(`TakePhoto failed with ${errorCode}.`); + } + } + + getReceiverImageInfo() { + let info = testNapi.getReceiverImageInfo(); + if(info !== null) { + promptAction.showToast({ message: `GetImageInfo: ${JSON.stringify(info)}.`}); + this.logger.log(`GetImageInfo: ${info}.`); + } else { + promptAction.showToast({ message: `GetImageInfo failed.`}); + this.logger.log(`GetImageInfo failed.`); + } + } + + releaseImageReceiver() { + let errorCode = testNapi.releaseImageReceiver(); + this.logger.check_result('ReleaseImageReceiver' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'ReleaseImageReceiver success.'}); + } else { + promptAction.showToast({ message: `ReleaseImageReceiver failed with ${errorCode}.`}); + this.logger.log(`ReleaseImageReceiver failed with ${errorCode}.`); + } + } +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/ets/utils/SourceFunctions.ets b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/SourceFunctions.ets new file mode 100644 index 0000000000000000000000000000000000000000..94a5a5567ac77d44612dca4fd579cdc01aa3b107 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/ets/utils/SourceFunctions.ets @@ -0,0 +1,148 @@ +/* + * 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 testNapi from 'libentry.so'; +import {AppLog } from '../utils/Logger' +import { promptAction } from '@kit.ArkUI'; +import { common } from '@kit.AbilityKit'; +import { pushSourceToBox, getFileFd } from '../utils/FunctionUtility' +const TAG: string = 'SourceFunctions'; +export class SourceFunctions { + constructor() { + } + + private logger = new AppLog(TAG); + + async createImageSource(context: common.UIAbilityContext, fileName: string): Promise { + let filePath = context.filesDir + '/' + fileName; + await pushSourceToBox(context, fileName); + let errorCode = testNapi.createImageSource(filePath); + this.logger.check_result('Create imageSource' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'Create imageSource success.'}); + } else { + this.logger.log('Create imageSource error is: ' + errorCode); + promptAction.showToast({ message: 'Create imageSource error is: ' + errorCode}); + } + } + + getImageInfo() { + let width = testNapi.getImageInfo(); + this.logger.log(`Get the width of the imageSource is ${width}.`); + promptAction.showToast({ message: `Get the width of the imageSource is ${width}.`}); + } + + getImageProperty(key: string) { + this.logger.log(`Get the key is ${key}.`); + let value = testNapi.getImageProperty(key); + this.logger.log(`Get the value of ${key} is ${value}.`); + promptAction.showToast({ message: `Get the value of ${key} is ${value}.`}); + } + + modifyImageProperty(key: string, value: string): void { + let errorCode = testNapi.modifyImageProperty(key, value); + this.logger.check_result('ModifyImageProperty' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'ModifyImageProperty success.'}); + } else { + promptAction.showToast({ message: `ModifyImageProperty failed with ${errorCode}.`}); + this.logger.log(`ModifyImageProperty failed with ${errorCode}.`); + } + } + + createPixelMap(): void { + let errorCode = testNapi.createPixelMap(); + this.logger.check_result('CreatePixelMap' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'CreatePixelMap success.'}); + } else { + promptAction.showToast({ message: `CreatePixelMap failed with ${errorCode}.`}); + this.logger.log(`CreatePixelMap failed with ${errorCode}.`); + } + } + + getFrameCount() { + let count = testNapi.getFrameCount(); + promptAction.showToast({ message: `GetFrameCount return count ${count}.`}); + } + + createPixelmapList(): void { + let errorCode = testNapi.createPixelmapList(); + this.logger.check_result('CreatePixelMapList' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'CreatePixelMapList success.'}); + } else { + promptAction.showToast({ message: `CreatePixelMapList failed with ${errorCode}.`}); + this.logger.log(`CreatePixelMapList failed with ${errorCode}.`); + } + } + + getDelayTimeList() { + let errorCode = testNapi.getDelayTimeList(); + this.logger.check_result('GetDelayTimeList' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'GetDelayTimeList success.'}); + } else { + promptAction.showToast({ message: `GetDelayTimeList failed with ${errorCode}.`}); + this.logger.log(`GetDelayTimeList failed with ${errorCode}.`); + } + } + + releaseImageSource() { + let errorCode = testNapi.releaseImageSource(); + this.logger.check_result('ReleaseImageSource' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'ReleaseImageSource success.'}); + } else { + promptAction.showToast({ message: `ReleaseImageSource failed with ${errorCode}.`}); + this.logger.log(`ReleaseImageSource failed with ${errorCode}.`); + } + } + + async createPixelmapUsingAllocator(context: common.UIAbilityContext, fileName: string): Promise { + let filePath = context.filesDir + '/' + fileName; + await pushSourceToBox(context, fileName); + let errorCode = testNapi.testStrideWithAllocatorType(filePath); + if(errorCode === 0) { + promptAction.showToast({ message: 'CreatePixelMapUsingAllocator success.'}); + } else { + this.logger.log('CreatePixelMapUsingAllocator error is: ' + errorCode); + promptAction.showToast({ message: 'CreatePixelMapUsingAllocator error is: ' + errorCode}); + } + } + + packToFileFromImageSourceTestJs(context: common.UIAbilityContext, fileName: string) { + const fd = getFileFd(context, fileName); + let errorCode = testNapi.packToFileFromImageSourceTestJs(fd); + this.logger.check_result('PackToFileFromImageSourceTestJs' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'PackToFileFromImageSourceTestJs success.'}); + } else { + promptAction.showToast({ message: `PackToFileFromImageSourceTestJs failed with ${errorCode}.`}); + this.logger.log(`PackToFileFromImageSourceTestJs failed with ${errorCode}.`); + } + } + + packToFileFromPixelmapTestJs(context: common.UIAbilityContext, fileName: string) { + let fd = getFileFd(context, fileName); + let errorCode = testNapi.packToFileFromPixelmapTestJs(fd); + this.logger.check_result('PackToFileFromPixelmapTestJs' , errorCode); + if(errorCode === 0) { + promptAction.showToast({ message: 'PackToFileFromPixelmapTestJs success.'}); + } else { + promptAction.showToast({ message: `PackToFileFromPixelmapTestJs failed with ${errorCode}.`}); + this.logger.log(`PackToFileFromPixelmapTestJs failed with ${errorCode}.`); + } + } +} diff --git a/ImageKit/ImageNativeSample/entry/src/main/module.json5 b/ImageKit/ImageNativeSample/entry/src/main/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..15ad755c22a6b553b2840a5e662f76a2e4aa368a --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/module.json5 @@ -0,0 +1,74 @@ +/* + * 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" + ], + "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": [ + "ohos.want.action.home" + ] + } + ] + } + ], + "extensionAbilities": [ + { + "name": "EntryBackupAbility", + "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets", + "type": "backup", + "exported": false, + "metadata": [ + { + "name": "ohos.extension.backup", + "resource": "$profile:backup_config" + } + ] + } + ], + "requestPermissions": [ + { + "name": "ohos.permission.CAMERA", + "reason": "$string:camera_permission", + "usedScene": { + "abilities": ["EntryAbility"], + "when": "always" + } + }, + ] + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/color.json b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..7e67488406eca711b2126a41d15432abce84b025 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/color.json @@ -0,0 +1,28 @@ +{ + "color": [ + { + "name": "start_window_background", + "value": "#FFFFFF" + }, + { + "name": "white", + "value": "#FFFFFF" + }, + { + "name": "gray", + "value": "#aabbcc" + }, + { + "name": "black", + "value": "#000000" + }, + { + "name": "green", + "value": "#73CD57" + }, + { + "name": "blue", + "value": "#FF2132CF" + } + ] +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/float.json b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/float.json new file mode 100644 index 0000000000000000000000000000000000000000..051fd4a9cc07648fe50025c5e7d6a554a9ddde32 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/float.json @@ -0,0 +1,36 @@ +{ + "float": [ + { + "name": "page_text_font_size", + "value": "50fp" + }, + { + "name": "index_text_font_size", + "value": "30fp" + }, + { + "name": "index_button_font_size", + "value": "30fp" + }, + { + "name": "index_button_width_size", + "value": "68px" + }, + { + "name": "index_button_height_size", + "value": "50fp" + }, + { + "name": "index_button_borderRadius_size", + "value": "10px" + }, + { + "name": "index_margin_size", + "value": "10px" + }, + { + "name": "BackUpComponent_margin_size", + "value": "100px" + } + ] +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/integer.json b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/integer.json new file mode 100644 index 0000000000000000000000000000000000000000..b78c61f1a5e75d09d5b70e9e3b0864e94506e68b --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/integer.json @@ -0,0 +1,8 @@ +{ + "integer": [ + { + "name": "BackUpComponent_text_font_size", + "value": 20 + } + ] +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/string.json b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000000000000000000000000000000000..47ead1fc1e6e26b459b55275afba63bb6cfb80d4 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/resources/base/element/string.json @@ -0,0 +1,24 @@ +{ + "string": [ + { + "name": "module_desc", + "value": "module description" + }, + { + "name": "EntryAbility_desc", + "value": "description" + }, + { + "name": "EntryAbility_label", + "value": "label" + }, + { + "name": "camera_permission", + "value": "apply camera" + }, + { + "name": "file_permission", + "value": "apply file" + } + ] +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/background.png b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/background.png new file mode 100644 index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f Binary files /dev/null and b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/background.png differ diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/block.png b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/block.png new file mode 100644 index 0000000000000000000000000000000000000000..b67324c6c6d2ff1a70acb0e3f5c3a4e3204ad3ee Binary files /dev/null and b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/block.png differ diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/foreground.png b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f Binary files /dev/null and b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/foreground.png differ diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/layered_image.json b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/layered_image.json new file mode 100644 index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a --- /dev/null +++ b/ImageKit/ImageNativeSample/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/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/startIcon.png b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/startIcon.png new file mode 100644 index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b Binary files /dev/null and b/ImageKit/ImageNativeSample/entry/src/main/resources/base/media/startIcon.png differ diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/profile/backup_config.json b/ImageKit/ImageNativeSample/entry/src/main/resources/base/profile/backup_config.json new file mode 100644 index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/resources/base/profile/backup_config.json @@ -0,0 +1,3 @@ +{ + "allowToBackupRestore": true +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/base/profile/main_pages.json b/ImageKit/ImageNativeSample/entry/src/main/resources/base/profile/main_pages.json new file mode 100644 index 0000000000000000000000000000000000000000..8c3968f802abb6729515e8bf78a9c2f28c92d09f --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/main/resources/base/profile/main_pages.json @@ -0,0 +1,10 @@ +{ + "src": [ + "pages/Index", + "pages/ImageCodec", + "pages/ImageReceiver", + "pages/PictureCodec", + "pages/EditExif", + "pages/GifCodec" + ] +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/dark/element/color.json b/ImageKit/ImageNativeSample/entry/src/main/resources/dark/element/color.json new file mode 100644 index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499 --- /dev/null +++ b/ImageKit/ImageNativeSample/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/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/allAux.jpg b/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/allAux.jpg new file mode 100644 index 0000000000000000000000000000000000000000..28eea137afa5584f35736d3b13423a8a9816df2a Binary files /dev/null and b/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/allAux.jpg differ diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/test.gif b/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/test.gif new file mode 100644 index 0000000000000000000000000000000000000000..9a26aa13f504995b61be7bdd235ab89e60e09beb Binary files /dev/null and b/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/test.gif differ diff --git a/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/test.jpeg b/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/test.jpeg new file mode 100644 index 0000000000000000000000000000000000000000..1cd1867bfa62c5e0c9f99844aa2d3fdeef253c6d Binary files /dev/null and b/ImageKit/ImageNativeSample/entry/src/main/resources/rawfile/test.jpeg differ diff --git a/ImageKit/ImageNativeSample/entry/src/mock/Libentry.mock.ets b/ImageKit/ImageNativeSample/entry/src/mock/Libentry.mock.ets new file mode 100644 index 0000000000000000000000000000000000000000..bbcd4ffee2dc23d8783fd8a1ac5e5325bc2b5240 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/mock/Libentry.mock.ets @@ -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. + */ +const nativeMock: Record = { + 'add': (a: number, b: number) => { + return a + b; + }, +}; + +export default nativeMock; \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/mock/mock-config.json5 b/ImageKit/ImageNativeSample/entry/src/mock/mock-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..98b0ae79f0090e1fc381d54c959fb32c9f7563f4 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/mock/mock-config.json5 @@ -0,0 +1,19 @@ +/* + * 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. + */ +{ + "libentry.so": { + "source": "src/mock/Libentry.mock.ets" + } +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Ability.test.ets b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Ability.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..7f30942b81554a399e89aa253c7089eca4f8d8d1 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Ability.test.ets @@ -0,0 +1,49 @@ +/* + * 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/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Exif.test.ets b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Exif.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..f53f607320843756135b570e258d4e8b2df3089d --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Exif.test.ets @@ -0,0 +1,269 @@ +/* +* 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, Level } from '@ohos/hypium'; +import { Driver, ON, MatchPattern } from '@ohos.UiTest'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import resourceManager from '@ohos.resourceManager'; +import inputMethod from '@ohos.inputMethod' + +const TAG = '[Sample_Exif]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Exif_'; +let abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let manager: resourceManager.ResourceManager; +const driver = Driver.create(); + +// 通用的测试函数。 +async function runTest(testCaseName: string, buttonText: string, delayTime: number, description: string, + done: Function) { + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, begin`); + + let btnAccept = await driver.findComponent(ON.text(buttonText)); + if (btnAccept !== undefined) { + await btnAccept.click(); + await driver.delayMs(delayTime); // 等待操作完成。 + } + else { + await driver.delayMs(delayTime); + } + + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, end`); + done(); // 测试完成。 +} + +export default function ExifTest() { + describe('ExifTest', () => { + // 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. + abilityDelegator.startAbility({ + bundleName: 'com.sample.ndkImage', + abilityName: 'EntryAbility' + }); + }) + 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. + }) + + // 单独运行该测试套时将获取权限的按钮解开。 + /** + * @tc.number Exif_GetAccess_0001 + * @tc.name Exif_GetAccess_0001 + * @tc.desc Request camera permissions + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_GetAccess_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_GetAccess_0001', // 测试用例名称。 + '允许', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'GetAccess_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Exif_EnterPage_0001 + * @tc.name Exif_EnterPage_0001 + * @tc.desc Enter Exif page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_EnterPage_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_EnterPage_0001', // 测试用例名称。 + '跳转到读取和修改Exif信息页面', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Exif_EnterPage', // 描述。 + done // done 回调。 + ); + }) + + // 创建ImageSource。 + /** + * @tc.number Exif_CreateImageSource_0001 + * @tc.name Exif_CreateImageSource_0001 + * @tc.desc Create ImageSource + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_CreateImageSource_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_CreateImageSource_0001', // 测试用例名称。 + 'CreateImageSource', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Exif_CreateImageSource_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Exif_Key_0001 + * @tc.name Exif_Key_0001 + * @tc.desc Specify the property key value + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_Key_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_Key_0001', // 测试用例名称 + 'ChoosePropertyKey', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Exif_Key_0001', // 描述 + done // done 回调 + ); + }) + + // 选择fNumber。 + /** + * @tc.number Exif_fNumber_0001 + * @tc.name Exif_fNumber_0001 + * @tc.desc Select fNumber + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_fNumber_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_fNumber_0001', // 测试用例名称 + 'FNumber', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Exif_fNumber_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Exif_GetImageProperty_0001 + * @tc.name Exif_GetImageProperty_0001 + * @tc.desc GetImageProperty + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_GetImageProperty_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_GetImageProperty_0001', // 测试用例名称 + 'GetImageProperty', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Exif_GetImageProperty_0001', // 描述。 + done // done 回调。 + ); + }) + + // 输入指定property的key值 + /** + * @tc.number Exif_ValueInput_0001 + * @tc.name Exif_ValueInput_0001 + * @tc.desc Enter the key value of the specified property + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_ValueInput_0001', Level.LEVEL1, async (done: Function) => { + hilog.info(DOMAIN, TAG, BUNDLE + `Exif_ValueInput_0001, begin`); + + let btnAccept = await driver.findComponent(ON.id('valueInput')); + if (btnAccept !== undefined) { + await btnAccept.click(); + await driver.delayMs(200); // 等待操作完成 + } + + let fNumber = await driver.findComponent(ON.text('1')); + if (fNumber !== undefined) { + await fNumber.click(); + await driver.delayMs(200); // 等待操作完成 + } + + let im = inputMethod.getController() + im.stopInputSession() + await driver.delayMs(200); // 等待操作完成 + + hilog.info(DOMAIN, TAG, BUNDLE + `Exif_ValueInput_0001, end`); + done(); // 测试完成 + }) + /** + * @tc.number Exif_Modify_0001 + * @tc.name Exif_Modify_0001 + * @tc.desc Modify Exif information + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_Modify_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_Modify_0001', // 测试用例名称 + 'ModifyImageProperty', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Exif_Modify_0001', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Exif_Release_0001 + * @tc.name Exif_Release_0001 + * @tc.desc Release source + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_Release_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_Release_0001', // 测试用例名称 + 'ReleaseImageSource', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Exif_Release', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Exif_EnterPage_0002 + * @tc.name Exif_EnterPage_0002 + * @tc.desc Enter index page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Exif_EnterPage_0002', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Exif_EnterPage_0002', // 测试用例名称。 + 'back', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Exif_EnterPage_0002', // 描述。 + done // done 回调。 + ); + }) + }) +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Gif.test.ets b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Gif.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..a172545770b9fb079f6e9fcdd6d9f56986b6ae4e --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Gif.test.ets @@ -0,0 +1,200 @@ +/* +* 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, Level } from '@ohos/hypium'; +import { Driver, ON, MatchPattern } from '@ohos.UiTest'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import resourceManager from '@ohos.resourceManager'; + +const TAG = '[Sample_Gif]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Gif_'; +let abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let manager: resourceManager.ResourceManager; +const driver = Driver.create(); + +// 通用的测试函数。 +async function runTest(testCaseName: string, buttonText: string, delayTime: number, description: string, + done: Function) { + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, begin`); + + let btnAccept = await driver.findComponent(ON.text(buttonText)); + if (btnAccept !== undefined) { + await btnAccept.click(); + await driver.delayMs(delayTime); // 等待操作完成。 + } + else { + await driver.delayMs(delayTime); + } + + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, end`); + done(); // 测试完成。 +} + +export default function GifTest() { + describe('GifTest', () => { + // 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. + abilityDelegator.startAbility({ + bundleName: 'com.sample.ndkImage', + abilityName: 'EntryAbility' + }); + }) + 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. + }) + + // 单独运行该测试套时将获取权限的按钮解开。 + // /** + // * @tc.number Gif_GetAccess_0001 + // * @tc.name Gif_GetAccess_0001 + // * @tc.desc Request camera permissions + // * @tc.size MediumTest + // * @tc.type Function + // * @tc.level Level 1 + // */ + // it('Gif_GetAccess_0001', Level.LEVEL1, async (done: Function) => { + // await runTest( + // 'Gif_GetAccess_0001', // 测试用例名称。 + // '允许', // 按钮文本。 + // 2000, // 延时 2000 毫秒。 + // 'GetAccess_0001', // 描述。 + // done // done 回调。 + // ); + // }) + + /** + * @tc.number Gif_EnterPage_0001 + * @tc.name Gif_EnterPage_0001 + * @tc.desc Enter Gif page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Gif_EnterPage_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Gif_EnterPage_0001', // 测试用例名称。 + '跳转到Gif编解码操作页面', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Gif_EnterPage', // 描述。 + done // done 回调。 + ); + }) + + // 创建ImageSource。 + /** + * @tc.number Gif_CreateImageSource_0001 + * @tc.name Gif_CreateImageSource_0001 + * @tc.desc Create ImageSource + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Gif_CreateImageSource_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Gif_CreateImageSource_0001', // 测试用例名称。 + 'CreateImageSource', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Gif_CreateImageSource_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Gif_CreatePixelmapList_0001 + * @tc.name Gif_CreatePixelmapList_0001 + * @tc.desc Create PixelmapList + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Gif_CreatePixelmapList_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Gif_CreatePixelmapList_0001', // 测试用例名称。 + 'CreatePixelmapList', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Gif_CreatePixelmapList_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Gif_GetDelayTimeList_0001 + * @tc.name Gif_GetDelayTimeList_0001 + * @tc.desc Get DelayTimeList + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Gif_GetDelayTimeList_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Gif_GetDelayTimeList_0001', // 测试用例名称。 + 'GetDelayTimeList', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Gif_GetDelayTimeList_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Gif_Release_0001 + * @tc.name Gif_Release_0001 + * @tc.desc Release source + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Gif_Release_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Gif_Release_0001', // 测试用例名称。 + 'ReleaseImageSource', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Gif_Release', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Gif_EnterPage_0002 + * @tc.name Gif_EnterPage_0002 + * @tc.desc Enter index page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Gif_EnterPage_0002', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Gif_EnterPage_0002', // 测试用例名称。 + 'back', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Gif_EnterPage_0002', // 描述。 + done // done 回调。 + ); + }) + }) +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/ImageSource.test.ets b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/ImageSource.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..012035874b1721da85c3488df848386ca524bfd0 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/ImageSource.test.ets @@ -0,0 +1,254 @@ +/* +* 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, Level } from '@ohos/hypium'; +import { Driver, ON, MatchPattern } from '@ohos.UiTest'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import resourceManager from '@ohos.resourceManager'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = '[Sample_ImagesSource]'; +const DOMAIN = 0xF811; +const BUNDLE = 'ImagesSource_'; +let abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let manager: resourceManager.ResourceManager; +const driver = Driver.create(); + +// 通用的测试函数 +async function runTest(testCaseName: string, buttonText: string, delayTime: number, description: string, + done: Function) { + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, begin`); + + let btnAccept = await driver.findComponent(ON.text(buttonText)); + if (btnAccept !== undefined) { + await btnAccept.click(); + await driver.delayMs(delayTime); // 等待操作完成 + } + else { + await driver.delayMs(delayTime); + } + + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, end`); + done(); // 测试完成 +} + +export default function ImagesSourceTest() { + describe('ImagesSourceTest', () => { + // 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. + abilityDelegator.startAbility({ + bundleName: 'com.sample.ndkImage', + abilityName: 'EntryAbility' + }); + }) + 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. + }) + + // 单独运行该测试套时将获取权限的按钮解开 + // /** + // * @tc.number ImagesSource_GetAccess_0001 + // * @tc.name ImagesSource_GetAccess_0001 + // * @tc.desc Request camera permissions + // * @tc.size MediumTest + // * @tc.type Function + // * @tc.level Level 1 + // */ + // it('ImagesSource_GetAccess_0001', Level.LEVEL1, async (done: Function) => { + // await runTest( + // 'ImagesSource_GetAccess_0001', // 测试用例名称 + // '允许', // 按钮文本 + // 2000, // 延时 2000 毫秒 + // 'GetAccess_0001', // 描述 + // done // done 回调 + // ); + // }) + + /** + * @tc.number ImagesSource_EnterPage_0001 + * @tc.name ImagesSource_EnterPage_0001 + * @tc.desc Enter ImagesSource page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_EnterPage_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_EnterPage_0001', // 测试用例名称。 + '跳转到图片编解码操作页面', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_EnterPage', // 描述。 + done // done 回调 + ); + }) + + /** + * @tc.number ImageSource_CreateImageSource_0001 + * @tc.name ImageSource_CreateImageSource_0001 + * @tc.desc Create ImageSource + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImageSource_CreateImageSource_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImageSource_CreateImageSource_0001', // 测试用例名称。 + 'CreateImageSource', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImageSource_CreateImageSource_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number ImagesSource_packToFileFromImageSource_0001 + * @tc.name ImagesSource_packToFileFromImageSource_0001 + * @tc.desc Pack to file from ImageSource + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_packToFileFromImageSource_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_packToFileFromImageSource_0001', // 测试用例名称。 + 'packToFileFromImageSource', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_packToFileFromImageSource_0001', // 描述。 + done // done 回调 + ); + }) + + /** + * @tc.number ImagesSource_GetImageInfo_0001 + * @tc.name ImagesSource_GetImageInfo_0001 + * @tc.desc Get ImageInfo + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_GetImageInfo_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_GetImageInfo_0001', // 测试用例名称。 + 'GetImageInfo', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_GetImageInfo_0001', // 描述。 + done // done 回调 + ); + }) + + /** + * @tc.number ImagesSource_createPixelMap_0001 + * @tc.name ImagesSource_createPixelMap_0001 + * @tc.desc Get ImageInfo + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_createPixelMap_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_createPixelMap_0001', // 测试用例名称。 + 'createPixelMap', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_createPixelMap_0001', // 描述。 + done // done 回调 + ); + }) + + /** + * @tc.number ImagesSource_packToFileFromPixelmap_0001 + * @tc.name ImagesSource_packToFileFromPixelmap_0001 + * @tc.desc Pack to file from Pixelmap + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_packToFileFromPixelmap_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_packToFileFromPixelmap_0001', // 测试用例名称。 + 'packToFileFromPixelmap', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_packToFileFromPixelmap_0001', // 描述。 + done // done 回调 + ); + }) + + /** + * @tc.number ImagesSource_CreatePixelmapUsingAllocator_0001 + * @tc.name ImagesSource_CreatePixelmapUsingAllocator_0001 + * @tc.desc Create pixelmap Using allocator + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_CreatePixelmapUsingAllocator_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_CreatePixelmapUsingAllocator_0001', // 测试用例名称。 + 'CreatePixelmapUsingAllocator', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_CreatePixelmapUsingAllocator_0001', // 描述。 + done // done 回调 + ); + }) + + /** + * @tc.number ImagesSource_Release_0001 + * @tc.name ImagesSource_Release_0001 + * @tc.desc Release source + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_Release_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_Release_0001', // 测试用例名称。 + 'ReleaseImageSource', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_Release', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number ImagesSource_EnterPage_0002 + * @tc.name ImagesSource_EnterPage_0002 + * @tc.desc Enter the last page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('ImagesSource_EnterPage_0002', Level.LEVEL1, async (done: Function) => { + await runTest( + 'ImagesSource_EnterPage_0002', // 测试用例名称。 + 'back', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'ImagesSource_EnterPage_0002', // 描述。 + done // done 回调 + ); + }) + }) +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/List.test.ets b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..e72b7543b5f64d83676b7e8e6d2f164798256884 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/List.test.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 abilityTest from './Ability.test'; +import ExifTest from './Exif.test'; +import GifTest from './Gif.test'; +import ImagesSourceTest from './ImageSource.test'; +import PictureTest from './Picture.test'; +import ReceiveTest from './Receiver.test'; + +export default function testsuite() { + abilityTest(); + ExifTest(); + GifTest(); + ImagesSourceTest(); + PictureTest(); + ReceiveTest(); +} diff --git a/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Picture.test.ets b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Picture.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..1f5a635310ae847619b3eccabec518a31bd9d908 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Picture.test.ets @@ -0,0 +1,218 @@ +/* +* 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, Level } from '@ohos/hypium'; +import { Driver, ON, MatchPattern } from '@ohos.UiTest'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import resourceManager from '@ohos.resourceManager'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = '[Sample_Picture]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Picture_'; +let abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let manager: resourceManager.ResourceManager; +const driver = Driver.create(); + +// 通用的测试函数。 +async function runTest(testCaseName: string, buttonText: string, delayTime: number, description: string, + done: Function) { + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, begin`); + + let btnAccept = await driver.findComponent(ON.text(buttonText)); + if (btnAccept !== undefined) { + await btnAccept.click(); + await driver.delayMs(delayTime); // 等待操作完成。 + } + else { + await driver.delayMs(delayTime); + } + + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, end`); + done(); // 测试完成。 +} + +export default function PictureTest() { + describe('PictureTest', () => { + // 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. + abilityDelegator.startAbility({ + bundleName: 'com.sample.ndkImage', + abilityName: 'EntryAbility' + }); + }) + 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. + }) + + // 单独运行该测试套时将获取权限的按钮解开。 + // /** + // * @tc.number Picture_GetAccess_0001 + // * @tc.name Picture_GetAccess_0001 + // * @tc.desc Request camera permissions + // * @tc.size MediumTest + // * @tc.type Function + // * @tc.level Level 1 + // */ + // it('Picture_GetAccess_0001', Level.LEVEL1, async (done: Function) => { + // await runTest( + // 'Picture_GetAccess_0001', // 测试用例名称。 + // '允许', // 按钮文本。 + // 2000, // 延时 2000 毫秒。 + // 'GetAccess_0001', // 描述。 + // done // done 回调。 + // ); + // }) + + /** + * @tc.number Picture_EnterPage_0001 + * @tc.name Picture_EnterPage_0001 + * @tc.desc Enter Picture page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Picture_EnterPage_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Picture_EnterPage_0001', // 测试用例名称。 + '跳转到picture编解码演示页面', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Picture_EnterPage', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Picture_SetDesiredAuxiliaryPictures_0001 + * @tc.name Picture_SetDesiredAuxiliaryPictures_0001 + * @tc.desc Set desired auxiliaryPictures + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Picture_SetDesiredAuxiliaryPictures_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Picture_SetDesiredAuxiliaryPictures_0001', // 测试用例名称。 + 'SetDesiredAuxiliaryPictures', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Picture_SetDesiredAuxiliaryPictures_0001', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Picture_CreatePictureByImageSource_0001 + * @tc.name Picture_CreatePictureByImageSource_0001 + * @tc.desc Create picture by imageSource + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Picture_CreatePictureByImageSource_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Picture_CreatePictureByImageSource_0001', // 测试用例名称 + 'CreatePictureByImageSource', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Picture_CreatePictureByImageSource_0001', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Picture_packToDataFromPicture_0001 + * @tc.name Picture_packToDataFromPicture_0001 + * @tc.desc Pack to data from picture + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Picture_packToDataFromPicture_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Picture_packToDataFromPicture_0001', // 测试用例名称 + 'packToDataFromPicture', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Picture_packToDataFromPicture_0001', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Picture_packToFileFromPicture_0001 + * @tc.name Picture_packToFileFromPicture_0001 + * @tc.desc Pack to file from picture + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Picture_packToFileFromPicture_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Picture_packToFileFromPicture_0001', // 测试用例名称 + 'packToFileFromPicture', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Picture_packToFileFromPicture_0001', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Picture_Release_0001 + * @tc.name Picture_Release_0001 + * @tc.desc Release source + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Picture_Release_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Picture_Release_0001', // 测试用例名称 + 'ReleasePictureSource', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Picture_Release', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Picture_EnterPage_0002 + * @tc.name Picture_EnterPage_0002 + * @tc.desc Enter the last page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Picture_EnterPage_0002', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Picture_EnterPage_0002', // 测试用例名称 + 'back', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Picture_EnterPage_0002', // 描述 + done // done 回调 + ); + }) + }) +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Receiver.test.ets b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Receiver.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..0e0e46b6aab1bced2709d04c09208fa543be73f7 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/ets/test/Receiver.test.ets @@ -0,0 +1,182 @@ +/* +* 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, Level } from '@ohos/hypium'; +import { Driver, ON, MatchPattern } from '@ohos.UiTest'; +import abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry'; +import resourceManager from '@ohos.resourceManager'; +import deviceInfo from '@ohos.deviceInfo'; + +const TAG = '[Sample_Receiver]'; +const DOMAIN = 0xF811; +const BUNDLE = 'Receiver_'; +let abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator(); +let manager: resourceManager.ResourceManager; +const driver = Driver.create(); + +// 通用的测试函数。 +async function runTest(testCaseName: string, buttonText: string, delayTime: number, description: string, + done: Function) { + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, begin`); + + let btnAccept = await driver.findComponent(ON.text(buttonText)); + if (btnAccept !== undefined) { + await btnAccept.click(); + await driver.delayMs(delayTime); // 等待操作完成。 + } + else { + await driver.delayMs(delayTime); + } + + hilog.info(DOMAIN, TAG, BUNDLE + `${description}, end`); + done(); // 测试完成。 +} + +export default function ReceiverTest() { + describe('ReceiverTest', () => { + // 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. + abilityDelegator.startAbility({ + bundleName: 'com.sample.ndkImage', + abilityName: 'EntryAbility' + }); + }) + 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. + }) + + // 单独运行该测试套时将获取权限的按钮解开。 + // /** + // * @tc.number Receiver_GetAccess_0001 + // * @tc.name Receiver_GetAccess_0001 + // * @tc.desc Request camera permissions + // * @tc.size MediumTest + // * @tc.type Function + // * @tc.level Level 1 + // */ + // it('Receiver_GetAccess_0001', Level.LEVEL1, async (done: Function) => { + // await runTest( + // 'Receiver_GetAccess_0001', // 测试用例名称。 + // '允许', // 按钮文本。 + // 2000, // 延时 2000 毫秒。 + // 'GetAccess_0001', // 描述。 + // done // done 回调。 + // ); + // }) + + /** + * @tc.number Receiver_EnterPage_0001 + * @tc.name Receiver_EnterPage_0001 + * @tc.desc Enter Receiver page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Receiver_EnterPage_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Receiver_EnterPage_0001', // 测试用例名称。 + '跳转到图片接收页面', // 按钮文本。 + 2000, // 延时 2000 毫秒。 + 'Receiver_EnterPage', // 描述。 + done // done 回调。 + ); + }) + + /** + * @tc.number Receiver_initImageReceiver_0001 + * @tc.name Receiver_initImageReceiver_0001 + * @tc.desc Init ImageReceiver + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Receiver_initImageReceiver_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Receiver_initImageReceiver_0001', // 测试用例名称 + 'initImageReceiver', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Receiver_initImageReceiver_0001', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Receiver_takePhoto_0001 + * @tc.name Receiver_takePhoto_0001 + * @tc.desc Take photo + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Receiver_takePhoto_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Receiver_takePhoto_0001', // 测试用例名称 + 'takePhoto', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Receiver_takePhoto_0001', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Receiver_Release_0001 + * @tc.name Receiver_Release_0001 + * @tc.desc Release source + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Receiver_Release_0001', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Receiver_Release_0001', // 测试用例名称 + 'releaseImageReceiver', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Receiver_Release', // 描述 + done // done 回调 + ); + }) + + /** + * @tc.number Receiver_EnterPage_0002 + * @tc.name Receiver_EnterPage_0002 + * @tc.desc Enter the last page + * @tc.size MediumTest + * @tc.type Function + * @tc.level Level 1 + */ + it('Receiver_EnterPage_0002', Level.LEVEL1, async (done: Function) => { + await runTest( + 'Receiver_EnterPage_0002', // 测试用例名称 + 'back', // 按钮文本 + 2000, // 延时 2000 毫秒 + 'Receiver_EnterPage_0002', // 描述 + done // done 回调 + ); + }) + }) +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/entry/src/ohosTest/module.json5 b/ImageKit/ImageNativeSample/entry/src/ohosTest/module.json5 new file mode 100644 index 0000000000000000000000000000000000000000..59667117c86b64ab9863f7b382c435ae4a3c32fa --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/ohosTest/module.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. + */ +{ + "module": { + "name": "entry_test", + "type": "feature", + "deviceTypes": [ + "default" + ], + "deliveryWithInstall": true, + "installationFree": false + } +} diff --git a/ImageKit/ImageNativeSample/entry/src/test/List.test.ets b/ImageKit/ImageNativeSample/entry/src/test/List.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..a60c87c5cbb0badf7c3fd8975034590e6fafa992 --- /dev/null +++ b/ImageKit/ImageNativeSample/entry/src/test/List.test.ets @@ -0,0 +1,19 @@ +/* + * 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/ImageKit/ImageNativeSample/entry/src/test/LocalUnit.test.ets b/ImageKit/ImageNativeSample/entry/src/test/LocalUnit.test.ets new file mode 100644 index 0000000000000000000000000000000000000000..8f6d7ba80e37fb21f64c3c8384df009d75952cd2 --- /dev/null +++ b/ImageKit/ImageNativeSample/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/ImageKit/ImageNativeSample/hvigor/hvigor-config.json5 b/ImageKit/ImageNativeSample/hvigor/hvigor-config.json5 new file mode 100644 index 0000000000000000000000000000000000000000..3b057578a1bb4d591ee53054e39ab0154fc2e43a --- /dev/null +++ b/ImageKit/ImageNativeSample/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": "6.0.0", + "dependencies": { + }, + "execution": { + // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | "ultrafine" | 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 */ + // "optimizationStrategy": "memory" /* Define the optimization strategy. Value: [ "memory" | "performance" ]. Default: "memory" */ + }, + "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/ImageKit/ImageNativeSample/hvigorfile.ts b/ImageKit/ImageNativeSample/hvigorfile.ts new file mode 100644 index 0000000000000000000000000000000000000000..ae9086af35844176c08f1be3772d081d95d267c6 --- /dev/null +++ b/ImageKit/ImageNativeSample/hvigorfile.ts @@ -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 { 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. */ +} \ No newline at end of file diff --git a/ImageKit/ImageNativeSample/oh-package.json5 b/ImageKit/ImageNativeSample/oh-package.json5 new file mode 100644 index 0000000000000000000000000000000000000000..ea8e9998db8cd7a235b666d8899f5b73b057d782 --- /dev/null +++ b/ImageKit/ImageNativeSample/oh-package.json5 @@ -0,0 +1,24 @@ +/* + * 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": "6.0.0", + "description": "Please describe the basic information.", + "dependencies": { + }, + "devDependencies": { + "@ohos/hypium": "1.0.15", + "@ohos/hamock": "1.0.0", + } +} diff --git a/ImageKit/ImageNativeSample/screenShots/Exif.png b/ImageKit/ImageNativeSample/screenShots/Exif.png new file mode 100644 index 0000000000000000000000000000000000000000..4ac1fbd87f33922ee4d653a46cd3ffb7b0324325 Binary files /dev/null and b/ImageKit/ImageNativeSample/screenShots/Exif.png differ diff --git a/ImageKit/ImageNativeSample/screenShots/codec.png b/ImageKit/ImageNativeSample/screenShots/codec.png new file mode 100644 index 0000000000000000000000000000000000000000..68f904289e59a7c567426285f0b39562a6ae2787 Binary files /dev/null and b/ImageKit/ImageNativeSample/screenShots/codec.png differ diff --git a/ImageKit/ImageNativeSample/screenShots/index.png b/ImageKit/ImageNativeSample/screenShots/index.png new file mode 100644 index 0000000000000000000000000000000000000000..1f6c3a94c57da3ed00fee1d07b861978073c6175 Binary files /dev/null and b/ImageKit/ImageNativeSample/screenShots/index.png differ