场景描述
使用ImageEffect接口实现对图片添加滤镜链,添加的滤镜链由系统提供的对比度、亮度、裁剪等滤镜与自定义滤镜构成,以此实现对图片的编辑。
方案描述
- 在arkts侧解码resources下的图片,获取image.pixelMap,并设置图片滤镜亮度、对比度、裁剪等参数,调用napi接口将image.PixelMap和滤镜参数传递到native侧。
- native侧将获取到的image.PixelMap转换成可作为ImageEffect输入的OH\_PixelmapNative对象。
- 将OH\_PixelmapNative作为ImageEffect的输入,根据传入的滤镜参数,以此往滤镜链路里添加亮度、对比度、裁剪滤镜以及自定义滤镜。
- 将添加滤镜效果的OH\_PixelmapNative对象,转化成image.PixelMap对象返回给arkts层回显。
关键步骤及代码
构建传递给native侧的滤镜参数。
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); } }
解码resources下的图片,获取image.pixelMap,并设置图片滤镜亮度、对比度、裁剪等参数,调用napi接口将image.PixelMap和滤镜参数传递到native侧。
if (this.brightnessSelect || this.contrastSelect || this.cropSelect || this.customSelect) { let pixelMap = await ImageUtils.getInstance().getPixelMap($r('app.media.ic_1080x1920')); // 调用napi接口,传入image.pixelMap对象及滤镜参数 this.displayPixelMap = imageEffect.apply(pixelMap, [...this.filterOptions]); } async getPixelMap(resource: Resource): Promise<image.PixelMap> { const resourceStr = getContext(this).resourceManager; let imageBuffer = await resourceStr.getMediaContent(resource); return await image.createImageSource(imageBuffer.buffer as object as ArrayBuffer).createPixelMap(); }
native侧将image.PixelMap转化成OH\_PixelmapNative。
OH_PixelmapNative* pixelmapNativePtr = nullptr; OH_PixelmapNative_ConvertPixelmapNativeFromNapi(env, args[EXPECTED_ARGS_ZERO],&pixelmapNativePtr);
根据napi接口接收到的滤镜参数,构建滤镜链路。
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; }
构建并注册自定义滤镜。
static ImageEffect_FilterDelegate delegate; 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); return result; }
将OH\_PixelmapNative作为ImageEffect的输入,根据传入的滤镜参数,以此往滤镜链路里添加亮度、对比度、裁剪滤镜以及自定义滤镜。
// 创建ImageEffect对象 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); }); // 将步骤4中构建的滤镜链路添加到ImageEffect对象中 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); } // 将由image.PixelMap转化得到的oh_PixelmapNative设置为ImageEffect的输入 ImageEffect_ErrorCode errorCode = OH_ImageEffect_SetInputPixelmap(imageEffectPtr.get(), pixelmapNativePtr); 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);
将添加滤镜效果的OH\_PixelmapNative对象,转化成image.PixelMap对象返回给arkts层回显。
OH_PixelmapNative_ConvertPixelmapNativeToNapi(env, pixelmapNativePtr, &result); return result;
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。