1# 使用ImageEffect编辑图片 2 3## 场景介绍 4 5ImageEffect提供了一系列接口用于图像的编辑。开发者可以通过`ImageEffect`接口处理不同图像输入类型`Pixelmap`、`NativeWindow`、`NativeBuffer`或`Uri`,获得滤镜处理效果。 6针对ImageEffect,常见的开发场景如下: 7 8- 通过`ImageEffect`提供的Native API接口添加滤镜或滤镜链,设置输入图像,最终生效滤镜效果。 9- 通过注册自定义滤镜,实现开发者的定制化滤镜效果。 10- 通过`EffectFilter`提供的Native API接口快速实现单个滤镜的处理效果。 11 12## 接口说明 13 14详细的接口说明请参考[ImageEffect](../../reference/apis-image-kit/_image_effect.md)。 15 16## 开发步骤 17 18**添加动态链接库** 19 20CMakeLists.txt中添加以下lib。 21 22```txt 23target_link_libraries(entry PUBLIC 24 libace_ndk.z.so 25 libimage_effect.so 26 libpixelmap.so 27 libnative_window.so 28 libnative_buffer.so 29) 30``` 31 32根据处理的图像类型添加对应动态链接库:`Pixelmap`(libpixelmap.so)、`NativeWindow`(libnative_window.so)、`NativeBuffer`(libnative_buffer.so) 33 34**添加头文件** 35 36```c++ 37#include <multimedia/image_effect/image_effect.h> 38#include <multimedia/image_effect/image_effect_filter.h> 39#include <multimedia/image_effect/image_effect_errors.h> 40``` 41 42### 通过ImageEffect提供的接口生效图像效果 43 441. 创建ImageEffect实例。 45 46 ```c++ 47 // 创建imageEffect实例,“ImageEdit”是imageEffect实例别名。 48 OH_ImageEffect *imageEffect = OH_ImageEffect_Create("ImageEdit"); 49 ``` 50 512. 添加EffectFilter滤镜。 52 53 ```c++ 54 // 添加滤镜,获取 OH_EffectFilter 实例。多次调用该接口可以添加多个滤镜,组成滤镜链。 55 OH_EffectFilter *filter = OH_ImageEffect_AddFilter(imageEffect, OH_EFFECT_BRIGHTNESS_FILTER); 56 CHECK_AND_RETURN_LOG(filter != nullptr, "OH_ImageEffect_AddFilter fail!"); 57 58 // 设置滤镜参数, 例如:滤镜强度设置为50。 59 ImageEffect_Any value = { .dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT, .dataValue.floatValue = 50.f }; 60 ImageEffect_ErrorCode errorCode = OH_EffectFilter_SetValue(filter, OH_EFFECT_FILTER_INTENSITY_KEY, &value); 61 ``` 62 633. 设置处理数据。 64 65 **场景一:设置 OH_PixelmapNative 输入类型。** 66 67 OH_PixelmapNative的具体使用方法请参考[Pixelmap开发指导](image-pixelmap-operation-native.md)。 68 69 ```c++ 70 // 设置输入的Pixelmap。 71 errorCode = OH_ImageEffect_SetInputPixelmap(imageEffect, inputPixelmap); 72 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetInputPixelmap fail!"); 73 74 // 设置输出的Pixelmap(可选),不调用该接口时会在输入Pixelmap上直接生效滤镜效果。 75 errorCode = OH_ImageEffect_SetOutputPixelmap(imageEffect, outputPixelmap); 76 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputPixelmap fail!"); 77 ``` 78 79 **场景二:设置 OH_NativeBuffer 输入类型。** 80 81 OH_NativeBuffer的具体使用方法请参考[NativeBuffer开发指导](../../graphics/native-buffer-guidelines.md)。 82 83 ```c++ 84 // 设置输入的NativeBuffer。 85 errorCode = OH_ImageEffect_SetInputNativeBuffer(imageEffect, inputNativeBuffer); 86 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetInputNativeBuffer fail!"); 87 88 // 设置输出的NativeBuffer(可选),不调用该接口时会在输入NativeBuffer上直接生效滤镜效果。 89 errorCode = OH_ImageEffect_SetOutputNativeBuffer(imageEffect, outputNativeBuffer); 90 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputNativeBuffer fail!"); 91 ``` 92 93 **场景三:设置 URI 输入类型。** 94 95 ```c++ 96 // 设置输入的URI。 97 errorCode = OH_ImageEffect_SetInputUri(imageEffect, inputUri); 98 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetInputUri fail!"); 99 100 // 设置输出的URI(可选),不调用该接口时会在输入URI上直接生效滤镜效果。 101 errorCode = OH_ImageEffect_SetOutputUri(imageEffect, outputUri); 102 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputUri fail!"); 103 ``` 104 105 **场景四:设置 OHNativeWindow 输入类型。** 106 107 以相机预览场景为例来说明OHNativeWindow输入场景。XComponent组件为相机预览流提供的SurfaceId,可在native c++层将SurfaceId转换成OHNativeWindow,下面提供一份代码示例。 108 XComponent模块的具体使用方法请参考[XComponent组件参考](../../reference/apis-arkui/arkui-ts/ts-basic-components-xcomponent.md)。 109 NativeWindow模块的具体使用方法请参考[OHNativeWindow](../../reference/apis-arkgraphics2d/_native_window.md)。 110 Camera的具体使用方法请参考[Camera预览参考](../camera/native-camera-preview.md)。 111 112 (1) 在xxx.ets中添加一个XComponent组件。 113 114 ```ts 115 XComponent({ 116 id: 'xcomponentId', 117 type: 'surface', 118 controller: this.mXComponentController, 119 libraryname: 'entry' 120 }) 121 .onLoad(() => { 122 // 获取XComponent的SurfaceId。 123 this.mSurfaceId = this.mXComponentController.getXComponentSurfaceId() 124 125 // 调用native接口获取输入SurfaceId。 126 this.mSurfaceId = imageEffect.getSurfaceId(this.mSurfaceId) 127 128 // 调用相机接口启动预览,将获取到的输入SurfaceId传递给相机框架 129 // ... 130 }) 131 .width('100%') 132 .height('100%') 133 ``` 134 135 (2) imageEffect.getSurfaceId的native c++层具体实现。 136 137 ```c++ 138 // 根据SurfaceId创建NativeWindow,注意创建出来的NativeWindow在使用结束后需要主动调用OH_NativeWindow_DestoryNativeWindow进行释放。 139 uint64_t outputSurfaceId; 140 std::istrstream iss(outputSurfaceIdStr); 141 issue >> outputSurfaceId; 142 OHNativeWindow *outputNativeWindow = nullptr; 143 int32_t res = OH_NativeWindow_CreateNativeWindowFromSurfaceId(outputSurfaceId, &outputNativeWindow); 144 CHECK_AND_RETURN_LOG(res == 0, "OH_NativeWindow_CreateNativeWindowFromSurfaceId fail!"); 145 146 // 设置输出显示的Surface。 147 ImageEffect_ErrorCode errorCode = OH_ImageEffect_SetOutputSurface(imageEffect, outputNativeWindow); 148 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputSurface fail!"); 149 150 // 获取输入的Surface。注意获取的inputNativeWindow在使用结束后需要主动调用OH_NativeWindow_DestoryNativeWindow进行释放。 151 OHNativeWindow *inputNativeWindow = nullptr; 152 errorCode = OH_ImageEffect_GetInputSurface(imageEffect, &inputNativeWindow); 153 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_GetInputSurface fail!"); 154 155 // 从获取到输入的NativeWindow中获取SurfaceId。 156 uint64_t inputSurfaceId = 0; 157 res = OH_NativeWindow_GetSurfaceId(inputNativeWindow, &inputSurfaceId); 158 CHECK_AND_RETURN_LOG(res == 0, "OH_NativeWindow_GetSurfaceId fail!"); 159 160 // 将SurfaceId转成字符串进行返回。 161 std::string inputSurfaceIdStr = std::to_string(inputSurfaceId); 162 ``` 163 1644. 启动效果器。 165 166 ```c++ 167 // 执行生效滤镜效果。 168 errorCode = OH_ImageEffect_Start(imageEffect); 169 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_Start fail!"); 170 ``` 171 1725. 停止生效效果(可选,仅在输入Surface场景下才有效)。 173 174 ```c++ 175 // 停止生效滤镜效果。 176 errorCode = OH_ImageEffect_Stop(imageEffect); 177 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_Stop fail!"); 178 ``` 179 1806. 序列化效果器(可选)。 181 182 ```c++ 183 char *info = nullptr; 184 errorCode = OH_ImageEffect_Save(imageEffect, &info); 185 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_Save fail!"); 186 ``` 187 1887. 销毁效果器实例。 189 190 ```c++ 191 // 释放imageEffect实例资源。 192 errorCode = OH_ImageEffect_Release(imageEffect); 193 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, result, "OH_ImageEffect_Release fail!"); 194 ``` 195 196### 自定义滤镜 197 198以下步骤描述了如何实现并注册自定义滤镜接口: 199 2001. 定义 ImageEffect_FilterDelegate。 201 202 ```c++ 203 // 图像信息结构体。 204 struct EffectBufferInfo { 205 void *addr = nullptr; 206 int32_t width = 0; 207 int32_t height = 0; 208 int32_t rowSize = 0; 209 ImageEffect_Format format = ImageEffect_Format::EFFECT_PIXEL_FORMAT_UNKNOWN; 210 }; 211 212 // 自定义滤镜具体实现。 213 ImageEffect_FilterDelegate filterDelegate = { 214 .setValue = [](OH_EffectFilter *filter, const char *key, const ImageEffect_Any *value) { 215 // 参数校验,校验成功时返回true,否则返回false。 216 // ... 217 return true; 218 }, 219 .render = [](OH_EffectFilter *filter, OH_EffectBufferInfo *info, OH_EffectFilterDelegate_PushData pushData) { 220 return Render(filter, info, pushData); 221 }, 222 .save = [](OH_EffectFilter *filter, char **info) { 223 // 获取自定义所设置的滤镜参数,其中"Brightness"为自定义滤镜的Key,由开发者自己任意指定。 224 ImageEffect_Any value; 225 ImageEffect_ErrorCode errorCode = OH_EffectFilter_GetValue(filter, "Brightness", &value); 226 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, false, "OH_EffectFilter_GetValue fail!"); 227 228 // 生成键值对信息。 229 json values; 230 values["Brightness"] = value.dataValue.floatValue; 231 json root; 232 root["name"] = "CustomBrightness"; 233 root["values"] = values; 234 235 // 将json对象转成字符串infoStr 236 // ... 237 238 // 对*info赋值序列化字符串地址。 239 *info = infoStr; 240 return true; 241 }, 242 .restore = [](const char *info) { 243 // 创建 OH_EffectFilter 实例,其中"CustomBrightness"为自定义滤镜的滤镜名。 244 OH_EffectFilter *filter = OH_EffectFilter_Create("CustomBrightness"); 245 // 解析json字符串info获取key和value。 246 // ... 247 248 // 设置滤镜参数, value为info中按json解析出来的参数。 249 ImageEffect_ErrorCode errorCode = OH_EffectFilter_SetValue(filter, "Brightness", &value); 250 251 // ... 252 return filter; 253 } 254 }; 255 ``` 256 257 其中Render接口的实现分两种场景。 258 259 **场景一:自定义算法可以直接修改info中的像素数据(比如:亮度调节滤镜)。** 260 261 ```c++ 262 bool Render(OH_EffectFilter *filter, OH_EffectBufferInfo *info, OH_EffectFilterDelegate_PushData pushData) 263 { 264 // 获取图像信息具体参数。 265 EffectBufferInfo inputBufferInfo; 266 OH_EffectBufferInfo_GetAddr(info, &inputBufferInfo.addr); 267 OH_EffectBufferInfo_GetWidth(info, &inputBufferInfo.width); 268 OH_EffectBufferInfo_GetHeight(info, &inputBufferInfo.height); 269 OH_EffectBufferInfo_GetRowSize(info, &inputBufferInfo.rowSize); 270 OH_EffectBufferInfo_GetEffectFormat(info, &inputBufferInfo.format); 271 272 // 调用自定义滤镜算法。 273 ApplyCustomAlgo(inputBufferInfo); 274 275 // 编辑完成后调用pushData直接传递原图。 276 pushData(filter, info); 277 return true; 278 } 279 ``` 280 281 **场景二:自定义算法不能直接修改info中的像素数据(比如:裁剪滤镜)。** 282 283 ```c++ 284 bool Render(OH_EffectFilter *filter, OH_EffectBufferInfo *info, OH_EffectFilterDelegate_PushData pushData) 285 { 286 // 获取图像信息具体参数。 287 EffectBufferInfo inputBufferInfo; 288 OH_EffectBufferInfo_GetAddr(info, &inputBufferInfo.addr); 289 OH_EffectBufferInfo_GetWidth(info, &inputBufferInfo.width); 290 OH_EffectBufferInfo_GetHeight(info, &inputBufferInfo.height); 291 OH_EffectBufferInfo_GetRowSize(info, &inputBufferInfo.rowSize); 292 OH_EffectBufferInfo_GetEffectFormat(info, &inputBufferInfo.format); 293 294 // 创建输出像素信息。 295 EffectBufferInfo outputBufferInfo = CreateOutputBufferInfo(inputBufferInfo); 296 297 // 调用自定义滤镜算法。 298 ApplyCustomAlgo(inputBufferInfo, outputBufferInfo); 299 300 // 生成outputOhInfo。 301 OH_EffectBufferInfo *outputOhInfo = OH_EffectBufferInfo_Create(); 302 OH_EffectBufferInfo_SetAddr(outputOhInfo, outputBufferInfo.addr); 303 OH_EffectBufferInfo_SetWidth(outputOhInfo, outputBufferInfo.width); 304 OH_EffectBufferInfo_SetHeight(outputOhInfo, outputBufferInfo.height); 305 OH_EffectBufferInfo_SetRowSize(outputOhInfo, outputBufferInfo.rowSize); 306 OH_EffectBufferInfo_SetEffectFormat(outputOhInfo, outputBufferInfo.format); 307 308 // 编辑完成后调用pushData传递outputOhInfo。 309 pushData(filter, outputOhInfo); 310 311 // 释放资源。 312 OH_EffectBufferInfo_Release(outputOhInfo); 313 ReleaseOutputBuffer(outputBufferInfo.addr); 314 315 return true; 316 } 317 ``` 318 3192. 生成自定义滤镜信息。 320 321 ```c++ 322 // 创建 OH_EffectFilterInfo 实例。 323 OH_EffectFilterInfo *customFilterInfo = OH_EffectFilterInfo_Create(); 324 CHECK_AND_RETURN_LOG(customFilterInfo != nullptr, "OH_EffectFilter_GetValue fail!"); 325 326 // 设置自定义滤镜滤镜名。 327 OH_EffectFilterInfo_SetFilterName(customFilterInfo, "CustomBrightness"); 328 329 // 设置自定义滤镜所支持的内存类型。 330 ImageEffect_BufferType bufferTypeArray[] = { ImageEffect_BufferType::EFFECT_BUFFER_TYPE_PIXEL }; 331 OH_EffectFilterInfo_SetSupportedBufferTypes(customFilterInfo, sizeof(bufferTypeArray) / sizeof(ImageEffect_BufferType), bufferTypeArray); 332 333 // 设置自定义滤镜所支持的像素格式。 334 ImageEffect_Format formatArray[] = { ImageEffect_Format::EFFECT_PIXEL_FORMAT_RGBA8888 }; 335 OH_EffectFilterInfo_SetSupportedFormats(customFilterInfo, sizeof(formatArray) / sizeof(ImageEffect_Format), formatArray); 336 ``` 337 3383. 将 ImageEffect_FilterDelegate 注册到效果器。 339 340 ```c++ 341 // 注册自定义滤镜。 342 ImageEffect_ErrorCode errorCode = OH_EffectFilter_Register(customFilterInfo, &filterDelegate); 343 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_EffectFilter_Register fail!"); 344 ``` 345 346### EffectFilter快速实现单个滤镜的处理效果 347 3481. 创建滤镜。 349 350 ```c++ 351 // 创建滤镜。比如:创建对比度效果器。 352 OH_EffectFilter *filter = OH_EffectFilter_Create(OH_EFFECT_CONTRAST_FILTER); 353 ``` 354 3552. 设置滤镜参数。 356 357 ```c++ 358 // 设置滤镜参数, 滤镜强度设置为50。 359 ImageEffect_Any value = {.dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT, .dataValue.floatValue = 50.f}; 360 ImageEffect_ErrorCode errorCode = OH_EffectFilter_SetValue(filter, OH_EFFECT_FILTER_INTENSITY_KEY, &value); 361 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_EffectFilter_SetValue fail!"); 362 ``` 363 3643. 生效滤镜。 365 366 ```c++ 367 // 生效滤镜效果。 368 errorCode = OH_EffectFilter_Render(filter, inputPixelmap, outputPixelmap); 369 ``` 370 3714. 销毁滤镜实例。 372 373 ```c++ 374 // 销毁滤镜实例。 375 errorCode = OH_EffectFilter_Release(filter); 376 ``` 377 378### 查询能力 379 380- 根据滤镜名查询滤镜信息。 381 382 ```c++ 383 // 创建 OH_EffectFilterInfo 实例。 384 OH_EffectFilterInfo *filterInfo = OH_EffectFilterInfo_Create(); 385 CHECK_AND_RETURN_LOG(filterInfo != nullptr, "OH_EffectFilterInfo_Create fail!"); 386 387 // 根据滤镜名查询滤镜能力信息。 388 ImageEffect_ErrorCode errorCode = OH_EffectFilter_LookupFilterInfo(OH_EFFECT_BRIGHTNESS_FILTER, filterInfo); 389 CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_EffectFilter_LookupFilterInfo fail!"); 390 391 // 从滤镜能力信息中获取滤镜名。 392 char *name = nullptr; 393 OH_EffectFilterInfo_GetFilterName(filterInfo, &name); 394 395 // 获取支持的内存类型。 396 uint32_t supportedBufferTypesCnt = 0; 397 ImageEffect_BufferType *bufferTypeArray = nullptr; 398 OH_EffectFilterInfo_GetSupportedBufferTypes(filterInfo, &supportedBufferTypesCnt, &bufferTypeArray); 399 400 // 获取支持的像素类型信息。 401 uint32_t supportedFormatsCnt = 0; 402 ImageEffect_Format *formatArray = nullptr; 403 OH_EffectFilterInfo_GetSupportedFormats(filterInfo, supportedFormatsCnt, &formatArray); 404 405 // 销毁 OH_EffectFilterInfo 实例。 406 OH_EffectFilterInfo_Release(filterInfo); 407 ``` 408 409- 根据条件查询满足条件的滤镜。 410 411 ```c++ 412 // 查询所有的Filter,需要主动进行资源释放。 413 ImageEffect_FilterNames *filterNames = OH_EffectFilter_LookupFilters("Default"); 414 415 // ... 416 417 // 释放FilterNames虚拟内存资源。 418 OH_EffectFilter_ReleaseFilterNames(); 419 ``` 420 421## 相关实例 422 423针对ImageEffect的开发,有以下相关实例可供参考: 424 425- [ImageEffect(API12)](https://gitee.com/openharmony/applications_app_samples/tree/master/code/BasicFeature/Media/ImageEffect)