!4327 新增Sample_ImageEffect
Merge pull request !4327 from lusunqi/master
15
OAT.xml
@ -185,6 +185,21 @@ Note:If the text contains special characters, please escape them according to th
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/Camera_js/app_pic/auth1.jpg" desc="Provided by code/BasicFeature/Media/Camera_js"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/Camera_js/app_pic/auth4.jpg" desc="Provided by code/BasicFeature/Media/Camera_js"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/Camera_js/entry/src/ohosTest/resources/base/media/icon.png" desc="Provided by code/BasicFeature/Media/Camera_js"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/filter_details.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/brightness_efilter.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/filters_info.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/image_show.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/contrast_efilter.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/AppScope/resources/base/media/app_icon.png" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/filter_chains.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/entry/src/ohosTest/resources/base/media/icon.png" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/entry/src/main/resources/base/media/startIcon.png" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/crop_efilter.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/filter_selection.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/entry/src/main/resources/base/media/ic_1080x1920.jpg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/filter_parameters.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/screenshots/query_parameter.jpeg" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Media/ImageEffect/entry/src/main/resources/base/media/icon.png" desc="Provided by code/BasicFeature/Media/ImageEffect"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Connectivity/VPN/server/server.zip" desc="Provided by code/BasicFeature/Connectivity/VPN"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Connectivity/StageSocket/certificate_file.zip" desc="Provided by code/BasicFeature/Connectivity/StageSocket"/>
|
||||
<filteritem type="filepath" name="code/BasicFeature/Native/NdkDrawing/screenshots/device/Index.jpg" desc="Provided by code/BasicFeature/Native/NdkDrawing"/>
|
||||
|
13
code/BasicFeature/Media/ImageEffect/.gitignore
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/local.properties
|
||||
/.idea
|
||||
**/build
|
||||
/.hvigor
|
||||
.cxx
|
||||
/.clangd
|
||||
/.clang-format
|
||||
/.clang-tidy
|
||||
**/.test
|
||||
/oh-package-lock.json5
|
||||
/entry/oh-package-lock.json5
|
25
code/BasicFeature/Media/ImageEffect/AppScope/app.json5
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"app": {
|
||||
"bundleName": "com.samples.ImageEffect",
|
||||
"vendor": "example",
|
||||
"versionCode": 1000000,
|
||||
"versionName": "1.0.0",
|
||||
"icon": "$media:app_icon",
|
||||
"label": "$string:app_name"
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "app_name",
|
||||
"value": "ImageEffect"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 2.0 KiB |
117
code/BasicFeature/Media/ImageEffect/README_zh.md
Normal file
@ -0,0 +1,117 @@
|
||||
# 图片编辑
|
||||
|
||||
### 介绍
|
||||
|
||||
在本示例中,图片编解码模块提供了强大的图像处理功能。该模块能够有效生成pixelMap对象,供更进一步的图像操作使用。
|
||||
|
||||
- 算子接口整合
|
||||
|
||||
通过提供的图像算子接口,本示例支持对图片亮度、对比度以及裁剪等属性的调整。Brightness(亮度)、Contrast(对比度)和Crop(裁剪)等算子为开发者提供了便捷的方式来实现图片的基本处理需求。
|
||||
|
||||
- 自定义滤镜算子及算子链拓展<br>
|
||||
|
||||
框架为开发者设计了自定义算子接口,允许在已有功能基础上添加个性化的滤镜效果。开发者可以依照特定需求设计并集成新的算子,实现图像处理功能。
|
||||
|
||||
- 功能查询接口<br>
|
||||
|
||||
框架还提供了查询接口,允许开发者次查询单个算子或整个算子链的详细信息。
|
||||
|
||||
### 效果预览
|
||||
|
||||
| 图片展示 | 滤镜参数 | 滤镜选择 |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| <img src="screenshots/image_show.jpeg" alt="image_show.jpeg" style="zoom:20%;" /> | <img src="screenshots/filter_parameters.jpeg" alt="filter_parameters.jpeg" style="zoom:20%;" /> | <img src="screenshots/filter_selection.jpeg" alt="filter_selection.jpeg" style="zoom:20%;" /> |
|
||||
|
||||
| 滤镜信息 | 查询参数 | 查询信息 |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| <img src="screenshots/filter_details.jpeg" alt="filter_details.jpeg" style="zoom:20%;" /> | <img src="screenshots/query_parameter.jpeg" alt="query_parameter.jpeg" style="zoom:20%;" /> | <img src="screenshots/filters_info.jpeg" alt="image_show.jpeg" style="zoom:20%;" /> |
|
||||
|
||||
| 图片亮度调节 | 图片对比度调节 | 图片裁剪调节 | 图片滤镜链调节 |
|
||||
| :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: | :----------------------------------------------------------: |
|
||||
| <img src="screenshots/brightness_efilter.jpeg" alt="brightness_efilter.jpeg" style="zoom:20%;" /> | <img src="screenshots/contrast_efilter.jpeg" alt="contrast_efilter.jpeg" style="zoom:20%;" /> | <img src="screenshots/crop_efilter.jpeg" alt="crop_efilter.jpeg.jpeg" style="zoom:20%;" /> | <img src="screenshots/filter_chains.jpeg" alt="filter_chains.jpeg" style="zoom:20%;" /> |
|
||||
|
||||
使用说明:
|
||||
|
||||
1. 进入设置:在图片展示页面,点击位于右上角的设置图标,即可打开参数设置页面;
|
||||
|
||||
2. 调整滤镜参数:在参数设置页面中,选择所需的滤镜选项,并通过拖动滑动条来调节各个滤镜算子的参数;
|
||||
|
||||
3. 滤镜算子选择:您可以选择裁剪、缩放、旋转等内置的算子,或添加自定义滤镜。允许同时选择多个滤镜以形成滤镜链,满足复合效果需求;
|
||||
|
||||
4. 确认与保存设置:调整完毕后,点击确认按钮以保存所设置的滤镜参数;
|
||||
|
||||
5. 应用滤镜效果:返回图片展示页面后,点击Apply按钮,系统将展现经过滤镜处理后的图片效果;
|
||||
|
||||
6. 重置图片效果:如需撤销所做改动,点击Reset按钮,图片将恢复至调整前状态;
|
||||
|
||||
7. 再次进入设置:再次点击设置图标时,参数设置页面将显示上一次用户所选的参数设定;
|
||||
|
||||
8. 查看滤镜详细信息:在参数设置页面,点击滑块旁的搜索图标,系统将展示一个详细信息页面,提供所选滤镜相关信息;
|
||||
|
||||
9. 查询滤镜信息:点击查询按钮并选择查询参数来获取滤镜信息页面,该页面将显示所应用的滤镜个数和名称信息;
|
||||
|
||||
10. 退出应用:当需要退出应用程序时,上滑动作将应用放入系统垃圾箱中,完成退出操作;
|
||||
|
||||
|
||||
### 工程目录
|
||||
|
||||
```
|
||||
entry/src/main/cpp/
|
||||
|---backend
|
||||
| |---image_edit.cpp // 图片编辑native接口
|
||||
| |---image_edit.h
|
||||
|---types/libentry
|
||||
| |---index.d.ts // 类型声明
|
||||
| |---oh-package.json5 // 模块级依赖管理配置
|
||||
|---utils
|
||||
| |---common_utils.cpp // 字符串工具
|
||||
| |---common_utils.h
|
||||
|---CMakeLists.txt // 系统构建文件
|
||||
|---logging.h // 日志工具
|
||||
|---napi_init.cpp // NAPI的初始化文件
|
||||
entry/src/main/ets
|
||||
|---entryability
|
||||
| |---EntryAbility.ets // 应用入口
|
||||
|---pages
|
||||
| |---ImageEditPages.ets // 图片编辑页面
|
||||
|---utils
|
||||
| |---ImageUtils.ets // 图像处理
|
||||
```
|
||||
|
||||
具体实现
|
||||
|
||||
- 图片编辑功能在ImageEditPage中实现,源码参考[ImageEditPage.ets](entry%2Fsrc%2Fmain%2Fets%2Fpages%2FImageEdit.ets):
|
||||
- 滤镜选择:首先使用image的createImageSource生成pixelmap,然后在图片展示页面点击设置按钮弹出滤镜参数设置页面,选择滤镜并设置参数,点击确认按钮保存滤镜参数选择。
|
||||
- 滤镜生效:点击Apply按钮,展示经过滤镜处理后的图片效果,点击Reset按钮,图片恢复至调整前状态。
|
||||
- 滤镜查询:点击滑动条后面的查询图标可查询单个滤镜信息,点击下方查询按钮可查询对应条件的滤镜信息。
|
||||
- native接口在image_edit中实现,源码参考[image_edit.cpp](entry%2Fsrc%2Fmain%2Fcpp%2Fbackend%2Fimage_edit.cpp):
|
||||
- 图片编辑:图片编辑处理需要加载libimage_effect.so,对传入的pixelmap进行处理,使用Brightness对图像进行亮度处理使用Contrast对图像进行对比度处理,使用Crop对图像进行裁剪处理,也可以自定义滤镜对图像进行处理。
|
||||
- 滤镜查询:接口实现对滤镜的查询功能,通过OH_EffectFilter_LookupFilterInfo接口方法查询单个滤镜的详细信息,通过OH_EffectFilter_LookupFilters接口方法查询指定条件下的滤镜数量以及信息。
|
||||
|
||||
### 相关权限
|
||||
|
||||
不涉及。
|
||||
|
||||
### 依赖
|
||||
|
||||
不涉及。
|
||||
|
||||
### 约束与限制
|
||||
|
||||
1.本示例仅支持标准系统上运行,支持设备:RK3568;
|
||||
|
||||
2.本示例已适配API12版本SDK,版本号:5.0.0.21,镜像版本号:OpenHarmony5.0.0.21;
|
||||
|
||||
3.本示例需要使用DevEco Studio NEXT Developer Preview1 (Build Version: 4.1.3.501, built on February 5, 2024)才可编译运行。
|
||||
|
||||
### 下载
|
||||
|
||||
如需单独下载本工程,执行如下命令:
|
||||
|
||||
```
|
||||
git init
|
||||
git config core.sparsecheckout true
|
||||
echo code/BasicFeature/Media/ImageEffect/ > .git/info/sparse-checkout
|
||||
git remote add origin https://gitee.com/openharmony/applications_app_samples.git
|
||||
git pull origin master
|
||||
```
|
50
code/BasicFeature/Media/ImageEffect/build-profile.json5
Normal file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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": {
|
||||
"products": [
|
||||
{
|
||||
"name": "default",
|
||||
"signingConfig": "default",
|
||||
"compileSdkVersion": 12,
|
||||
"compatibleSdkVersion": 12,
|
||||
"runtimeOS": "OpenHarmony"
|
||||
}
|
||||
],
|
||||
"buildModeSet": [
|
||||
{
|
||||
"name": "debug"
|
||||
},
|
||||
{
|
||||
"name": "release"
|
||||
}
|
||||
],
|
||||
},
|
||||
"modules": [
|
||||
{
|
||||
"name": "entry",
|
||||
"srcPath": "./entry",
|
||||
"targets": [
|
||||
{
|
||||
"name": "default",
|
||||
"applyToProducts": [
|
||||
"default"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
6
code/BasicFeature/Media/ImageEffect/entry/.gitignore
vendored
Normal file
@ -0,0 +1,6 @@
|
||||
/node_modules
|
||||
/oh_modules
|
||||
/.preview
|
||||
/build
|
||||
/.cxx
|
||||
/.test
|
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"apiType": "stageMode",
|
||||
"buildOption": {
|
||||
"externalNativeOptions": {
|
||||
"path": "./src/main/cpp/CMakeLists.txt",
|
||||
"arguments": "",
|
||||
"cppFlags": "",
|
||||
"abiFilters": ["armeabi-v7a", "arm64-v8a"]
|
||||
}
|
||||
},
|
||||
"buildOptionSet": [
|
||||
{
|
||||
"name": "release",
|
||||
"arkOptions": {
|
||||
"obfuscation": {
|
||||
"ruleOptions": {
|
||||
"enable": true,
|
||||
"files": [
|
||||
"./obfuscation-rules.txt"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"nativeLib": {
|
||||
"debugSymbol": {
|
||||
"strip": true,
|
||||
"exclude": []
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"targets": [
|
||||
{
|
||||
"name": "default"
|
||||
},
|
||||
{
|
||||
"name": "ohosTest",
|
||||
}
|
||||
]
|
||||
}
|
6
code/BasicFeature/Media/ImageEffect/entry/hvigorfile.ts
Normal file
@ -0,0 +1,6 @@
|
||||
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. */
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
# 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://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
|
||||
|
||||
# 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
|
26
code/BasicFeature/Media/ImageEffect/entry/oh-package.json5
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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"
|
||||
}
|
||||
}
|
@ -0,0 +1,27 @@
|
||||
# the minimum version of CMake.
|
||||
cmake_minimum_required(VERSION 3.4.1)
|
||||
project(ImageEffect)
|
||||
|
||||
set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
include_directories(${NATIVERENDER_ROOT_PATH}
|
||||
${NATIVERENDER_ROOT_PATH}/include
|
||||
${NATIVERENDER_ROOT_PATH}/backend
|
||||
${NATIVERENDER_ROOT_PATH}/utils
|
||||
)
|
||||
|
||||
add_library(entry SHARED
|
||||
napi_init.cpp
|
||||
utils/common_utils.cpp
|
||||
utils/pixelmap_helper.cpp
|
||||
backend/image_edit.cpp
|
||||
)
|
||||
target_link_libraries(entry PUBLIC
|
||||
libace_napi.z.so
|
||||
libhilog_ndk.z.so
|
||||
libpixelmap.so
|
||||
libimage_effect.so
|
||||
libpixelmap_ndk.z.so
|
||||
libimage_packer.so
|
||||
libimage_source.so
|
||||
)
|
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 "image_edit.h"
|
||||
#include <map>
|
||||
#include <bits/alltypes.h>
|
||||
|
||||
#include <multimedia/image_effect/image_effect.h>
|
||||
#include <multimedia/image_framework/image_pixel_map_mdk.h>
|
||||
#include "logging.h"
|
||||
#include "utils/common_utils.h"
|
||||
#include "utils/pixelmap_helper.h"
|
||||
|
||||
struct FilterArrayData {
|
||||
std::string name;
|
||||
int value;
|
||||
};
|
||||
|
||||
struct PixelmapInfo {
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
int32_t format = PIXEL_FORMAT::PIXEL_FORMAT_UNKNOWN;
|
||||
uint32_t rowStride = 0;
|
||||
};
|
||||
|
||||
static ImageEffect_FilterDelegate delegate;
|
||||
|
||||
std::vector<std::vector<FilterArrayData>> GetFilters(napi_env env, napi_value arg);
|
||||
|
||||
OH_EffectFilter *AddFilter(OH_ImageEffect *imageEffect, const char *filterName);
|
||||
napi_value SetFilterValue(OH_EffectFilter *filter, const char *filterName, float filterValue,
|
||||
OH_PixelmapNative *pixelmap);
|
||||
|
||||
const double PI = 3.14159265;
|
||||
|
||||
constexpr int EXPECTED_ARGS_ZERO = 0;
|
||||
constexpr int EXPECTED_ARGS_ONE = 1;
|
||||
constexpr int EXPECTED_ARGS_TWO = 2;
|
||||
|
||||
constexpr int AREA_INFO_ZERO = 0;
|
||||
constexpr int AREA_INFO_ONE = 1;
|
||||
constexpr int AREA_INFO_TWO = 2;
|
||||
constexpr int AREA_INFO_THREE = 3;
|
||||
|
||||
constexpr int RGB_IDX_ONE = 1;
|
||||
constexpr int RGB_IDX_TWO = 2;
|
||||
constexpr int RGB_IDX_THREE = 3;
|
||||
|
||||
constexpr int EXPECTED_CONSTANT_THREE = 3;
|
||||
constexpr int EXPECTED_CONSTANT_FOUR = 4;
|
||||
constexpr int EXPECTED_LUT_SIZE_LIMIT = 256;
|
||||
|
||||
const int LUT_CYCLE_SIZE = 256;
|
||||
|
||||
napi_value ImageEdit::Apply(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_value result = nullptr;
|
||||
napi_get_undefined(env, &result);
|
||||
|
||||
size_t argc = EXPECTED_ARGS_TWO;
|
||||
napi_value args[EXPECTED_ARGS_TWO] = {nullptr};
|
||||
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_get_cb_info fail! status = %{public}d", status);
|
||||
|
||||
std::string path = CommonUtils::GetStringArgument(env, args[EXPECTED_ARGS_ZERO]);
|
||||
std::vector<std::vector<FilterArrayData>> filters = GetFilters(env, args[EXPECTED_ARGS_ONE]);
|
||||
|
||||
OH_ImageEffect *imageEffect = OH_ImageEffect_Create("imageEdit");
|
||||
CHECK_AND_RETURN_RET_LOG(imageEffect != nullptr, result, "OH_ImageEffect_Create fail!");
|
||||
std::shared_ptr<OH_ImageEffect> imageEffectPtr(imageEffect, [](OH_ImageEffect *imageEffect) {
|
||||
OH_ImageEffect_Release(imageEffect);
|
||||
});
|
||||
|
||||
std::shared_ptr<OH_PixelmapNative> pixelmapNativePtr = PixelMapHelper::Decode(path);
|
||||
CHECK_AND_RETURN_RET_LOG(pixelmapNativePtr != nullptr, result, "Decode path fail! path=%{public}s", path.c_str());
|
||||
|
||||
for (int i = 0; i < filters.size(); i++) {
|
||||
OH_EffectFilter *filter = AddFilter(imageEffectPtr.get(), filters[i][0].name.c_str());
|
||||
CHECK_AND_RETURN_RET_LOG(filter != nullptr, result, "OH_ImageEffect_AddFilter fail!");
|
||||
SetFilterValue(filter, filters[i][0].name.c_str(), filters[i][0].value, pixelmapNativePtr.get());
|
||||
}
|
||||
|
||||
ImageEffect_ErrorCode errorCode = OH_ImageEffect_SetInputPixelmap(imageEffectPtr.get(), pixelmapNativePtr.get());
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, result,
|
||||
"OH_ImageEffect_SetInputPixelMap fail! errorCode = %{public}d", errorCode);
|
||||
|
||||
errorCode = OH_ImageEffect_Start(imageEffectPtr.get());
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, result,
|
||||
"OH_ImageEffect_Start fail! errorCode = %{public}d", errorCode);
|
||||
|
||||
bool encodeRes = PixelMapHelper::Encode(pixelmapNativePtr.get(), path);
|
||||
CHECK_AND_RETURN_RET_LOG(encodeRes, result, "Encode path fail! path=%{public}s", path.c_str());
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
OH_EffectFilter *AddFilter(OH_ImageEffect *imageEffect, const char *filterName)
|
||||
{
|
||||
OH_EffectFilter *filter = OH_ImageEffect_AddFilter(imageEffect, filterName);
|
||||
CHECK_AND_RETURN_RET_LOG(filter != nullptr, filter, "OH_ImageEffect_AddFilter fail!");
|
||||
return filter;
|
||||
}
|
||||
|
||||
PixelmapInfo GetPixelmapInfo(OH_PixelmapNative *pixelmap)
|
||||
{
|
||||
OH_Pixelmap_ImageInfo *imageInfo = nullptr;
|
||||
OH_PixelmapImageInfo_Create(&imageInfo);
|
||||
OH_PixelmapNative_GetImageInfo(pixelmap, imageInfo);
|
||||
PixelmapInfo info;
|
||||
OH_PixelmapImageInfo_GetWidth(imageInfo, &info.width);
|
||||
OH_PixelmapImageInfo_GetHeight(imageInfo, &info.height);
|
||||
OH_PixelmapImageInfo_GetPixelFormat(imageInfo, &info.format);
|
||||
OH_PixelmapImageInfo_GetRowStride(imageInfo, &info.rowStride);
|
||||
OH_PixelmapImageInfo_Release(imageInfo);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
napi_value SetFilterValue(OH_EffectFilter *filter, const char *filterName, float filterValue,
|
||||
OH_PixelmapNative *pixelmap)
|
||||
{
|
||||
napi_value result;
|
||||
ImageEffect_Any value;
|
||||
std::string key;
|
||||
|
||||
if (strcmp(filterName, OH_EFFECT_CROP_FILTER) == 0) {
|
||||
PixelmapInfo pixelMapInfo = GetPixelmapInfo(pixelmap);
|
||||
uint32_t *areaInfo = new uint32_t[4];
|
||||
CHECK_AND_RETURN_RET_LOG(areaInfo, result, "areaInfo fail!");
|
||||
areaInfo[AREA_INFO_ZERO] = pixelMapInfo.width / 100.f * (100.f - static_cast<int>(filterValue));
|
||||
areaInfo[AREA_INFO_ONE] = pixelMapInfo.height / 100.f * (100.f - static_cast<int>(filterValue));
|
||||
areaInfo[AREA_INFO_TWO] = pixelMapInfo.width;
|
||||
areaInfo[AREA_INFO_THREE] = pixelMapInfo.height;
|
||||
value.dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_PTR;
|
||||
value.dataValue.ptrValue = areaInfo;
|
||||
key = OH_EFFECT_FILTER_REGION_KEY;
|
||||
} else if (strcmp(filterName, "CustomBrightness") == 0) {
|
||||
value.dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT;
|
||||
value.dataValue.floatValue = filterValue;
|
||||
key = "brightness";
|
||||
} else {
|
||||
value.dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT;
|
||||
value.dataValue.floatValue = filterValue;
|
||||
key = OH_EFFECT_FILTER_INTENSITY_KEY;
|
||||
}
|
||||
|
||||
ImageEffect_ErrorCode errorCode = OH_EffectFilter_SetValue(filter, key.c_str(), &value);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, nullptr,
|
||||
"OH_EffectFilter_SetValue fail! errorCode = %{public}d", errorCode);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::pair<napi_status, uint32_t> GetNapiArrayLength(napi_env env, napi_value element)
|
||||
{
|
||||
uint32_t length = 0;
|
||||
napi_status status = napi_get_array_length(env, element, &length);
|
||||
return std::make_pair(status, length);
|
||||
}
|
||||
|
||||
std::string HandleStringType(napi_env env, napi_value childElement, napi_status &status)
|
||||
{
|
||||
std::string name;
|
||||
|
||||
size_t bufferLength = 0;
|
||||
status = napi_get_value_string_utf8(env, childElement, nullptr, 0, &bufferLength);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok && bufferLength > 0, name,
|
||||
"GetFilters napi_get_value_string_utf8 fail! status = %{public}d", status);
|
||||
char *buffer = nullptr;
|
||||
buffer = reinterpret_cast<char *>(malloc((bufferLength + 1) * sizeof(char)));
|
||||
status = napi_get_value_string_utf8(env, childElement, buffer, bufferLength + 1, &bufferLength);
|
||||
if (status == napi_ok) {
|
||||
name = buffer;
|
||||
}
|
||||
free(buffer);
|
||||
return name;
|
||||
}
|
||||
|
||||
int HandleNumberType(napi_env env, napi_value childElement, napi_status &status)
|
||||
{
|
||||
int32_t result = 0;
|
||||
status = napi_get_value_int32(env, childElement, &result);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "GetFilters napi_get_value_int32 fail! status = %{public}d",
|
||||
status);
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::vector<FilterArrayData>> GetFilters(napi_env env, napi_value arg)
|
||||
{
|
||||
std::vector<std::vector<FilterArrayData>> data;
|
||||
napi_status status;
|
||||
|
||||
bool is_array;
|
||||
status = napi_is_array(env, arg, &is_array);
|
||||
CHECK_AND_RETURN_RET_LOG(is_array == true, data, "GetFilters napi_is_array fail! status=%{public}d", status);
|
||||
|
||||
// Handle napi array length
|
||||
auto array_length = GetNapiArrayLength(env, arg);
|
||||
CHECK_AND_RETURN_RET_LOG(array_length.first == napi_ok, data,
|
||||
"GetFilters napi_get_array_length fail! status=%{public}d", array_length.first);
|
||||
|
||||
for (uint32_t i = 0; i < array_length.second; i++) {
|
||||
napi_value element;
|
||||
status = napi_get_element(env, arg, i, &element);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok, data, "GetFilters napi_get_element fail! status=%{public}d",
|
||||
status);
|
||||
|
||||
auto child_length = GetNapiArrayLength(env, element);
|
||||
CHECK_AND_RETURN_RET_LOG(child_length.first == napi_ok, data,
|
||||
"GetFilters child napi_get_array_length fail! status=%{public}d", child_length.first);
|
||||
|
||||
std::vector<FilterArrayData> row;
|
||||
FilterArrayData filterArrayData;
|
||||
for (uint32_t j = 0; j < child_length.second; j++) {
|
||||
napi_value childElement;
|
||||
status = napi_get_element(env, element, j, &childElement);
|
||||
|
||||
napi_valuetype valueType;
|
||||
status = napi_typeof(env, childElement, &valueType);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok, data,
|
||||
"GetFilters child napi_typeof fail! status=%{public}d, value=%{public}d", status, valueType);
|
||||
|
||||
if (valueType == napi_string) {
|
||||
filterArrayData.name = HandleStringType(env, childElement, status);
|
||||
} else if (valueType == napi_number) {
|
||||
filterArrayData.value = HandleNumberType(env, childElement, status);
|
||||
}
|
||||
}
|
||||
row.push_back(filterArrayData);
|
||||
data.push_back(row);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
napi_value ImageEdit::LookupFilterInfo(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_value result = nullptr;
|
||||
napi_get_undefined(env, &result);
|
||||
size_t argc = EXPECTED_ARGS_ONE;
|
||||
napi_value args[EXPECTED_ARGS_ONE] = {nullptr};
|
||||
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_get_cb_info fail! status = %{public}d", status);
|
||||
std::string filterName = CommonUtils::GetStringArgument(env, args[EXPECTED_ARGS_ZERO]);
|
||||
|
||||
OH_EffectFilterInfo *effectInfo = OH_EffectFilterInfo_Create();
|
||||
// 示例代码: 传入nullptr的format, 获取OH_Formats的size
|
||||
ImageEffect_ErrorCode errorCode = OH_EffectFilter_LookupFilterInfo(filterName.c_str(), effectInfo);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, result,
|
||||
"OH_EffectFilter_LookupFilterInfo fail! errorCode = %{public}d", errorCode);
|
||||
|
||||
char *name = nullptr;
|
||||
OH_EffectFilterInfo_GetFilterName(effectInfo, &name);
|
||||
|
||||
uint32_t supportedBufferTypesCount = 0;
|
||||
ImageEffect_BufferType *bufferTypeArray = nullptr;
|
||||
OH_EffectFilterInfo_GetSupportedBufferTypes(effectInfo, &supportedBufferTypesCount, &bufferTypeArray);
|
||||
|
||||
uint32_t supportedFormatsCount = 0;
|
||||
ImageEffect_Format *formatArray = nullptr;
|
||||
OH_EffectFilterInfo_GetSupportedFormats(effectInfo, &supportedFormatsCount, &formatArray);
|
||||
|
||||
LOG_I("LookupFilterInfo: name=%{public}s, bufferTypesCount=%{public}d, formatsCount=%{public}d", name,
|
||||
supportedBufferTypesCount, supportedFormatsCount);
|
||||
|
||||
std::string infoStr = CommonUtils::EffectInfoToString(effectInfo);
|
||||
LOG_I("LookupFilterInfo:%{public}s", infoStr.c_str());
|
||||
status = napi_create_string_utf8(env, infoStr.c_str(), strlen(infoStr.c_str()), &result);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_create_string_utf8 fail!");
|
||||
|
||||
OH_EffectFilterInfo_Release(effectInfo);
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value ImageEdit::RegisterCustomBrightness()
|
||||
{
|
||||
napi_value result = nullptr;
|
||||
// 自定义算子能力信息
|
||||
OH_EffectFilterInfo *effectInfo = OH_EffectFilterInfo_Create();
|
||||
OH_EffectFilterInfo_SetFilterName(effectInfo, "CustomBrightness");
|
||||
ImageEffect_BufferType bufferType = ImageEffect_BufferType::EFFECT_BUFFER_TYPE_PIXEL;
|
||||
OH_EffectFilterInfo_SetSupportedBufferTypes(effectInfo, 1, &bufferType);
|
||||
ImageEffect_Format format = ImageEffect_Format::EFFECT_PIXEL_FORMAT_RGBA8888;
|
||||
OH_EffectFilterInfo_SetSupportedFormats(effectInfo, 1, &format);
|
||||
// 自定义算子实现接口
|
||||
delegate = {
|
||||
.setValue = [](OH_EffectFilter *filter, const char *key, const ImageEffect_Any *value) { return true; },
|
||||
.render = [](OH_EffectFilter *filter, OH_EffectBufferInfo *src,
|
||||
OH_EffectFilterDelegate_PushData pushData) { return true; },
|
||||
.save = [](OH_EffectFilter *filter, char **info) { return true; },
|
||||
.restore = [](const char *info) { return OH_EffectFilter_Create("CustomBrightness"); }};
|
||||
ImageEffect_ErrorCode errorCode = OH_EffectFilter_Register(effectInfo, &delegate);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, result,
|
||||
"OH_EffectFilter_Register fail! errorCode = %{public}d", errorCode);
|
||||
OH_EffectFilter *filter = OH_EffectFilter_Create("CustomBrightness");
|
||||
CHECK_AND_RETURN_RET_LOG(filter != nullptr, result, "OH_ImageEffect_AddFilter fail!");
|
||||
ImageEffect_Any value;
|
||||
std::string key = "";
|
||||
value.dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT, value.dataValue.floatValue = 0;
|
||||
key = "brightness";
|
||||
OH_ImageEffect *imageEffect = OH_ImageEffect_Create("imageEdit");
|
||||
OH_EffectFilter *customerFilter = OH_ImageEffect_AddFilter(imageEffect, "CustomBrightness");
|
||||
CHECK_AND_RETURN_RET_LOG(customerFilter != nullptr, result, "OH_ImageEffect_AddFilter fail!");
|
||||
return result;
|
||||
}
|
||||
|
||||
napi_value ImageEdit::LookupFilters(napi_env env, napi_callback_info info)
|
||||
{
|
||||
napi_value result = nullptr;
|
||||
napi_get_undefined(env, &result);
|
||||
size_t argc = EXPECTED_ARGS_ONE;
|
||||
napi_value args[EXPECTED_ARGS_ONE] = {nullptr};
|
||||
napi_status status = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
||||
CHECK_AND_RETURN_RET_LOG(status == napi_ok, result, "napi_get_cb_info fail! status = %{public}d", status);
|
||||
const char *key = CommonUtils::GetStringArgument(env, args[EXPECTED_ARGS_ZERO]);
|
||||
|
||||
ImageEffect_FilterNames *filterNames = OH_EffectFilter_LookupFilters(key);
|
||||
CHECK_AND_RETURN_RET_LOG(filterNames != nullptr, result, "OH_EffectFilter_LookupFilters fail!");
|
||||
|
||||
std::string res = "size: " + std::to_string(filterNames->size) + std::string(", name: ");
|
||||
for (int i = 0; i < filterNames->size; i++) {
|
||||
res += filterNames->nameList[i];
|
||||
if (i < filterNames->size - 1) {
|
||||
res += " | ";
|
||||
}
|
||||
}
|
||||
status = napi_create_string_utf8(env, res.c_str(), res.size(), &result);
|
||||
return result;
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 IMAGE_EDIT_H
|
||||
#define IMAGE_EDIT_H
|
||||
|
||||
#include "napi/native_api.h"
|
||||
|
||||
class ImageEdit {
|
||||
public:
|
||||
static napi_value Apply(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value LookupFilterInfo(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value LookupFilters(napi_env env, napi_callback_info info);
|
||||
|
||||
static napi_value RegisterCustomBrightness();
|
||||
};
|
||||
|
||||
#endif //IMAGE_EDIT_H
|
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 IMAGE_EFFECT_LOGGING_H
|
||||
#define IMAGE_EFFECT_LOGGING_H
|
||||
|
||||
#include <hilog/log.h>
|
||||
|
||||
#define EFFECT_LOG_TAG "ImageEffectSample"
|
||||
|
||||
#define LOG_I(...) OH_LOG_Print(LOG_APP, LOG_INFO, 0xFF00, EFFECT_LOG_TAG, __VA_ARGS__)
|
||||
#define LOG_W(...) OH_LOG_Print(LOG_APP, LOG_WARN, 0xFF00, EFFECT_LOG_TAG, __VA_ARGS__)
|
||||
#define LOG_E(...) OH_LOG_Print(LOG_APP, LOG_ERROR, 0xFF00, EFFECT_LOG_TAG, __VA_ARGS__)
|
||||
|
||||
#endif // IMAGE_EFFECT_LOGGING_H
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 "image_edit.h"
|
||||
|
||||
napi_property_descriptor DESCRIPTOR(const char *name, napi_callback cb)
|
||||
{
|
||||
napi_property_descriptor desc = {name, nullptr, cb, nullptr, nullptr, nullptr, napi_default, nullptr};
|
||||
return desc;
|
||||
}
|
||||
|
||||
EXTERN_C_START
|
||||
void RegisterCustomBrightness() { ImageEdit::RegisterCustomBrightness(); }
|
||||
|
||||
static napi_value Init(napi_env env, napi_value exports)
|
||||
{
|
||||
RegisterCustomBrightness();
|
||||
|
||||
napi_property_descriptor desc[] = {
|
||||
DESCRIPTOR("apply", ImageEdit::Apply),
|
||||
DESCRIPTOR("lookupFilterInfo", ImageEdit::LookupFilterInfo),
|
||||
DESCRIPTOR("lookupFilters", ImageEdit::LookupFilters),
|
||||
};
|
||||
napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
|
||||
return exports;
|
||||
}
|
||||
EXTERN_C_END
|
||||
|
||||
static napi_module demoModule = {
|
||||
.nm_version = 1,
|
||||
.nm_flags = 0,
|
||||
.nm_filename = nullptr,
|
||||
.nm_register_func = Init,
|
||||
.nm_modname = "entry",
|
||||
.nm_priv = ((void *)0),
|
||||
.reserved = {0},
|
||||
};
|
||||
|
||||
extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
|
26
code/BasicFeature/Media/ImageEffect/entry/src/main/cpp/types/libentry/index.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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';
|
||||
|
||||
declare namespace ImageEffect {
|
||||
const apply: (path: string, filterOptions: Array<Array<String|number>>) => void;
|
||||
|
||||
const lookupFilterInfo: (name: String) => string;
|
||||
|
||||
const lookupFilters: (key: String) => string;
|
||||
}
|
||||
|
||||
export default ImageEffect;
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "libentry.so",
|
||||
"types": "./index.d.ts",
|
||||
"version": "",
|
||||
"description": "Please describe the basic information."
|
||||
}
|
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "common_utils.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "logging.h"
|
||||
|
||||
const std::map<ImageEffect_Format, const char *> formatToStr_ = {
|
||||
{ImageEffect_Format::EFFECT_PIXEL_FORMAT_RGBA8888, "RGBA8888"},
|
||||
{ImageEffect_Format::EFFECT_PIXEL_FORMAT_NV12, "YUVNV12"},
|
||||
{ImageEffect_Format::EFFECT_PIXEL_FORMAT_NV21, "YUVNV21"},
|
||||
};
|
||||
|
||||
const std::map<ImageEffect_BufferType, const char *> bufferTypeToStr_ = {
|
||||
{ImageEffect_BufferType::EFFECT_BUFFER_TYPE_PIXEL, "Pixel"},
|
||||
{ImageEffect_BufferType::EFFECT_BUFFER_TYPE_TEXTURE, "Texture"},
|
||||
};
|
||||
|
||||
const char *CommonUtils::GetStringArgument(napi_env env, napi_value value)
|
||||
{
|
||||
char *buffer = nullptr;
|
||||
size_t bufferLength = 0;
|
||||
napi_status status = napi_get_value_string_utf8(env, value, nullptr, 0, &bufferLength);
|
||||
if (status == napi_ok && bufferLength > 0) {
|
||||
buffer = reinterpret_cast<char *>(malloc((bufferLength + 1) * sizeof(char)));
|
||||
if (buffer == nullptr) {
|
||||
LOG_E("No memory");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
status = napi_get_value_string_utf8(env, value, buffer, bufferLength + 1, &bufferLength);
|
||||
if (status != napi_ok) {
|
||||
LOG_E("napi_get_value_string_utf8 fail");
|
||||
free(buffer);
|
||||
buffer = nullptr;
|
||||
}
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char *GetBufferType(ImageEffect_BufferType &bufferType)
|
||||
{
|
||||
auto it = bufferTypeToStr_.find(bufferType);
|
||||
if (it == bufferTypeToStr_.end()) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
const char *GetFormat(ImageEffect_Format &ohFormat)
|
||||
{
|
||||
auto it = formatToStr_.find(ohFormat);
|
||||
if (it == formatToStr_.end()) {
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::string CommonUtils::EffectInfoToString(OH_EffectFilterInfo *info)
|
||||
{
|
||||
std::string result = "";
|
||||
|
||||
char *name = nullptr;
|
||||
OH_EffectFilterInfo_GetFilterName(info, &name);
|
||||
result += "name:" + std::string(name) + ", ";
|
||||
|
||||
uint32_t supportedBufferTypesSize = 0;
|
||||
ImageEffect_BufferType *bufferTypeArray = nullptr;
|
||||
OH_EffectFilterInfo_GetSupportedBufferTypes(info, &supportedBufferTypesSize, &bufferTypeArray);
|
||||
result += "supportedBufferType: {";
|
||||
for (uint32_t i = 0;i < supportedBufferTypesSize; ++i) {
|
||||
ImageEffect_BufferType bufferType = bufferTypeArray[i];
|
||||
result += GetBufferType(bufferType) + std::string(" ");
|
||||
}
|
||||
result += "}";
|
||||
|
||||
uint32_t supportedFormatsSize = 0;
|
||||
ImageEffect_Format *formatArray = nullptr;
|
||||
OH_EffectFilterInfo_GetSupportedFormats(info, &supportedFormatsSize, &formatArray);
|
||||
result += "supportedFormat: {";
|
||||
for (uint32_t i = 0;i < supportedFormatsSize; ++i) {
|
||||
ImageEffect_Format ohFormat = formatArray[i];
|
||||
result += GetFormat(ohFormat) + std::string(" ");
|
||||
}
|
||||
result += "}";
|
||||
|
||||
return result;
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 COMMON_UTILS_H
|
||||
#define COMMON_UTILS_H
|
||||
|
||||
#include <string>
|
||||
#include "napi/native_api.h"
|
||||
|
||||
#include "logging.h"
|
||||
#include <multimedia/image_effect/image_effect_filter.h>
|
||||
|
||||
#define CHECK_AND_RETURN_RET_LOG(cond, ret, fmt, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
LOG_E(fmt, ##__VA_ARGS__); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_AND_RETURN_LOG(cond, fmt, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
LOG_E(fmt, ##__VA_ARGS__); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_AND_NO_RETURN_LOG(cond, fmt, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
LOG_E(fmt, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_AND_RETURN_NO_RET(cond, fmt, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
LOG_E(fmt, ##__VA_ARGS__); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
class CommonUtils {
|
||||
public:
|
||||
static const char *GetStringArgument(napi_env env, napi_value value);
|
||||
|
||||
static std::string EffectInfoToString(OH_EffectFilterInfo *info);
|
||||
};
|
||||
|
||||
#endif // COMMON_UTILS_H
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 "pixelmap_helper.h"
|
||||
#include "common_utils.h"
|
||||
#include <multimedia/image_framework/image_source_native.h>
|
||||
#include <multimedia/image_framework/image_packer_native.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
constexpr int EXPECTED_ONE_HUNDRED = 100;
|
||||
|
||||
std::shared_ptr<OH_DecodingOptions> CreateDecodingOptions()
|
||||
{
|
||||
OH_DecodingOptions *options = nullptr;
|
||||
Image_ErrorCode errorCode = OH_DecodingOptions_Create(&options);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == Image_ErrorCode::IMAGE_SUCCESS, nullptr,
|
||||
"OH_DecodingOptions_Create fail! errorCode=%{public}d", errorCode);
|
||||
|
||||
std::shared_ptr<OH_DecodingOptions> optionsPtr(options, [](OH_DecodingOptions *options) {
|
||||
OH_DecodingOptions_Release(options);
|
||||
});
|
||||
|
||||
return optionsPtr;
|
||||
}
|
||||
|
||||
std::shared_ptr<OH_PixelmapNative> PixelMapHelper::Decode(std::string &pathName)
|
||||
{
|
||||
int fd = open(pathName.c_str(), O_RDWR);
|
||||
CHECK_AND_RETURN_RET_LOG(fd != -1, nullptr, "Open path fail! pathName=%{public}s", pathName.c_str());
|
||||
|
||||
std::shared_ptr<int> fdPtr(&fd, [](int *fd) { close(*fd); });
|
||||
OH_ImageSourceNative *imageSource = nullptr;
|
||||
Image_ErrorCode errorCode = OH_ImageSourceNative_CreateFromFd(*fdPtr.get(), &imageSource);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == Image_ErrorCode::IMAGE_SUCCESS, nullptr,
|
||||
"OH_ImageSourceNative_CreateFromFd fail! errorCode=%{public}d", errorCode);
|
||||
|
||||
std::shared_ptr<OH_ImageSourceNative> imageSourcePtr(imageSource, [](OH_ImageSourceNative *imageSource) {
|
||||
OH_ImageSourceNative_Release(imageSource);
|
||||
});
|
||||
|
||||
std::shared_ptr<OH_DecodingOptions> optionsPtr = CreateDecodingOptions();
|
||||
CHECK_AND_RETURN_RET_LOG(optionsPtr != nullptr, nullptr, "CreateDecodingOptions fail!");
|
||||
|
||||
OH_PixelmapNative *pixelmap = nullptr;
|
||||
errorCode = OH_ImageSourceNative_CreatePixelmap(imageSourcePtr.get(), optionsPtr.get(), &pixelmap);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == Image_ErrorCode::IMAGE_SUCCESS, nullptr,
|
||||
"OH_ImageSourceNative_CreatePixelmap fail! errorCode=%{public}d", errorCode);
|
||||
|
||||
std::shared_ptr<OH_PixelmapNative> pixelmapPtr(pixelmap, [](OH_PixelmapNative *pixelmap) {
|
||||
OH_PixelmapNative_Release(pixelmap);
|
||||
});
|
||||
|
||||
return pixelmapPtr;
|
||||
}
|
||||
|
||||
std::shared_ptr<OH_PackingOptions> CreatePackingOptions()
|
||||
{
|
||||
OH_PackingOptions *options = nullptr;
|
||||
Image_ErrorCode errorCode = OH_PackingOptions_Create(&options);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == Image_ErrorCode::IMAGE_SUCCESS, nullptr,
|
||||
"OH_PackingOptions_Create fail! errorCode=%{public}d", errorCode);
|
||||
|
||||
std::shared_ptr<OH_PackingOptions> optionsPtr(options, [](OH_PackingOptions *options) {
|
||||
OH_PackingOptions_Release(options);
|
||||
});
|
||||
|
||||
OH_PackingOptions_SetQuality(optionsPtr.get(), EXPECTED_ONE_HUNDRED);
|
||||
Image_MimeType format = { .data = const_cast<char *>(MIME_TYPE_JPEG), .size = strlen(MIME_TYPE_JPEG) };
|
||||
OH_PackingOptions_SetMimeType(optionsPtr.get(), &format);
|
||||
return optionsPtr;
|
||||
}
|
||||
|
||||
bool PixelMapHelper::Encode(OH_PixelmapNative *pixelmap, std::string &path)
|
||||
{
|
||||
OH_ImagePackerNative *imagePacker = nullptr;
|
||||
Image_ErrorCode errorCode = OH_ImagePackerNative_Create(&imagePacker);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == Image_ErrorCode::IMAGE_SUCCESS, false,
|
||||
"OH_ImagePackerNative_Create fail! errorCode=%{public}d", errorCode);
|
||||
|
||||
std::shared_ptr<OH_ImagePackerNative> imagePackerPtr(imagePacker, [](OH_ImagePackerNative *imagePacker) {
|
||||
OH_ImagePackerNative_Release(imagePacker);
|
||||
});
|
||||
|
||||
std::shared_ptr<OH_PackingOptions> optionsPtr = CreatePackingOptions();
|
||||
CHECK_AND_RETURN_RET_LOG(optionsPtr != nullptr, false, "CreatePackingOptions fail!");
|
||||
|
||||
int fd = open(path.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
|
||||
CHECK_AND_RETURN_RET_LOG(fd != -1, false, "Open path fail! path=%{public}s", path.c_str());
|
||||
errorCode = OH_ImagePackerNative_PackToFileFromPixelmap(imagePackerPtr.get(), optionsPtr.get(), pixelmap, fd);
|
||||
close(fd);
|
||||
CHECK_AND_RETURN_RET_LOG(errorCode == Image_ErrorCode::IMAGE_SUCCESS, false,
|
||||
"OH_ImagePackerNative_PackToFileFromPixelmap fail! errorCode=%{public}d", errorCode);
|
||||
|
||||
return true;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 IMAGEEFFECT_PIXELMAP_HELPER_H
|
||||
#define IMAGEEFFECT_PIXELMAP_HELPER_H
|
||||
|
||||
#include <multimedia/image_framework/pixelmap_native.h>
|
||||
#include <multimedia/image_framework/image_pixel_map_mdk.h>
|
||||
#include <memory>
|
||||
|
||||
#include "napi/native_api.h"
|
||||
|
||||
class PixelMapHelper {
|
||||
public:
|
||||
static std::shared_ptr<OH_PixelmapNative> Decode(std::string &pathName);
|
||||
static bool Encode(OH_PixelmapNative *pixelmap, std::string &pathName);
|
||||
|
||||
static std::shared_ptr<OH_PixelmapNative> ConvertPixelmap(NativePixelMap *nativePixelMap);
|
||||
static napi_value ConvertPixelmap(OH_PixelmapNative *pixelmapNative, napi_env env);
|
||||
};
|
||||
|
||||
#endif // IMAGEEFFECT_PIXELMAP_HELPER_H
|
@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
|
||||
export default class EntryAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
|
||||
}
|
||||
|
||||
onDestroy(): void {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage): void {
|
||||
// Main window is created, set main page for this ability
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageCreate');
|
||||
|
||||
windowStage.loadContent('pages/ImageEditPage', (err, data) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s', JSON.stringify(data) ?? '');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy(): void {
|
||||
// Main window is destroyed, release UI related resources
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground(): void {
|
||||
// Ability has brought to foreground
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');
|
||||
}
|
||||
|
||||
onBackground(): void {
|
||||
// Ability has back to background
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');
|
||||
}
|
||||
};
|
@ -0,0 +1,538 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 imageEffect from 'libentry.so'
|
||||
import image from '@ohos.multimedia.image';
|
||||
import { ImageUtils } from '../utils/ImageUtils';
|
||||
import { fileUri } from '@kit.CoreFileKit';
|
||||
import fs from '@ohos.file.fs';
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct ImageEditPage {
|
||||
private tag: string = '[Sample_ImageEdit]';
|
||||
settingBtn: Resource = $r('app.media.ic_public_settings');
|
||||
@Provide pixelMap: image.PixelMap | undefined = undefined;
|
||||
@Provide displayPixelMap: image.PixelMap | undefined = undefined;
|
||||
@State brightnessSetValue: number = 100;
|
||||
@State brightnessSelect: boolean = true;
|
||||
@State contrastSetValue: number = 0;
|
||||
@State contrastSelect: boolean = false;
|
||||
@State cropSetValue: number = 100;
|
||||
@State cropSelect: boolean = false;
|
||||
@State customSetValue: number = 0;
|
||||
@State customSelect: boolean = false;
|
||||
@State filterOptions: Array<Array<string | number>> = [];
|
||||
@State filterInfo: string = "";
|
||||
|
||||
aboutToAppear(): void {
|
||||
console.info(`${this.tag} aboutToAppear called`);
|
||||
ImageUtils.getInstance().getPixelMap($r('app.media.ic_1080x1920')).then(pixelMap => {
|
||||
this.pixelMap = pixelMap;
|
||||
})
|
||||
ImageUtils.getInstance().getPixelMap($r('app.media.ic_1080x1920')).then(pixelMap => {
|
||||
this.displayPixelMap = pixelMap;
|
||||
})
|
||||
console.info(`${this.tag} aboutToAppear done`);
|
||||
}
|
||||
|
||||
aboutToDisappear(): void {
|
||||
console.info(`${this.tag} aboutToDisappear called`);
|
||||
console.info(`${this.tag} aboutToDisappear done`);
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Row() {
|
||||
Row() {
|
||||
Text($r('app.string.image_edit'))
|
||||
.fontColor(Color.White)
|
||||
.fontSize('app.float.title_font_size')
|
||||
.margin({ left: $r('app.float.home_page_title_margin') })
|
||||
}
|
||||
|
||||
Blank()
|
||||
|
||||
Row({ space: 0 }) {
|
||||
Button() {
|
||||
Image(this.settingBtn)
|
||||
.width($r('app.float.title_image_width'))
|
||||
.height($r('app.float.title_image_height'))
|
||||
.id('btn_setting')
|
||||
}
|
||||
.height('100%')
|
||||
.type(ButtonType.Normal)
|
||||
.aspectRatio(1)
|
||||
.backgroundColor(Color.Transparent)
|
||||
.onClick(() => {
|
||||
if (this.dialogController != undefined) {
|
||||
console.info(`${this.tag} to open setting dialog`);
|
||||
this.dialogController.open();
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height($r('app.float.home_page_title_height'))
|
||||
.margin({ top: $r('app.float.home_page_title_margin') })
|
||||
|
||||
Column() {
|
||||
Image(this.displayPixelMap)
|
||||
.objectFit(ImageFit.None)
|
||||
}
|
||||
.clip(true)
|
||||
.width('100%')
|
||||
.height('85%')
|
||||
|
||||
Column() {
|
||||
Row() {
|
||||
Button("Reset").id("btn_reset").onClick(() => {
|
||||
this.pixelInit();
|
||||
}).width(100).margin({ left: 3, right: 3, top: 3, bottom: 6 })
|
||||
|
||||
Button("Apply").id("btn_apply").onClick(() => {
|
||||
this.doApply();
|
||||
}).width(100).margin({ left: 3, right: 3, top: 3, bottom: 6 })
|
||||
}
|
||||
.justifyContent(FlexAlign.Center)
|
||||
}
|
||||
.align(Alignment.End)
|
||||
.width('100%')
|
||||
.height('6%')
|
||||
.margin({ top: $r('app.float.home_page_title_margin') })
|
||||
.backgroundColor(Color.Black)
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
.backgroundColor(Color.Black)
|
||||
}
|
||||
|
||||
private async doSavePixel(): Promise<void> {
|
||||
let pixelMap = await ImageUtils.getInstance().getPixelMap($r('app.media.ic_1080x1920'));
|
||||
const imagePackerApi = image.createImagePacker();
|
||||
const packOption: image.PackingOption = {
|
||||
format: 'image/jpeg',
|
||||
quality: 100
|
||||
};
|
||||
let filePath = getContext().filesDir + "/test.jpg";
|
||||
let uri = fileUri.getUriFromPath(filePath);
|
||||
let imageData = await imagePackerApi.packing(pixelMap, packOption);
|
||||
let file = fs.openSync(uri, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE);
|
||||
let writeLen = fs.writeSync(file.fd, imageData);
|
||||
fs.closeSync(file);
|
||||
console.info(`write data to file succeed and size is ${writeLen}`);
|
||||
}
|
||||
|
||||
private confirmInfo() {
|
||||
this.filterOptions = [];
|
||||
if (this.brightnessSelect) {
|
||||
let brightnessArray: (string | number)[] = [];
|
||||
brightnessArray.push("Brightness", this.brightnessSetValue);
|
||||
this.filterOptions.push(brightnessArray);
|
||||
}
|
||||
if (this.contrastSelect) {
|
||||
let contrastArray: (string | number)[] = [];
|
||||
contrastArray.push("Contrast", this.contrastSetValue);
|
||||
this.filterOptions.push(contrastArray);
|
||||
}
|
||||
if (this.cropSelect) {
|
||||
let cropArray: (string | number)[] = [];
|
||||
cropArray.push("Crop", this.cropSetValue);
|
||||
this.filterOptions.push(cropArray);
|
||||
}
|
||||
if (this.customSelect) {
|
||||
let customArray: (string | number)[] = [];
|
||||
customArray.push("CustomBrightness", this.customSetValue);
|
||||
this.filterOptions.push(customArray);
|
||||
}
|
||||
}
|
||||
|
||||
private async doApply(): Promise<void> {
|
||||
this.confirmInfo();
|
||||
if (this.brightnessSelect || this.contrastSelect || this.cropSelect || this.customSelect) {
|
||||
await this.doSavePixel();
|
||||
let filePath = getContext().filesDir + "/test.jpg";
|
||||
imageEffect.apply(filePath, [...this.filterOptions]);
|
||||
this.displayPixelMap = await ImageUtils.getInstance().getPixelMapByFilePath(filePath);
|
||||
}
|
||||
}
|
||||
|
||||
private async pixelInit(): Promise<void> {
|
||||
this.displayPixelMap?.release();
|
||||
this.displayPixelMap = await ImageUtils.getInstance().getPixelMap($r('app.media.ic_1080x1920'))
|
||||
}
|
||||
|
||||
dialogController: CustomDialogController = new CustomDialogController({
|
||||
builder: CustomDialogExample({
|
||||
cancel: this.onCancel,
|
||||
confirm: this.onAccept,
|
||||
filterOptions: $filterOptions,
|
||||
brightnessSetValue: $brightnessSetValue,
|
||||
brightnessSelect: $brightnessSelect,
|
||||
contrastSetValue: $contrastSetValue,
|
||||
contrastSelect: $contrastSelect,
|
||||
cropSetValue: $cropSetValue,
|
||||
cropSelect: $cropSelect,
|
||||
customSetValue: $customSetValue,
|
||||
customSelect: $customSelect,
|
||||
filterInfo: $filterInfo,
|
||||
}),
|
||||
cancel: this.existApp,
|
||||
autoCancel: true,
|
||||
})
|
||||
|
||||
onCancel() {
|
||||
console.info(`Callback when the cancel button is clicked`);
|
||||
}
|
||||
|
||||
onAccept() {
|
||||
console.info(`Callback when the confirm button is clicked`);
|
||||
}
|
||||
|
||||
existApp() {
|
||||
console.info(`click the callback in the blank area`);
|
||||
}
|
||||
}
|
||||
|
||||
@CustomDialog
|
||||
struct CustomDialogExample {
|
||||
@Link brightnessSetValue: number
|
||||
@Link brightnessSelect: boolean
|
||||
@Link contrastSetValue: number
|
||||
@Link contrastSelect: boolean
|
||||
@Link cropSetValue: number
|
||||
@Link cropSelect: boolean
|
||||
@Link customSetValue: number
|
||||
@Link customSelect: boolean
|
||||
@Link filterOptions: Array<Array<string | number>>
|
||||
@Link filterInfo: string;
|
||||
controller: CustomDialogController;
|
||||
cancel: () => void = () => {
|
||||
}
|
||||
confirm: () => void = () => {
|
||||
}
|
||||
@State formatList: Array<String> = ["Format:default", "Format:rgba_8888", "Format:nv21", "Format:nv12"]
|
||||
@State handlePopup: boolean = false
|
||||
|
||||
@Builder
|
||||
FilterInfoMenu() {
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Start, justifyContent: FlexAlign.Center }) {
|
||||
Flex({ direction: FlexDirection.Row, justifyContent: FlexAlign.Start }) {
|
||||
Text(this.filterInfo).fontSize(16)
|
||||
}
|
||||
}
|
||||
.width('60%').height('15%')
|
||||
.opacity(0.8)
|
||||
.id("filter_info_menu")
|
||||
}
|
||||
|
||||
private async doLookFilterInfo(name: String): Promise<void> {
|
||||
this.filterInfo = imageEffect.lookupFilterInfo(name);
|
||||
}
|
||||
|
||||
build() {
|
||||
Column() {
|
||||
Column() {
|
||||
Divider().height(2).color(0xcccccc)
|
||||
Column() {
|
||||
Text('Filter')
|
||||
.width('100%')
|
||||
.fontSize(18)
|
||||
.margin({ bottom: 10 })
|
||||
|
||||
Row() {
|
||||
Column() {
|
||||
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
|
||||
Checkbox({ name: 'brightnessCheckbox', group: 'filterCheckboxGroup' })
|
||||
.selectedColor(0x39a2db)
|
||||
.select(this.brightnessSelect)
|
||||
.onChange((value: boolean) => {
|
||||
this.brightnessSelect = value;
|
||||
})
|
||||
.width(10)
|
||||
.height(14)
|
||||
.id("checkbox_brightness")
|
||||
Text('Brightness').fontSize(10).width('18%')
|
||||
Slider({
|
||||
value: this.brightnessSetValue,
|
||||
min: -100,
|
||||
max: 100,
|
||||
style: SliderStyle.OutSet
|
||||
})
|
||||
.showTips(true, this.brightnessSetValue.toFixed())
|
||||
.onChange((value: number, mode: SliderChangeMode) => {
|
||||
this.brightnessSetValue = value
|
||||
console.info('value:' + value + 'mode:' + mode.toString())
|
||||
})
|
||||
.width('60%')
|
||||
.id("slider_brightness")
|
||||
// toFixed(0)将滑动条返回值处理为整数精度
|
||||
Column() {
|
||||
Text(this.brightnessSetValue.toFixed(0)).fontSize(12)
|
||||
}.width('8%')
|
||||
|
||||
Column() {
|
||||
Image($r('app.media.ic_public_search'))
|
||||
.width('5%')
|
||||
.height('3.7%')
|
||||
}.bindMenu(this.FilterInfoMenu, {
|
||||
onAppear: () => {
|
||||
this.doLookFilterInfo("Brightness");
|
||||
},
|
||||
onDisappear: () => {
|
||||
this.filterInfo = "";
|
||||
}
|
||||
})
|
||||
.margin({ left: 2 })
|
||||
.id("btn_search_brightness")
|
||||
}
|
||||
|
||||
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
|
||||
Checkbox({ name: 'contrastCheckbox', group: 'filterCheckboxGroup' })
|
||||
.selectedColor(0x39a2db)
|
||||
.select(this.contrastSelect)
|
||||
.onChange((value: boolean) => {
|
||||
this.contrastSelect = value;
|
||||
})
|
||||
.width(10)
|
||||
.height(14)
|
||||
.id("checkbox_contrast")
|
||||
Text('Contrast').fontSize(10).width('18%')
|
||||
Slider({
|
||||
value: this.contrastSetValue,
|
||||
min: -100,
|
||||
max: 100,
|
||||
style: SliderStyle.OutSet
|
||||
})
|
||||
.showTips(true, this.contrastSetValue.toFixed())
|
||||
.onChange((value: number, mode: SliderChangeMode) => {
|
||||
this.contrastSetValue = value
|
||||
console.info('value:' + value + 'mode:' + mode.toString())
|
||||
})
|
||||
.width('60%')
|
||||
.id("slider_contrast")
|
||||
// toFixed(0)将滑动条返回值处理为整数精度
|
||||
Column() {
|
||||
Text(this.contrastSetValue.toFixed(0)).fontSize(12)
|
||||
}.width('8%')
|
||||
|
||||
Column() {
|
||||
Image($r('app.media.ic_public_search'))
|
||||
.width('5%')
|
||||
.height('3.7%')
|
||||
}.bindMenu(this.FilterInfoMenu, {
|
||||
onAppear: () => {
|
||||
this.doLookFilterInfo("Contrast");
|
||||
},
|
||||
onDisappear: () => {
|
||||
this.filterInfo = "";
|
||||
}
|
||||
})
|
||||
.margin({ left: 2 })
|
||||
.id("btn_search_contrast")
|
||||
}
|
||||
|
||||
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
|
||||
Checkbox({ name: 'cropCheckbox', group: 'filterCheckboxGroup' })
|
||||
.selectedColor(0x39a2db)
|
||||
.select(this.cropSelect)
|
||||
.onChange((value: boolean) => {
|
||||
this.cropSelect = value;
|
||||
})
|
||||
.width(10)
|
||||
.height(14)
|
||||
.id("checkbox_crop")
|
||||
Text('Crop').fontSize(10).width('18%')
|
||||
Slider({
|
||||
value: this.cropSetValue,
|
||||
min: 1,
|
||||
max: 100,
|
||||
style: SliderStyle.OutSet
|
||||
})
|
||||
.showTips(true, this.cropSetValue.toFixed())
|
||||
.onChange((value: number, mode: SliderChangeMode) => {
|
||||
this.cropSetValue = value
|
||||
console.info('value:' + value + 'mode:' + mode.toString())
|
||||
})
|
||||
.width('60%')
|
||||
.id("slider_crop")
|
||||
// toFixed(0)将滑动条返回值处理为整数精度
|
||||
Column() {
|
||||
Text(this.cropSetValue.toFixed(0)).fontSize(12)
|
||||
}.width('8%')
|
||||
|
||||
Column() {
|
||||
Image($r('app.media.ic_public_search'))
|
||||
.width('5%')
|
||||
.height('3.7%')
|
||||
}.bindMenu(this.FilterInfoMenu, {
|
||||
onAppear: () => {
|
||||
this.doLookFilterInfo("Crop");
|
||||
},
|
||||
onDisappear: () => {
|
||||
this.filterInfo = "";
|
||||
}
|
||||
})
|
||||
.margin({ left: 2 })
|
||||
.id("btn_search_crop")
|
||||
}
|
||||
|
||||
Flex({ justifyContent: FlexAlign.Start, alignItems: ItemAlign.Center }) {
|
||||
Checkbox({ name: 'customCheckbox', group: 'filterCheckboxGroup' })
|
||||
.selectedColor(0x39a2db)
|
||||
.select(this.customSelect)
|
||||
.onChange((value: boolean) => {
|
||||
this.customSelect = value;
|
||||
})
|
||||
.width(10)
|
||||
.height(14)
|
||||
.id("checkbox_custom")
|
||||
Text('Custom').fontSize(10).width('18%')
|
||||
Slider({
|
||||
value: this.customSetValue,
|
||||
min: -100,
|
||||
max: 100,
|
||||
style: SliderStyle.OutSet
|
||||
})
|
||||
.showTips(true, this.customSetValue.toFixed())
|
||||
.onChange((value: number, mode: SliderChangeMode) => {
|
||||
this.customSetValue = value
|
||||
console.info('value:' + value + 'mode:' + mode.toString())
|
||||
})
|
||||
.width('60%')
|
||||
.id("slider_custom")
|
||||
// toFixed(0)将滑动条返回值处理为整数精度
|
||||
Column() {
|
||||
Text(this.customSetValue.toFixed(0)).fontSize(12)
|
||||
}.width('8%')
|
||||
|
||||
Column() {
|
||||
Image($r('app.media.ic_public_search'))
|
||||
.width('5%')
|
||||
.height('3.7%')
|
||||
}.bindMenu(this.FilterInfoMenu, {
|
||||
onAppear: () => {
|
||||
this.doLookFilterInfo("CustomBrightness");
|
||||
},
|
||||
onDisappear: () => {
|
||||
this.filterInfo = "";
|
||||
}
|
||||
})
|
||||
.margin({ left: 2 })
|
||||
.id("btn_search_custom")
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
}
|
||||
}.margin({ bottom: 10 })
|
||||
|
||||
Column() {
|
||||
Divider().height(2).color(0xCCCCCC);
|
||||
Column() {
|
||||
Text($r('app.string.look_up'))
|
||||
.width('100%')
|
||||
.fontSize(18)
|
||||
.margin({ bottom: 10 })
|
||||
Row() {
|
||||
Column() {
|
||||
Text($r('app.string.btn_search'))
|
||||
.width('15%')
|
||||
.fontSize(20)
|
||||
.margin({ left: '35%' })
|
||||
}
|
||||
|
||||
Column() {
|
||||
Image($r('app.media.ic_public_arrow_right'))
|
||||
.fillColor(Color.Black)
|
||||
.width('10%')
|
||||
.height('4%')
|
||||
}
|
||||
}
|
||||
.id("btn_search")
|
||||
.width('100%')
|
||||
.justifyContent(FlexAlign.Start)
|
||||
.bindMenu(this.LookupCategoryMenuBuilder)
|
||||
}
|
||||
}.margin({ bottom: 10 })
|
||||
|
||||
Divider().height(2).color(0xCCCCCC)
|
||||
|
||||
Flex({ justifyContent: FlexAlign.SpaceAround }) {
|
||||
Button($r('app.string.btn_cancel'))
|
||||
.onClick(() => {
|
||||
this.controller.close()
|
||||
this.cancel();
|
||||
}).backgroundColor(0xffffff)
|
||||
.fontColor(Color.Black)
|
||||
.id("btn_dialog_cancel")
|
||||
Button($r('app.string.btn_confirm'))
|
||||
.onClick(() => {
|
||||
|
||||
this.controller.close()
|
||||
this.confirm()
|
||||
}).backgroundColor(0xffffff)
|
||||
.fontColor(Color.Red)
|
||||
.id("btn_dialog_confirm")
|
||||
}
|
||||
}.margin(24)
|
||||
}
|
||||
|
||||
@Builder
|
||||
LookupCategoryMenuBuilder() {
|
||||
Menu() {
|
||||
MenuItem({ content: "Format" }).bindMenu(this.FormatMenuBuilder())
|
||||
}.id("menu_category")
|
||||
}
|
||||
|
||||
@Builder
|
||||
FormatMenuBuilder() {
|
||||
Menu() {
|
||||
ForEach(this.formatList, (item: string, index) => {
|
||||
LookupFilterMenuItem({ item: item })
|
||||
.id("menu_format")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Component
|
||||
struct LookupFilterMenuItem {
|
||||
@State item: string = "";
|
||||
@State handlePopup: boolean = false
|
||||
|
||||
build() {
|
||||
MenuItem({ content: this.item })
|
||||
.bindPopup(this.handlePopup, {
|
||||
message: 'Filters:\n' + imageEffect.lookupFilters(this.item),
|
||||
messageOptions: {
|
||||
font: {
|
||||
size: '14vp',
|
||||
style: FontStyle.Italic
|
||||
},
|
||||
},
|
||||
placementOnTop: false,
|
||||
onStateChange: (e) => {
|
||||
console.log(e.isVisible.toString())
|
||||
if (!e.isVisible) {
|
||||
this.handlePopup = false
|
||||
}
|
||||
}
|
||||
})
|
||||
.onClick(() => {
|
||||
this.handlePopup = !this.handlePopup
|
||||
})
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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';
|
||||
|
||||
export class ImageUtils {
|
||||
private static instance: ImageUtils;
|
||||
|
||||
public static getInstance(): ImageUtils {
|
||||
if (!ImageUtils.instance) {
|
||||
ImageUtils.instance = new ImageUtils();
|
||||
}
|
||||
return ImageUtils.instance;
|
||||
}
|
||||
|
||||
async getPixelMap(resource: Resource): Promise<image.PixelMap> {
|
||||
const resourceStr = getContext(this).resourceManager;
|
||||
let imageBuffer = await resourceStr.getMediaContent(resource);
|
||||
const pixelMap = await image.createImageSource(imageBuffer.buffer as object as ArrayBuffer).createPixelMap();
|
||||
return pixelMap;
|
||||
}
|
||||
|
||||
async getPixelMapByFilePath(filePath: string): Promise<image.PixelMap> {
|
||||
const imageSource: image.ImageSource = image.createImageSource(filePath)
|
||||
const pixelMap = await imageSource.createPixelMap();
|
||||
return pixelMap;
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Hunan OpenValley Digital Industry Development Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
{
|
||||
"module": {
|
||||
"name": "entry",
|
||||
"type": "entry",
|
||||
"description": "$string:module_desc",
|
||||
"mainElement": "EntryAbility",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:main_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "EntryAbility",
|
||||
"srcEntry": "./ets/entryability/EntryAbility.ets",
|
||||
"description": "$string:EntryAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:EntryAbility_label",
|
||||
"startWindowIcon": "$media:startIcon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"exported": true,
|
||||
"skills": [
|
||||
{
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
],
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
{
|
||||
"float": [
|
||||
{
|
||||
"name": "title_font_size",
|
||||
"value": "20fp"
|
||||
},
|
||||
{
|
||||
"name": "home_page_title_margin",
|
||||
"value": "10"
|
||||
},
|
||||
{
|
||||
"name": "home_page_title_height",
|
||||
"value": "38"
|
||||
},
|
||||
{
|
||||
"name": "title_image_width",
|
||||
"value": "24vp"
|
||||
},
|
||||
{
|
||||
"name": "title_image_height",
|
||||
"value": "24vp"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "ImageEffectSample"
|
||||
},
|
||||
{
|
||||
"name": "image_edit",
|
||||
"value": "imageEdit"
|
||||
},
|
||||
{
|
||||
"name": "btn_search",
|
||||
"value": "Search"
|
||||
},
|
||||
{
|
||||
"name": "look_up",
|
||||
"value": "LookUp"
|
||||
},
|
||||
{
|
||||
"name": "btn_confirm",
|
||||
"value": "btn_confirm"
|
||||
},
|
||||
{
|
||||
"name": "btn_cancel",
|
||||
"value": "Cancel"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 940 KiB |
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 12 24" version="1.1">
|
||||
<!-- Generator: Sketch 63.1 (92452) - https://sketch.com -->
|
||||
<title>Public/ic_public_arrow_right</title>
|
||||
<desc>Created with Sketch.</desc>
|
||||
<defs>
|
||||
<path d="M4.2482689,5.78255501 L4.28033009,5.81281566 L9.23007755,10.7625631 C9.8992572,11.4317428 9.91319844,12.5080354 9.27190128,13.1941781 L9.23007755,13.2374369 L4.28033009,18.1871843 C4.15145707,18.3160574 3.98735263,18.3882262 3.81902041,18.403691 L3.7730301,18.4065028 L3.7269699,18.4065028 C3.54277571,18.4008792 3.36025866,18.3277731 3.21966991,18.1871843 C2.93723717,17.9047516 2.92715028,17.4531048 3.18940926,17.1585854 L3.21966991,17.1265242 L7.81586399,12.5303301 C8.09829674,12.2478973 8.10838362,11.7962506 7.84612464,11.5017311 L7.81586399,11.4696699 L3.21966991,6.87347584 C2.9267767,6.58058262 2.9267767,6.10570888 3.21966991,5.81281566 C3.36088629,5.67159929 3.54440617,5.59846938 3.72943689,5.59342594 L3.77570243,5.59358355 C3.94528507,5.59936249 4.11328081,5.66235298 4.2482689,5.78255501 Z" id="_path-1"/>
|
||||
</defs>
|
||||
<g id="_Public/ic_public_arrow_right" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<mask id="_mask-2" fill="white">
|
||||
<use xlink:href="#_path-1"/>
|
||||
</mask>
|
||||
<use id="_路径" fill="#000000" fill-rule="nonzero" xlink:href="#_path-1"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24" version="1.1">
|
||||
<title>Public/ic_public_search_filled</title>
|
||||
<defs>
|
||||
<path d="M17.6179267,16.3277876 L20.8132621,19.5240485 C21.2037864,19.9145728 21.2037864,20.5477378 20.8132621,20.9382621 C20.4227378,21.3287864 19.7895728,21.3287864 19.3990485,20.9382621 L16.189979,17.729164 C16.7142906,17.3140255 17.1931651,16.8440081 17.6179267,16.3277876 Z M10.375,2 C15.0003848,2 18.75,5.74961522 18.75,10.375 C18.75,12.5107968 17.9505141,14.4598636 16.6344856,15.9392571 L16.8468572,15.6909887 C16.7564149,15.8009681 16.6632239,15.9086017 16.5673893,16.0137845 C16.4969337,16.0911028 16.4254201,16.1667191 16.3525335,16.240983 C16.338412,16.2553719 16.3241207,16.2698289 16.3097773,16.2842339 C16.2403031,16.3540107 16.1694244,16.4227398 16.0973523,16.4902097 C16.0802283,16.506238 16.063454,16.5218113 16.046616,16.5373165 C15.9709789,16.6069739 15.8937108,16.6755519 15.8151858,16.7427027 C15.8023252,16.7537003 15.7894477,16.7646456 15.7765366,16.7755526 L15.7332842,16.8118433 C14.2811297,18.021995 12.4130822,18.75 10.375,18.75 C5.74961522,18.75 2,15.0003848 2,10.375 C2,5.74961522 5.74961522,2 10.375,2 Z M10.375,4 C6.85418472,4 4,6.85418472 4,10.375 C4,13.8958153 6.85418472,16.75 10.375,16.75 C13.8958153,16.75 16.75,13.8958153 16.75,10.375 C16.75,6.85418472 13.8958153,4 10.375,4 Z" id="__path-1"/>
|
||||
</defs>
|
||||
<g id="__Public/ic_public_search_filled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<mask id="__mask-2" fill="white">
|
||||
<use xlink:href="#__path-1"/>
|
||||
</mask>
|
||||
<use id="__形状结合" fill="#000000" fill-rule="nonzero" xlink:href="#__path-1"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.8 KiB |
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24" version="1.1">
|
||||
<title>Public/ic_public_settings</title>
|
||||
<defs>
|
||||
<path d="M13.4894964,1.25 C14.1901033,1.25 14.8231865,1.66785112 15.0986042,2.31205231 L15.0986042,2.31205231 L15.92125,4.23625 L16.77175,4.72725 L18.8556101,4.47607817 C19.5285537,4.39491431 20.1856012,4.70961774 20.5451004,5.27951678 L20.5451004,5.27951678 L20.5800481,5.33735213 L22.0680131,7.91013134 C22.4194652,8.51781272 22.3737758,9.27669833 21.9519545,9.83782407 L21.9519545,9.83782407 L20.69375,11.51125 L20.69375,12.4885 L21.9519801,14.16219 C22.3597241,14.70461 22.4160026,15.4318142 22.1018413,16.0285992 L22.1018413,16.0285992 L22.0680196,16.0898574 L20.5800481,18.6626479 C20.2293867,19.2689622 19.5509852,19.6077912 18.8556101,19.5239218 L18.8556101,19.5239218 L16.77175,19.2725 L15.92125,19.7635 L15.0986042,21.6879477 C14.832071,22.3113682 14.2305752,22.7228063 13.5570765,22.748702 L13.5570765,22.748702 L13.4894964,22.75 L10.5105451,22.75 C9.80990141,22.75 9.17679241,22.3321056 8.90139751,21.6878548 L8.90139751,21.6878548 L8.0785,19.7635 L7.228,19.2725 L5.14438986,19.5239218 C4.47144629,19.6050857 3.81439883,19.2903823 3.45489956,18.7204832 L3.45489956,18.7204832 L3.41995189,18.6626479 L1.9319804,16.0898574 C1.58053408,15.482186 1.62621577,14.7233142 2.04801988,14.16219 L2.04801988,14.16219 L3.306,12.4885 L3.306,11.51125 L2.04804545,9.83782407 C1.64028496,9.29540252 1.58399872,8.56818536 1.89816473,7.97139057 L1.89816473,7.97139057 L1.93198692,7.91013134 L3.41995189,5.33735213 C3.77061333,4.73103782 4.44901483,4.39220884 5.14438986,4.47607817 L5.14438986,4.47607817 L7.228,4.72725 L8.0785,4.23625 L8.90139751,2.31214525 C9.1679087,1.68867667 9.7694279,1.27719647 10.4429614,1.25129813 L10.4429614,1.25129813 L10.5105451,1.25 Z M13.4894964,2.75 L10.5105451,2.75 C10.4104531,2.75 10.320009,2.8096992 10.2806668,2.90173504 L10.2806668,2.90173504 L9.42547944,4.90233575 C9.31921851,5.1509195 9.13523096,5.35835416 8.90110986,5.49353025 L8.90110986,5.49353025 L7.90597116,6.06810022 C7.67169142,6.20336791 7.39985123,6.25898058 7.13127161,6.22658714 L7.13127161,6.22658714 L4.96477622,5.96528566 C4.86543693,5.95330433 4.76852243,6.00170847 4.71842794,6.0883248 L4.71842794,6.0883248 L3.23046296,8.66110401 C3.18025552,8.74791564 3.18678258,8.85632787 3.24704275,8.93648869 L3.24704275,8.93648869 L4.55532037,10.6768191 C4.71812619,10.8933908 4.80615731,11.1569971 4.80615595,11.4279382 L4.80615595,11.4279382 L4.80615019,12.5719965 C4.80614882,12.8429255 4.71812287,13.1065199 4.55532821,13.3230849 L4.55532821,13.3230849 L3.24703351,15.0635037 C3.18677578,15.1436643 3.18024983,15.2520745 3.23045644,15.3388847 L3.23045644,15.3388847 L4.71842794,17.9116752 C4.76852243,17.9982915 4.86543693,18.0466957 4.96477622,18.0347143 L4.96477622,18.0347143 L7.13127161,17.7734129 C7.39985123,17.7410194 7.67169142,17.7966321 7.90597116,17.9318998 L7.90597116,17.9318998 L8.90110986,18.5064697 C9.13523096,18.6416458 9.31921851,18.8490805 9.42547944,19.0976643 L9.42547944,19.0976643 L10.2806668,21.098265 C10.320009,21.1903008 10.4104531,21.25 10.5105451,21.25 L10.5105451,21.25 L13.4894964,21.25 C13.5895831,21.25 13.6800236,21.190307 13.7193689,21.0982782 L13.7193689,21.0982782 L14.5747715,19.097494 C14.6810343,18.8489455 14.8650036,18.6415401 15.0990951,18.506376 L15.0990951,18.506376 L16.0940158,17.9319104 C16.3282993,17.7966355 16.6001464,17.7410191 16.8687329,17.7734134 L16.8687329,17.7734134 L19.0352238,18.0347143 C19.1345631,18.0466957 19.2314776,17.9982915 19.2815721,17.9116752 L19.2815721,17.9116752 L20.7695436,15.3388847 C20.8197502,15.2520745 20.8132242,15.1436643 20.7529665,15.0635037 L20.7529665,15.0635037 L19.4446718,13.3230849 C19.2818771,13.1065199 19.1938512,12.8429255 19.1938498,12.5719965 L19.1938498,12.5719965 L19.1938441,11.4279382 C19.1938427,11.1569971 19.2818738,10.8933908 19.4446796,10.6768191 L19.4446796,10.6768191 L20.7529572,8.93648869 C20.8132174,8.85632787 20.8197445,8.74791564 20.769537,8.66110401 L20.769537,8.66110401 L19.2815721,6.0883248 C19.2314776,6.00170847 19.1345631,5.95330433 19.0352238,5.96528566 L19.0352238,5.96528566 L16.8687329,6.2265866 C16.6001464,6.25898087 16.3282993,6.2033645 16.0940158,6.06808955 L16.0940158,6.06808955 L15.0990951,5.49362397 C14.8650036,5.3584599 14.6810343,5.15105452 14.5747715,4.90250599 L14.5747715,4.90250599 L13.7193689,2.90172176 C13.6800236,2.80969302 13.5895831,2.75 13.4894964,2.75 L13.4894964,2.75 Z M12,7.5 C14.4852814,7.5 16.5,9.51471863 16.5,12 C16.5,14.4852814 14.4852814,16.5 12,16.5 C9.51471863,16.5 7.5,14.4852814 7.5,12 C7.5,9.51471863 9.51471863,7.5 12,7.5 Z M12,9 C10.3431458,9 9,10.3431458 9,12 C9,13.6568542 10.3431458,15 12,15 C13.6568542,15 15,13.6568542 15,12 C15,10.3431458 13.6568542,9 12,9 Z" id="_path-1"/>
|
||||
</defs>
|
||||
<g id="_Public/ic_public_settings" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<mask id="_mask-2" fill="white">
|
||||
<use xlink:href="#_path-1"/>
|
||||
</mask>
|
||||
<use id="_形状结合" fill="#FFFFFF" fill-rule="nonzero" xlink:href="#_path-1"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.1 KiB |
After Width: | Height: | Size: 2.0 KiB |
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"pages/ImageEditPage"
|
||||
]
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "module description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "ImageEffect"
|
||||
},
|
||||
{
|
||||
"name": "btn_search",
|
||||
"value": "Search"
|
||||
},
|
||||
{
|
||||
"name": "look_up",
|
||||
"value": "LookUp"
|
||||
},
|
||||
{
|
||||
"name": "btn_confirm",
|
||||
"value": "Confirm"
|
||||
},
|
||||
{
|
||||
"name": "btn_cancel",
|
||||
"value": "Cancel"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_desc",
|
||||
"value": "模块描述"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_desc",
|
||||
"value": "description"
|
||||
},
|
||||
{
|
||||
"name": "EntryAbility_label",
|
||||
"value": "ImageEffect"
|
||||
},
|
||||
{
|
||||
"name": "btn_search",
|
||||
"value": "查询"
|
||||
},
|
||||
{
|
||||
"name": "look_up",
|
||||
"value": "LookUp"
|
||||
},
|
||||
{
|
||||
"name": "btn_confirm",
|
||||
"value": "确认"
|
||||
},
|
||||
{
|
||||
"name": "btn_cancel",
|
||||
"value": "取消"
|
||||
}
|
||||
]
|
||||
}
|
26
code/BasicFeature/Media/ImageEffect/entry/src/main/types/libentry/index.d.ts
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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';
|
||||
|
||||
declare namespace ImageEffect {
|
||||
const apply: (srcPixelMap: image.PixelMap, filterOptions: Array<Array<String|number>>) => void;
|
||||
|
||||
const lookupFilterInfo: (name: String) => string;
|
||||
|
||||
const lookupFilters: (key: String) => string;
|
||||
}
|
||||
|
||||
export default ImageEffect;
|
@ -0,0 +1,6 @@
|
||||
{
|
||||
"name": "libentry.so",
|
||||
"types": "./index.d.ts",
|
||||
"version": "",
|
||||
"description": "Please describe the basic information."
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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<string, Object> = {
|
||||
'add': (a: number, b: number) => {
|
||||
return a + b;
|
||||
},
|
||||
};
|
||||
|
||||
export default NativeMock;
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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"
|
||||
}
|
||||
}
|
@ -0,0 +1,346 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 '@ohos.hilog';
|
||||
import { describe, it } from '@ohos/hypium';
|
||||
import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||
import { Driver, ON } from "@ohos.UiTest";
|
||||
import { getString } from '../utils/ResourceUtil';
|
||||
|
||||
const TAG: string = '[Sample_ImageEffect]';
|
||||
const DOMAIN: number = 0xF811;
|
||||
const BUNDLE: string = 'ImageEffect';
|
||||
|
||||
async function openDialog() {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickSettingBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
let btSetting: string = getString($r('app.string.btn_setting'));
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'lsq:' + btSetting);
|
||||
await driver.assertComponentExist(ON.id(btSetting));
|
||||
let setting = await driver.findComponent(ON.id(btSetting));
|
||||
await setting.click();
|
||||
await driver.delayMs(1000);
|
||||
let confirm: string = getString($r('app.string.btn_dialog_confirm'));
|
||||
await driver.assertComponentExist(ON.id(confirm));
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickSettingBtn_001 end');
|
||||
}
|
||||
|
||||
async function confirmDialog() {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickConfirmBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
let btnDialogConfirm: string = getString($r('app.string.btn_dialog_confirm'));
|
||||
await driver.assertComponentExist(ON.id(btnDialogConfirm));
|
||||
let dialogConfirm = await driver.findComponent(ON.id(btnDialogConfirm));
|
||||
await dialogConfirm.click();
|
||||
await driver.delayMs(1000);
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickConfirmBtn_001 end');
|
||||
}
|
||||
|
||||
async function apply() {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickApplyBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
let btnApply: string = getString($r('app.string.btn_apply'));
|
||||
await driver.assertComponentExist(ON.id(btnApply));
|
||||
let apply = await driver.findComponent(ON.id(btnApply));
|
||||
await apply.click();
|
||||
await driver.delayMs(1000);
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickApplyBtn_001 end');
|
||||
}
|
||||
|
||||
export default function abilityTest() {
|
||||
describe('ActsAbilityTest', () => {
|
||||
/**
|
||||
* @tc.number StartAbility_001
|
||||
* @tc.name StartAbility_001
|
||||
* @tc.desc 启动Ability
|
||||
*/
|
||||
it('StartAbility_001', 0, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 begin');
|
||||
let abilityDelegatorRegistry = AbilityDelegatorRegistry.getAbilityDelegator();
|
||||
await abilityDelegatorRegistry.executeShellCommand('aa start -a EntryAbility -b com.samples.ImageEffect');
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'StartAbility_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number ClickDialogConfirmBtn_001
|
||||
* @tc.name ClickDialogConfirmBtn_001
|
||||
* @tc.desc 点击dialog取消按钮,关闭参数页面
|
||||
*/
|
||||
it('ClickDialogConfirmBtn_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickDialogConfirmBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let btnCancel: string = getString($r('app.string.btn_dialog_cancel'));
|
||||
await driver.assertComponentExist(ON.id(btnCancel));
|
||||
let cancel = await driver.findComponent(ON.id(btnCancel));
|
||||
await cancel.click();
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickDialogConfirmBtn_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number AdjustBrightness_001
|
||||
* @tc.name AdjustBrightness_001
|
||||
* @tc.desc Brightness滤镜
|
||||
*/
|
||||
it('AdjustBrightness_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustBrightness_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let checkboxBrightnessStr: string = getString($r('app.string.checkbox_brightness'));
|
||||
await driver.assertComponentExist(ON.id(checkboxBrightnessStr));
|
||||
let checkboxBrightness = await driver.findComponent(ON.id(checkboxBrightnessStr));
|
||||
await checkboxBrightness.click();
|
||||
await driver.delayMs(1000);
|
||||
let sliderBrightnessStr: string = getString($r('app.string.slider_brightness'));
|
||||
await driver.assertComponentExist(ON.id(sliderBrightnessStr));
|
||||
let sliderBrightness = await driver.findComponent(ON.id(sliderBrightnessStr));
|
||||
let point = await sliderBrightness.getBoundsCenter();
|
||||
await driver.swipe(point.x, point.y, point.x + 226, point.y);
|
||||
await driver.delayMs(1000);
|
||||
await confirmDialog();
|
||||
await apply();
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustBrightness_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number AdjustContrast_001
|
||||
* @tc.name AdjustContrast_001
|
||||
* @tc.desc Contrast滤镜
|
||||
*/
|
||||
it('AdjustContrast_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustContrast_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let checkboxContrastStr: string = getString($r('app.string.checkbox_contrast'));
|
||||
await driver.assertComponentExist(ON.id(checkboxContrastStr));
|
||||
let checkboxContrast = await driver.findComponent(ON.id(checkboxContrastStr));
|
||||
await checkboxContrast.click();
|
||||
await driver.delayMs(1000);
|
||||
let sliderContrastStr: string = getString($r('app.string.slider_contrast'));
|
||||
await driver.assertComponentExist(ON.id(sliderContrastStr));
|
||||
let sliderContrast = await driver.findComponent(ON.id(sliderContrastStr));
|
||||
let point = await sliderContrast.getBoundsCenter();
|
||||
await driver.swipe(point.x, point.y, point.x + 226, point.y);
|
||||
await driver.delayMs(1000);
|
||||
await confirmDialog();
|
||||
await apply();
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustContrast_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number AdjustCrop_001
|
||||
* @tc.name AdjustCrop_001
|
||||
* @tc.desc Crop滤镜
|
||||
*/
|
||||
it('AdjustCrop_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustCrop_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let checkboxCropStr: string = getString($r('app.string.checkbox_crop'));
|
||||
await driver.assertComponentExist(ON.id(checkboxCropStr));
|
||||
let checkboxCrop = await driver.findComponent(ON.id(checkboxCropStr));
|
||||
await checkboxCrop.click();
|
||||
await driver.delayMs(1000);
|
||||
let sliderCropStr: string = getString($r('app.string.slider_crop'));
|
||||
await driver.assertComponentExist(ON.id(sliderCropStr));
|
||||
let sliderCrop = await driver.findComponent(ON.id(sliderCropStr));
|
||||
let point = await sliderCrop.getBoundsCenter();
|
||||
await driver.swipe(point.x, point.y, point.x + 226, point.y);
|
||||
await driver.delayMs(1000);
|
||||
await confirmDialog();
|
||||
await apply();
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustCrop_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number AdjustCustom_001
|
||||
* @tc.name AdjustCustom_001
|
||||
* @tc.desc Custom滤镜
|
||||
*/
|
||||
it('AdjustCustom_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustCustom_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let checkboxCustomStr: string = getString($r('app.string.checkbox_custom'));
|
||||
await driver.assertComponentExist(ON.id(checkboxCustomStr));
|
||||
let checkboxCustom = await driver.findComponent(ON.id(checkboxCustomStr));
|
||||
await checkboxCustom.click();
|
||||
await driver.delayMs(1000);
|
||||
let sliderCustomStr: string = getString($r('app.string.slider_custom'));
|
||||
await driver.assertComponentExist(ON.id(sliderCustomStr));
|
||||
let sliderCustom = await driver.findComponent(ON.id(sliderCustomStr));
|
||||
let point = await sliderCustom.getBoundsCenter();
|
||||
await driver.swipe(point.x, point.y, point.x + 226, point.y);
|
||||
await driver.delayMs(1000);
|
||||
await confirmDialog();
|
||||
await apply();
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'AdjustCustom_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number ClickResetBtn_001
|
||||
* @tc.name AdjustCustom_001
|
||||
* @tc.desc 点击Reset按钮,图像效果复原
|
||||
*/
|
||||
it('ClickResetBtn_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickResetBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
let btnReset: string = getString($r('app.string.btn_reset'));
|
||||
await driver.assertComponentExist(ON.id(btnReset));
|
||||
let reset = await driver.findComponent(ON.id(btnReset));
|
||||
await reset.click();
|
||||
await driver.delayMs(1000);
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickResetBtn_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number ClickBrightnessSearchBtn_001
|
||||
* @tc.name ClickBrightnessSearchBtn_001
|
||||
* @tc.desc Brightness查询按钮,显示Brightness滤镜信息
|
||||
*/
|
||||
it('ClickBrightnessSearchBtn_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickBrightnessSearchBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let btnBrightnessSearch: string = getString($r('app.string.btn_search_brightness'));
|
||||
await driver.assertComponentExist(ON.id(btnBrightnessSearch));
|
||||
let brightnessSearch = await driver.findComponent(ON.id(btnBrightnessSearch));
|
||||
await brightnessSearch.click();
|
||||
await driver.delayMs(1000);
|
||||
let filterInfoStr: string = getString($r('app.string.filter_info_menu'));
|
||||
await driver.assertComponentExist(ON.id(filterInfoStr));
|
||||
await driver.findComponent(ON.id(filterInfoStr));
|
||||
await driver.delayMs(3000);
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickBrightnessSearchBtn_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number ClickContrastSearchBtn_001
|
||||
* @tc.name ClickContrastSearchBtn_001
|
||||
* @tc.desc Contrast查询按钮,显示Contrast滤镜信息
|
||||
*/
|
||||
it('ClickContrastSearchBtn_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickContrastSearchBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let btnContrastSearch: string = getString($r('app.string.btn_search_contrast'));
|
||||
await driver.assertComponentExist(ON.id(btnContrastSearch));
|
||||
let contrastSearch = await driver.findComponent(ON.id(btnContrastSearch));
|
||||
await contrastSearch.click();
|
||||
await driver.delayMs(1000);
|
||||
let filterInfoStr: string = getString($r('app.string.filter_info_menu'));
|
||||
await driver.assertComponentExist(ON.id(filterInfoStr));
|
||||
await driver.findComponent(ON.id(filterInfoStr));
|
||||
await driver.delayMs(3000);
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickContrastSearchBtn_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number ClickCropSearchBtn_001
|
||||
* @tc.name ClickCropSearchBtn_001
|
||||
* @tc.desc Crop查询按钮,显示Crop滤镜信息
|
||||
*/
|
||||
it('ClickCropSearchBtn_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickCropSearchBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let btnCropSearch: string = getString($r('app.string.btn_search_crop'));
|
||||
await driver.assertComponentExist(ON.id(btnCropSearch));
|
||||
let cropSearch = await driver.findComponent(ON.id(btnCropSearch));
|
||||
await cropSearch.click();
|
||||
await driver.delayMs(1000);
|
||||
let filterInfoStr: string = getString($r('app.string.filter_info_menu'));
|
||||
await driver.assertComponentExist(ON.id(filterInfoStr));
|
||||
await driver.findComponent(ON.id(filterInfoStr));
|
||||
await driver.delayMs(3000);
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickCropSearchBtn_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number ClickCustomSearchBtn_001
|
||||
* @tc.name ClickCustomSearchBtn_001
|
||||
* @tc.desc Custom查询按钮,显示Custom滤镜信息
|
||||
*/
|
||||
it('ClickCustomSearchBtn_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickCustomSearchBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let btnCustomSearch: string = getString($r('app.string.btn_search_custom'));
|
||||
await driver.assertComponentExist(ON.id(btnCustomSearch));
|
||||
let customSearch = await driver.findComponent(ON.id(btnCustomSearch));
|
||||
await customSearch.click();
|
||||
await driver.delayMs(1000);
|
||||
let filterInfoStr: string = getString($r('app.string.filter_info_menu'));
|
||||
await driver.assertComponentExist(ON.id(filterInfoStr));
|
||||
await driver.findComponent(ON.id(filterInfoStr));
|
||||
await driver.delayMs(3000);
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickCustomSearchBtn_001 end');
|
||||
})
|
||||
|
||||
/**
|
||||
* @tc.number ClickSearchBtn_001
|
||||
* @tc.name ClickSearchBtn_001
|
||||
* @tc.desc 点击查询按钮,显示滤镜滤镜信息
|
||||
*/
|
||||
it('ClickSearchBtn_001', 1, async (done: Function) => {
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickSearchBtn_001 begin');
|
||||
let driver = Driver.create();
|
||||
await driver.delayMs(1000);
|
||||
await openDialog();
|
||||
let btnSearch: string = getString($r('app.string.btn_search'));
|
||||
await driver.assertComponentExist(ON.id(btnSearch));
|
||||
let search = await driver.findComponent(ON.id(btnSearch));
|
||||
await search.click();
|
||||
await driver.delayMs(1000);
|
||||
let menuCategory: string = getString($r('app.string.menu_category'));
|
||||
await driver.assertComponentExist(ON.id(menuCategory));
|
||||
let category = await driver.findComponent(ON.id(menuCategory));
|
||||
await category.click();
|
||||
await driver.delayMs(1000);
|
||||
let menuFormat: string = getString($r('app.string.menu_format'));
|
||||
await driver.assertComponentExist(ON.id(menuFormat));
|
||||
let format = await driver.findComponent(ON.id(menuFormat));
|
||||
await format.click();
|
||||
await driver.delayMs(3000);
|
||||
done();
|
||||
hilog.info(DOMAIN, TAG, BUNDLE + 'ClickSearchBtn_001 end');
|
||||
})
|
||||
|
||||
})
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import abilityTest from './Ability.test';
|
||||
|
||||
export default function testsuite() {
|
||||
abilityTest();
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { abilityDelegatorRegistry } from '@kit.TestKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { window } from '@kit.ArkUI';
|
||||
import { Hypium } from '@ohos/hypium';
|
||||
import testsuite from '../test/List.test';
|
||||
|
||||
export default class TestAbility extends UIAbility {
|
||||
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onCreate');
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'want param:' + JSON.stringify(want) ?? '');
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'launchParam:' + JSON.stringify(launchParam) ?? '');
|
||||
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
|
||||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator();
|
||||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments();
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'start run testcase!!!');
|
||||
Hypium.hypiumTest(abilityDelegator, abilityDelegatorArguments, testsuite);
|
||||
}
|
||||
|
||||
onDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onDestroy');
|
||||
}
|
||||
|
||||
onWindowStageCreate(windowStage: window.WindowStage) {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageCreate');
|
||||
windowStage.loadContent('testability/pages/Index', (err, data) => {
|
||||
if (err.code) {
|
||||
hilog.error(0x0000, 'testTag', 'Failed to load the content. Cause: %{public}s', JSON.stringify(err) ?? '');
|
||||
return;
|
||||
}
|
||||
hilog.info(0x0000, 'testTag', 'Succeeded in loading the content. Data: %{public}s',
|
||||
JSON.stringify(data) ?? '');
|
||||
});
|
||||
}
|
||||
|
||||
onWindowStageDestroy() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onWindowStageDestroy');
|
||||
}
|
||||
|
||||
onForeground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onForeground');
|
||||
}
|
||||
|
||||
onBackground() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'TestAbility onBackground');
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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.
|
||||
*/
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct Index {
|
||||
@State message: string = 'Hello World';
|
||||
|
||||
build() {
|
||||
Row() {
|
||||
Column() {
|
||||
Text(this.message)
|
||||
.fontSize(50)
|
||||
.fontWeight(FontWeight.Bold)
|
||||
}
|
||||
.width('100%')
|
||||
}
|
||||
.height('100%')
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 { abilityDelegatorRegistry, TestRunner } from '@kit.TestKit';
|
||||
import { UIAbility, Want } from '@kit.AbilityKit';
|
||||
import { BusinessError } from '@kit.BasicServicesKit';
|
||||
import { hilog } from '@kit.PerformanceAnalysisKit';
|
||||
import { resourceManager } from '@kit.LocalizationKit';
|
||||
import { util } from '@kit.ArkTS';
|
||||
|
||||
let abilityDelegator: abilityDelegatorRegistry.AbilityDelegator;
|
||||
let abilityDelegatorArguments: abilityDelegatorRegistry.AbilityDelegatorArgs;
|
||||
let jsonPath: string = 'mock/mock-config.json';
|
||||
let tag: string = 'testTag';
|
||||
|
||||
async function onAbilityCreateCallback(data: UIAbility) {
|
||||
hilog.info(0x0000, 'testTag', 'onAbilityCreateCallback, data: ${}', JSON.stringify(data));
|
||||
}
|
||||
|
||||
async function addAbilityMonitorCallback(err: BusinessError) {
|
||||
hilog.info(0x0000, 'testTag', 'addAbilityMonitorCallback : %{public}s', JSON.stringify(err) ?? '');
|
||||
}
|
||||
|
||||
export default class OpenHarmonyTestRunner implements TestRunner {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
onPrepare() {
|
||||
hilog.info(0x0000, 'testTag', '%{public}s', 'OpenHarmonyTestRunner OnPrepare');
|
||||
}
|
||||
|
||||
async onRun() {
|
||||
let tag = 'testTag';
|
||||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun run');
|
||||
abilityDelegatorArguments = abilityDelegatorRegistry.getArguments()
|
||||
abilityDelegator = abilityDelegatorRegistry.getAbilityDelegator()
|
||||
let moduleName = abilityDelegatorArguments.parameters['-m'];
|
||||
let context = abilityDelegator.getAppContext().getApplicationContext().createModuleContext(moduleName);
|
||||
let mResourceManager = context.resourceManager;
|
||||
await checkMock(abilityDelegator, mResourceManager);
|
||||
const bundleName = abilityDelegatorArguments.bundleName;
|
||||
const testAbilityName: string = 'TestAbility';
|
||||
let lMonitor: abilityDelegatorRegistry.AbilityMonitor = {
|
||||
abilityName: testAbilityName,
|
||||
onAbilityCreate: onAbilityCreateCallback,
|
||||
moduleName: moduleName
|
||||
};
|
||||
abilityDelegator.addAbilityMonitor(lMonitor, addAbilityMonitorCallback)
|
||||
const want: Want = {
|
||||
bundleName: bundleName,
|
||||
abilityName: testAbilityName,
|
||||
moduleName: moduleName
|
||||
};
|
||||
abilityDelegator.startAbility(want, (err: BusinessError, data: void) => {
|
||||
hilog.info(0x0000, tag, 'startAbility : err : %{public}s', JSON.stringify(err) ?? '');
|
||||
hilog.info(0x0000, tag, 'startAbility : data : %{public}s', JSON.stringify(data) ?? '');
|
||||
})
|
||||
hilog.info(0x0000, tag, '%{public}s', 'OpenHarmonyTestRunner onRun end');
|
||||
}
|
||||
}
|
||||
|
||||
async function checkMock(abilityDelegator: abilityDelegatorRegistry.AbilityDelegator, resourceManager: resourceManager.ResourceManager) {
|
||||
let rawFile: Uint8Array;
|
||||
try {
|
||||
rawFile = resourceManager.getRawFileContentSync(jsonPath);
|
||||
hilog.info(0x0000, tag, 'MockList file exists');
|
||||
let mockStr: string = util.TextDecoder.create("utf-8", { ignoreBOM: true }).decodeWithStream(rawFile);
|
||||
let mockMap: Record<string, string> = getMockList(mockStr);
|
||||
try {
|
||||
abilityDelegator.setMockList(mockMap)
|
||||
} catch (error) {
|
||||
let code = (error as BusinessError).code;
|
||||
let message = (error as BusinessError).message;
|
||||
hilog.error(0x0000, tag, `abilityDelegator.setMockList failed, error code: ${code}, message: ${message}.`);
|
||||
}
|
||||
} catch (error) {
|
||||
let code = (error as BusinessError).code;
|
||||
let message = (error as BusinessError).message;
|
||||
hilog.error(0x0000, tag, `ResourceManager:callback getRawFileContent failed, error code: ${code}, message: ${message}.`);
|
||||
}
|
||||
}
|
||||
|
||||
function getMockList(jsonStr: string) {
|
||||
let jsonObj: Record<string, Object> = JSON.parse(jsonStr);
|
||||
let map: Map<string, object> = new Map<string, object>(Object.entries(jsonObj));
|
||||
let mockList: Record<string, string> = {};
|
||||
map.forEach((value: object, key: string) => {
|
||||
let realValue: string = value['source'].toString();
|
||||
mockList[key] = realValue;
|
||||
});
|
||||
hilog.info(0x0000, tag, '%{public}s', 'mock-json value:' + JSON.stringify(mockList) ?? '');
|
||||
return mockList;
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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 abilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
|
||||
|
||||
const delegator = abilityDelegatorRegistry.getAbilityDelegator();
|
||||
|
||||
export function getString(resourceData: Resource): string {
|
||||
let manage = delegator.getAppContext().resourceManager;
|
||||
return manage.getStringSync(resourceData)
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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",
|
||||
"description": "$string:module_test_desc",
|
||||
"mainElement": "TestAbility",
|
||||
"deviceTypes": [
|
||||
"default",
|
||||
"tablet"
|
||||
],
|
||||
"deliveryWithInstall": true,
|
||||
"installationFree": false,
|
||||
"pages": "$profile:test_pages",
|
||||
"abilities": [
|
||||
{
|
||||
"name": "TestAbility",
|
||||
"srcEntry": "./ets/testability/TestAbility.ets",
|
||||
"description": "$string:TestAbility_desc",
|
||||
"icon": "$media:icon",
|
||||
"label": "$string:TestAbility_label",
|
||||
"exported": true,
|
||||
"startWindowIcon": "$media:icon",
|
||||
"startWindowBackground": "$color:start_window_background",
|
||||
"skills": [
|
||||
{
|
||||
"actions": [
|
||||
"action.system.home"
|
||||
],
|
||||
"entities": [
|
||||
"entity.system.home"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
{
|
||||
"color": [
|
||||
{
|
||||
"name": "start_window_background",
|
||||
"value": "#FFFFFF"
|
||||
}
|
||||
]
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
{
|
||||
"string": [
|
||||
{
|
||||
"name": "module_test_desc",
|
||||
"value": "test ability description"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_desc",
|
||||
"value": "the test ability"
|
||||
},
|
||||
{
|
||||
"name": "TestAbility_label",
|
||||
"value": "test label"
|
||||
},
|
||||
{
|
||||
"name": "btn_setting",
|
||||
"value": "btn_setting"
|
||||
},
|
||||
{
|
||||
"name": "btn_dialog_confirm",
|
||||
"value": "btn_dialog_confirm"
|
||||
},
|
||||
{
|
||||
"name": "btn_dialog_cancel",
|
||||
"value": "btn_dialog_cancel"
|
||||
},
|
||||
{
|
||||
"name": "checkbox_brightness",
|
||||
"value": "checkbox_brightness"
|
||||
},
|
||||
{
|
||||
"name": "slider_brightness",
|
||||
"value": "slider_brightness"
|
||||
},
|
||||
{
|
||||
"name": "btn_apply",
|
||||
"value": "btn_apply"
|
||||
},
|
||||
{
|
||||
"name": "btn_reset",
|
||||
"value": "btn_reset"
|
||||
},
|
||||
{
|
||||
"name": "checkbox_contrast",
|
||||
"value": "checkbox_contrast"
|
||||
},
|
||||
{
|
||||
"name": "slider_contrast",
|
||||
"value": "slider_contrast"
|
||||
},
|
||||
{
|
||||
"name": "checkbox_crop",
|
||||
"value": "checkbox_crop"
|
||||
},
|
||||
{
|
||||
"name": "slider_crop",
|
||||
"value": "slider_crop"
|
||||
},
|
||||
{
|
||||
"name": "checkbox_custom",
|
||||
"value": "checkbox_custom"
|
||||
},
|
||||
{
|
||||
"name": "slider_custom",
|
||||
"value": "slider_custom"
|
||||
},
|
||||
{
|
||||
"name": "btn_search_brightness",
|
||||
"value": "btn_search_brightness"
|
||||
},
|
||||
{
|
||||
"name": "filter_info_menu",
|
||||
"value": "filter_info_menu"
|
||||
},
|
||||
{
|
||||
"name": "btn_search_contrast",
|
||||
"value": "btn_search_contrast"
|
||||
},
|
||||
{
|
||||
"name": "btn_search_crop",
|
||||
"value": "btn_search_crop"
|
||||
},
|
||||
{
|
||||
"name": "btn_search_custom",
|
||||
"value": "btn_search_custom"
|
||||
},
|
||||
{
|
||||
"name": "btn_search",
|
||||
"value": "btn_search"
|
||||
},
|
||||
{
|
||||
"name": "menu_category",
|
||||
"value": "menu_category"
|
||||
},
|
||||
{
|
||||
"name": "menu_format",
|
||||
"value": "menu_format"
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1,5 @@
|
||||
{
|
||||
"src": [
|
||||
"testability/pages/Index"
|
||||
]
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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();
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2024 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);
|
||||
});
|
||||
});
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
{
|
||||
"hvigorVersion": "4.0.4",
|
||||
"dependencies": {
|
||||
"@ohos/hvigor-ohos-plugin": "4.0.4"
|
||||
},
|
||||
"execution": {
|
||||
// "analyze": "default", /* Define the build analyze mode. Value: [ "default" | "verbose" | false ]. Default: "default" */
|
||||
// "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
|
||||
// "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
|
||||
// "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
|
||||
// "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"logging": {
|
||||
// "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
|
||||
},
|
||||
"debugging": {
|
||||
// "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
|
||||
},
|
||||
"nodeOptions": {
|
||||
// "maxOldSpaceSize": 4096 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process */
|
||||
}
|
||||
}
|
6
code/BasicFeature/Media/ImageEffect/hvigorfile.ts
Normal file
@ -0,0 +1,6 @@
|
||||
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. */
|
||||
}
|
54
code/BasicFeature/Media/ImageEffect/hvigorw
Normal file
@ -0,0 +1,54 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Hvigor startup script, version 1.0.0
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# NODE_HOME - location of a Node home dir
|
||||
# or
|
||||
# Add /usr/local/nodejs/bin to the PATH environment variable
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
HVIGOR_APP_HOME="`pwd -P`"
|
||||
HVIGOR_WRAPPER_SCRIPT=${HVIGOR_APP_HOME}/hvigor/hvigor-wrapper.js
|
||||
#NODE_OPTS="--max-old-space-size=4096"
|
||||
|
||||
fail() {
|
||||
echo "$*"
|
||||
exit 1
|
||||
}
|
||||
|
||||
set_executable_node() {
|
||||
EXECUTABLE_NODE="${NODE_HOME}/bin/node"
|
||||
if [ -x "$EXECUTABLE_NODE" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
EXECUTABLE_NODE="${NODE_HOME}/node"
|
||||
if [ -x "$EXECUTABLE_NODE" ]; then
|
||||
return
|
||||
fi
|
||||
fail "ERROR: NODE_HOME is set to an invalid directory,check $NODE_HOME\n\nPlease set NODE_HOME in your environment to the location where your nodejs installed"
|
||||
}
|
||||
|
||||
# Determine node to start hvigor wrapper script
|
||||
if [ -n "${NODE_HOME}" ]; then
|
||||
set_executable_node
|
||||
else
|
||||
EXECUTABLE_NODE="node"
|
||||
command -v ${EXECUTABLE_NODE} &> /dev/null || fail "ERROR: NODE_HOME not set and 'node' command not found"
|
||||
fi
|
||||
|
||||
# Check hvigor wrapper script
|
||||
if [ ! -r "$HVIGOR_WRAPPER_SCRIPT" ]; then
|
||||
fail "ERROR: Couldn't find hvigor/hvigor-wrapper.js in ${HVIGOR_APP_HOME}"
|
||||
fi
|
||||
|
||||
if [ -z "${NODE_OPTS}" ]; then
|
||||
NODE_OPTS="--"
|
||||
fi
|
||||
|
||||
# start hvigor-wrapper script
|
||||
exec "${EXECUTABLE_NODE}" "${NODE_OPTS}" \
|
||||
"${HVIGOR_WRAPPER_SCRIPT}" "$@"
|
54
code/BasicFeature/Media/ImageEffect/hvigorw.bat
Normal file
@ -0,0 +1,54 @@
|
||||
@rem
|
||||
@rem ----------------------------------------------------------------------------
|
||||
@rem Hvigor startup script for Windows, version 1.0.0
|
||||
@rem
|
||||
@rem Required ENV vars:
|
||||
@rem ------------------
|
||||
@rem NODE_HOME - location of a Node home dir
|
||||
@rem or
|
||||
@rem Add %NODE_HOME%/bin to the PATH environment variable
|
||||
@rem ----------------------------------------------------------------------------
|
||||
@rem
|
||||
@echo off
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
set WRAPPER_MODULE_PATH=%APP_HOME%\hvigor\hvigor-wrapper.js
|
||||
set NODE_EXE=node.exe
|
||||
@rem set NODE_OPTS="--max-old-space-size=4096"
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
if not defined NODE_OPTS set NODE_OPTS="--"
|
||||
|
||||
@rem Find node.exe
|
||||
if defined NODE_HOME (
|
||||
set NODE_HOME=%NODE_HOME:"=%
|
||||
set NODE_EXE_PATH=%NODE_HOME%/%NODE_EXE%
|
||||
)
|
||||
|
||||
%NODE_EXE% --version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" (
|
||||
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %*
|
||||
) else if exist "%NODE_EXE_PATH%" (
|
||||
"%NODE_EXE%" "%NODE_OPTS%" "%WRAPPER_MODULE_PATH%" %*
|
||||
) else (
|
||||
echo.
|
||||
echo ERROR: NODE_HOME is not set and no 'node' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the NODE_HOME variable in your environment to match the
|
||||
echo location of your NodeJs installation.
|
||||
)
|
||||
|
||||
if "%ERRORLEVEL%" == "0" (
|
||||
if "%OS%" == "Windows_NT" endlocal
|
||||
) else (
|
||||
exit /b %ERRORLEVEL%
|
||||
)
|
14
code/BasicFeature/Media/ImageEffect/oh-package.json5
Normal file
@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "imageeffect",
|
||||
"version": "1.0.0",
|
||||
"description": "Please describe the basic information.",
|
||||
"main": "",
|
||||
"author": "",
|
||||
"license": "",
|
||||
"dependencies": {
|
||||
},
|
||||
"devDependencies": {
|
||||
"@ohos/hypium": "1.0.15",
|
||||
"@ohos/hamock": "1.0.0"
|
||||
}
|
||||
}
|
28
code/BasicFeature/Media/ImageEffect/ohosTest.md
Normal file
@ -0,0 +1,28 @@
|
||||
# ImageEffect测试用例归档
|
||||
|
||||
## 用例表
|
||||
|
||||
| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 |
|
||||
| ---------------------------- | ------------------------------ | ------------------------------------------------------------ | ------------------------------ | -------- | -------- |
|
||||
| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass |
|
||||
| 验证弹出参数设置页面 | 进入图片展示页面 | 点击右上角设置按钮 | 成功弹出参数设置页面 | 是 | Pass |
|
||||
| 验证弹出参数设置页面取消功能 | 参数设置页面弹出 | 点击取消按钮 | 成功关闭参数设置页面 | 是 | Pass |
|
||||
| 验证参数设置页面确认功能 | 参数设置页面弹出,参数设置成功 | 点击确认按钮 | 成功关闭参数设置页面 | 是 | Pass |
|
||||
| 验证Brightness滑动条功能 | 参数设置页面弹出 | 滑动Brightness滑动条 | Brightness滑动条成功滑动 | 是 | Pass |
|
||||
| 验证Contrast滑动条功能 | 参数设置页面弹出 | 滑动Contrast滑动条 | Contrast滑动条成功滑动 | 是 | Pass |
|
||||
| 验证Crop滑动条功能 | 参数设置页面弹出 | 滑动Crop滑动条 | Crop滑动条成功滑动 | 是 | Pass |
|
||||
| 验证Custom滑动条功能 | 参数设置页面弹出 | 滑动Custom滑动条 | Custom滑动条成功滑动 | 是 | Pass |
|
||||
| 验证Brightness滤镜功能 | 参数设置页面弹出 | 选中Brightness-滑动滑动条-确认-Apply | Brightness滤镜效果应用成功 | 是 | Pass |
|
||||
| 验证Contrast滤镜功能 | 参数设置页面弹出 | 选中Contrast-滑动滑动条-确认-Apply | Contrast滤镜效果应用成功 | 是 | Pass |
|
||||
| 验证Crop滤镜功能 | 参数设置页面弹出 | 选中Crop-滑动滑动条-确认-Apply | Crop滤镜效果应用成功 | 是 | Pass |
|
||||
| 验证Custom滤镜功能 | 参数设置页面弹出 | 选中Custom-滑动滑动条-确认-Apply | Custom滤镜效果应用成功 | 是 | Pass |
|
||||
| 验证滤镜链功能 | 参数设置页面弹出 | 选中Brightness-滑动滑动条-确认-Apply;<br>选中Contrast-滑动滑动条-确认-Apply;<br>选中Crop-滑动滑动条-确认-Apply; | 滤镜链效果应用成功 | 是 | Pass |
|
||||
| 验证图像效果应用功能 | 滤镜参数设置成功 | 点击Apply按钮 | 按钮存在,图像效果改变 | 是 | Pass |
|
||||
| 验证图像效果复原功能 | 滤镜效果应用成功 | 点击Reset按钮 | 按钮存在,图像效果复原 | 是 | Pass |
|
||||
| 验证Brightness滤镜查询功能 | 参数设置页面弹出 | 点击Brightness查询按钮 | Brightness滤镜查询页面成功弹出 | 是 | Pass |
|
||||
| 验证Contrast滤镜查询功能 | 参数设置页面弹出 | 点击Contrast查询按钮 | Contrast滤镜查询页面成功弹出 | 是 | Pass |
|
||||
| 验证Crop滤镜查询功能 | 参数设置页面弹出 | 点击Crop查询按钮 | Crop滤镜查询页面成功弹出 | 是 | Pass |
|
||||
| 验证Custom滤镜查询功能 | 参数设置页面弹出 | 点击Custom查询按钮 | Custom滤镜查询页面成功弹出 | 是 | Pass |
|
||||
| 验证滤镜查询功能 | 参数设置页面弹出 | 点击查询按钮 | 弹出CategoryMenu页面 | 是 | Pass |
|
||||
| 验证CategoryMenu页面 | CategoryMenu页面成功弹出 | 点击CategoryMenu页面指定选项 | 弹出FormatMenu页面 | 是 | Pass |
|
||||
| 验证FormatMenu页面 | FormatMenu页面成功弹出 | 点击FormatMenu页面指定选项 | 弹出滤镜信息页面 | 是 | Pass |
|
After Width: | Height: | Size: 95 KiB |
After Width: | Height: | Size: 84 KiB |
After Width: | Height: | Size: 46 KiB |
After Width: | Height: | Size: 43 KiB |
After Width: | Height: | Size: 58 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 60 KiB |
BIN
code/BasicFeature/Media/ImageEffect/screenshots/image_show.jpeg
Normal file
After Width: | Height: | Size: 62 KiB |
After Width: | Height: | Size: 66 KiB |