harmony 鸿蒙Using ImageEffect to Edit Images

  • 2025-06-12
  • 浏览 (4)

Using ImageEffect to Edit Images

When to Use

The ImageEffect class provides a series of APIs for editing an image. You can use the APIs to implement various filter effects on images of different input types (pixel map, native window, native buffer, or URI). With the native APIs provided by ImageEffect, you can:

  • Add a filter or filter chain, set an input image, and make the filter effective on the image.
  • Customize a filter.
  • Use a system defined filter.

Available APIs

For details about the APIs, see ImageEffect.

How to Develop

Adding Dynamic Link Libraries

Add the following libraries to CMakeLists.txt.

target_link_libraries(entry PUBLIC
    libace_ndk.z.so
    libimage_effect.so
    libpixelmap.so
    libnative_window.so
    libnative_buffer.so
)

Add the following dynamic link libraries based on the image type: libpixelmap.so for the pixel map type, libnative_window.so for the native window type, and libnative_buffer.so for the native buffer type.

Adding the Header Files

#include <multimedia/image_effect/image_effect.h>
#include <multimedia/image_effect/image_effect_filter.h>
#include <multimedia/image_effect/image_effect_errors.h>

Making a Filter Effective

  1. Create an ImageEffect instance.

    // Create an ImageEffect instance, with the alias set to ImageEdit.
    OH_ImageEffect *imageEffect = OH_ImageEffect_Create("ImageEdit");
    
  2. Add a filter.

    // Add a filter to obtain an OH_EffectFilter instance. You can call this API multiple times to add multiple filters to form a filter chain.
    OH_EffectFilter *filter = OH_ImageEffect_AddFilter(imageEffect, OH_EFFECT_BRIGHTNESS_FILTER);
    CHECK_AND_RETURN_LOG(filter != nullptr, "OH_ImageEffect_AddFilter fail!");
    
    
    // Set a filter parameter. For example, set the intensity to 50.
    ImageEffect_Any value = { .dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT, .dataValue.floatValue = 50.f };
    ImageEffect_ErrorCode errorCode = OH_EffectFilter_SetValue(filter, OH_EFFECT_FILTER_INTENSITY_KEY, &value);
    
  3. Set the data to be processed.

    Scenario 1: Set the OH_PixelmapNative input type.

    For details about how to use OH_PixelmapNative, see PixelMap Data Processing (C/C++).

    // Set an input pixel map.
    errorCode = OH_ImageEffect_SetInputPixelmap(imageEffect, inputPixelmap);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetInputPixelmap fail!");
    
    
    // (Optional) Set an output pixel map. If this API is not called, the filter effect directly takes effect on the input pixel map.
    errorCode = OH_ImageEffect_SetOutputPixelmap(imageEffect, outputPixelmap);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputPixelmap fail!");
    

    Scenario 2: Set the OH_NativeBuffer input type.

    For details about how to use OH_NativeBuffer, see Native Buffer Development (C/C++).

    // Set an input native buffer.
    errorCode = OH_ImageEffect_SetInputNativeBuffer(imageEffect, inputNativeBuffer);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetInputNativeBuffer fail!");
    
    
    // (Optional) Set an output native buffer. If this API is not called, the filter effect directly takes effect on the input native buffer.
    errorCode = OH_ImageEffect_SetOutputNativeBuffer(imageEffect, outputNativeBuffer);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputNativeBuffer fail!");
    

    Scenario 3: Set the URI input type.

    // Set an input URI.
    errorCode = OH_ImageEffect_SetInputUri(imageEffect, inputUri);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetInputUri fail!");
    
    
    // (Optional) Set an output URI. If this API is not called, the filter effect directly takes effect on the input URI.
    errorCode = OH_ImageEffect_SetOutputUri(imageEffect, outputUri);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputUri fail!");
    

    Scenario 4: Set the OHNativeWindow input type.

    The following uses camera preview as an example to describe the scenario. The surface ID provided by the XComponent for camera preview streams can be converted into an OHNativeWindow instance at the native C++ layer. For details about how to use the XComponent, see XComponent. For details about how to use the native window module, see OHNativeWindow. For details about how to use the camera, see Camera Preview (C/C++).

    (1) Add an XComponent to the .ets file.

     XComponent({ 
         id: 'xcomponentId', 
         type: 'surface',
         controller: this.mXComponentController, 
         libraryname: 'entry'
     })
     .onLoad(() => {
         // Obtain the surface ID of the XComponent.
         this.mSurfaceId = this.mXComponentController.getXComponentSurfaceId()
    
    
         // Obtain the input surface ID.
         this.mSurfaceId = imageEffect.getSurfaceId(this.mSurfaceId)
    
    
         // Call the camera API to start preview and transfer the input surface ID to the camera framework.
         // ...
     })
     .width('100%')
     .height('100%')
    

    (2) Implement imageEffect.getSurfaceId at the native C++ layer.

     // Create a NativeWindow instance based on the surface ID. Note that the instance must be released by calling OH_NativeWindow_DestoryNativeWindow when it is no longer needed.
     uint64_t outputSurfaceId;
     std::istrstream iss(outputSurfaceIdStr);
     issue >> outputSurfaceId;
     OHNativeWindow *outputNativeWindow = nullptr;
     int32_t res = OH_NativeWindow_CreateNativeWindowFromSurfaceId(outputSurfaceId, &outputNativeWindow);
     CHECK_AND_RETURN_LOG(res == 0, "OH_NativeWindow_CreateNativeWindowFromSurfaceId fail!");
    
    
     // Set an output surface.
     ImageEffect_ErrorCode errorCode = OH_ImageEffect_SetOutputSurface(imageEffect, outputNativeWindow);
     CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_SetOutputSurface fail!");
    
    
     // Obtain the input surface. Note that the obtained inputNativeWindow instance must be released by calling OH_NativeWindow_DestoryNativeWindow when it is no longer needed.
     OHNativeWindow *inputNativeWindow = nullptr;
     errorCode = OH_ImageEffect_GetInputSurface(imageEffect, &inputNativeWindow);
     CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_GetInputSurface fail!");
    
    
     // Obtain the surface ID from the inputNativeWindow instance.
     uint64_t inputSurfaceId = 0;
     res = OH_NativeWindow_GetSurfaceId(inputNativeWindow, &inputSurfaceId);
     CHECK_AND_RETURN_LOG(res == 0, "OH_NativeWindow_GetSurfaceId fail!");
    
    
     // Convert the surface ID to a string and return the string.
     std::string inputSurfaceIdStr = std::to_string(inputSurfaceId);
    
  4. Start the image effector.

    // Start the image effector.
    errorCode = OH_ImageEffect_Start(imageEffect);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_Start fail!");
    
  5. (Optional) Stop the image effector. This operation is required only in the input surface scenario.

    // Stop the image effector.
    errorCode = OH_ImageEffect_Stop(imageEffect);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_Stop fail!");
    
  6. (Optional) Serialize the image effector.

    char *info = nullptr;
    errorCode = OH_ImageEffect_Save(imageEffect, &info);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_ImageEffect_Save fail!");
    
  7. Destroy the ImageEffect instance.

    // Release the ImageEffect instance.
    errorCode = OH_ImageEffect_Release(imageEffect);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, result, "OH_ImageEffect_Release fail!");
    

Customizing a Filter

To implement and register a custom filter, perform the following steps:

  1. Define ImageEffect_FilterDelegate.

    // Image information struct.
    struct EffectBufferInfo {
        void *addr = nullptr;
        int32_t width = 0;
        int32_t height = 0;
        int32_t rowSize = 0;
        ImageEffect_Format format = ImageEffect_Format::EFFECT_PIXEL_FORMAT_UNKNOWN;
    };
    
    
    // Implement a custom filter.
    ImageEffect_FilterDelegate filterDelegate = {
        .setValue = [](OH_EffectFilter *filter, const char *key, const ImageEffect_Any *value) {
            // Verify the parameters. If the verification is successful, true is returned. Otherwise, false is returned.
            // ...
            return true;
        },
        .render = [](OH_EffectFilter *filter, OH_EffectBufferInfo *info, OH_EffectFilterDelegate_PushData pushData) {
            return Render(filter, info, pushData);
        },
        .save = [](OH_EffectFilter *filter, char **info) {
            // Obtain the custom filter parameter. In this example, Brightness is the key of the custom filter.
            ImageEffect_Any value;
            ImageEffect_ErrorCode errorCode = OH_EffectFilter_GetValue(filter, "Brightness", &value);
            CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, false, "OH_EffectFilter_GetValue fail!");
    
    
            // Generate a key-value pair.
            json values;
            values["Brightness"] = value.dataValue.floatValue;         
            json root;
            root["name"] = "CustomBrightness";
            root["values"] = values;
    
    
           // Convert the JSON object into the string infoStr.
            // ...
    
    
            // Assign a serialized string address to *info.
            *info = infoStr;
            return true;
        },
        .restore = [](const char *info) {
            // Create an OH_EffectFilter instance, in which CustomBrightness is the name of the custom filter.
            OH_EffectFilter *filter = OH_EffectFilter_Create("CustomBrightness");
            // Parse the JSON string info to obtain the key and value.
            // ...
    
    
            // Set a filter parameter. value is the parameter parsed based on the JSON string in info.
            ImageEffect_ErrorCode errorCode = OH_EffectFilter_SetValue(filter, "Brightness", &value);
    
    
            // ...
            return filter;
        }
    };
    

    You can implement the Render API in two scenarios.

    Scenario 1: The custom algorithm can directly modify the pixel data in info (for example, the brightness filter).

    bool Render(OH_EffectFilter *filter, OH_EffectBufferInfo *info, OH_EffectFilterDelegate_PushData pushData)
    {
        // Obtain the image information.
        EffectBufferInfo inputBufferInfo;
        OH_EffectBufferInfo_GetAddr(info, &inputBufferInfo.addr);
        OH_EffectBufferInfo_GetWidth(info, &inputBufferInfo.width);
        OH_EffectBufferInfo_GetHeight(info, &inputBufferInfo.height);
        OH_EffectBufferInfo_GetRowSize(info, &inputBufferInfo.rowSize);
        OH_EffectBufferInfo_GetEffectFormat(info, &inputBufferInfo.format);
    
    
        // Invoke the custom filter algorithm.
        ApplyCustomAlgo(inputBufferInfo);
    
    
        // After the editing is complete, call pushData to directly transfer the original image.
        pushData(filter, info);
        return true;
    }
    

    Scenario 2: The custom algorithm cannot directly modify the pixel data in info (for example, the crop filter).

    bool Render(OH_EffectFilter *filter, OH_EffectBufferInfo *info, OH_EffectFilterDelegate_PushData pushData)
    {
        // Obtain the image information.
        EffectBufferInfo inputBufferInfo;
        OH_EffectBufferInfo_GetAddr(info, &inputBufferInfo.addr);
        OH_EffectBufferInfo_GetWidth(info, &inputBufferInfo.width);
        OH_EffectBufferInfo_GetHeight(info, &inputBufferInfo.height);
        OH_EffectBufferInfo_GetRowSize(info, &inputBufferInfo.rowSize);
        OH_EffectBufferInfo_GetEffectFormat(info, &inputBufferInfo.format);
    
    
        // Create output pixel information.
        EffectBufferInfo outputBufferInfo = CreateOutputBufferInfo(inputBufferInfo);
    
    
        // Invoke the custom filter algorithm.
        ApplyCustomAlgo(inputBufferInfo, outputBufferInfo);
    
    
        // Generate outputOhInfo.
        OH_EffectBufferInfo *outputOhInfo = OH_EffectBufferInfo_Create();
        OH_EffectBufferInfo_SetAddr(outputOhInfo, outputBufferInfo.addr);
        OH_EffectBufferInfo_SetWidth(outputOhInfo, outputBufferInfo.width);
        OH_EffectBufferInfo_SetHeight(outputOhInfo, outputBufferInfo.height);
        OH_EffectBufferInfo_SetRowSize(outputOhInfo, outputBufferInfo.rowSize);
        OH_EffectBufferInfo_SetEffectFormat(outputOhInfo, outputBufferInfo.format);
    
    
        // Call pushData to transfer outputOhInfo after editing.
        pushData(filter, outputOhInfo);
    
    
        // Release resources.
        OH_EffectBufferInfo_Release(outputOhInfo);
        ReleaseOutputBuffer(outputBufferInfo.addr);
    
    
        return true;
    }
    
  2. Generate custom filter information.

    // Create an OH_EffectFilterInfo instance.
    OH_EffectFilterInfo *customFilterInfo = OH_EffectFilterInfo_Create();
    CHECK_AND_RETURN_LOG(customFilterInfo != nullptr, "OH_EffectFilter_GetValue fail!");
    
    
    // Set the name of the custom filter.
    OH_EffectFilterInfo_SetFilterName(customFilterInfo, "CustomBrightness");
    
    
    // Set the buffer types supported by the custom filter.
    ImageEffect_BufferType bufferTypeArray[] = { ImageEffect_BufferType::EFFECT_BUFFER_TYPE_PIXEL };
    OH_EffectFilterInfo_SetSupportedBufferTypes(customFilterInfo, sizeof(bufferTypeArray) / sizeof(ImageEffect_BufferType), bufferTypeArray);
    
    
    // Set the pixel formats supported by the custom filter.
    ImageEffect_Format formatArray[] = { ImageEffect_Format::EFFECT_PIXEL_FORMAT_RGBA8888 };
    OH_EffectFilterInfo_SetSupportedFormats(customFilterInfo, sizeof(formatArray) / sizeof(ImageEffect_Format), formatArray);
    
  3. Register ImageEffect_FilterDelegate with the image effector.

    // Register the custom filter.
    ImageEffect_ErrorCode errorCode = OH_EffectFilter_Register(customFilterInfo, &filterDelegate);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_EffectFilter_Register fail!");
    

Using a System Defined Filter

  1. Create a filter.

    // Create a filter, for example, a contrast filter.
    OH_EffectFilter *filter = OH_EffectFilter_Create(OH_EFFECT_CONTRAST_FILTER);
    
  2. Set a filter parameter.

    // Set a filter parameter. For example, set the intensity to 50.
    ImageEffect_Any value = {.dataType = ImageEffect_DataType::EFFECT_DATA_TYPE_FLOAT, .dataValue.floatValue = 50.f};
    ImageEffect_ErrorCode errorCode = OH_EffectFilter_SetValue(filter, OH_EFFECT_FILTER_INTENSITY_KEY, &value);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_EffectFilter_SetValue fail!");
    
  3. Make the filter take effect.

    // Start rendering with the filter.
    errorCode = OH_EffectFilter_Render(filter, inputPixelmap, outputPixelmap);
    
  4. Destroy the filter instance.

    // Destroy the filter instance.
    errorCode = OH_EffectFilter_Release(filter);
    

Query Capabilities

  • Query filter information based on the filter name.

    // Create an OH_EffectFilterInfo instance.
    OH_EffectFilterInfo *filterInfo = OH_EffectFilterInfo_Create();
    CHECK_AND_RETURN_LOG(filterInfo != nullptr, "OH_EffectFilterInfo_Create fail!");
    
    
    // Query the filter information based on the filter name.
    ImageEffect_ErrorCode errorCode = OH_EffectFilter_LookupFilterInfo(OH_EFFECT_BRIGHTNESS_FILTER, filterInfo);
    CHECK_AND_RETURN_LOG(errorCode == ImageEffect_ErrorCode::EFFECT_SUCCESS, "OH_EffectFilter_LookupFilterInfo fail!");
    
    
    // Obtain the filter name from the filter information.
    char *name = nullptr;
    OH_EffectFilterInfo_GetFilterName(filterInfo, &name);
    
    
    // Obtain the supported buffer types.
    uint32_t supportedBufferTypesCnt = 0;
    ImageEffect_BufferType *bufferTypeArray = nullptr;
    OH_EffectFilterInfo_GetSupportedBufferTypes(filterInfo, &supportedBufferTypesCnt, &bufferTypeArray);
    
    
    // Obtain the supported pixel formats.
    uint32_t supportedFormatsCnt = 0;
    ImageEffect_Format *formatArray = nullptr;
    OH_EffectFilterInfo_GetSupportedFormats(filterInfo, supportedFormatsCnt, &formatArray);
    
    
    // Destroy the OH_EffectFilterInfo instance.
    OH_EffectFilterInfo_Release(filterInfo);
    
  • Query filters that meet given conditions.

    // Query all filters. Resources need to be released.
    ImageEffect_FilterNames *filterNames = OH_EffectFilter_LookupFilters("Default");
    
    
    // ...
    
    
    // Release virtual memory resources by filter names.
    OH_EffectFilter_ReleaseFilterNames();
    

你可能感兴趣的鸿蒙文章

harmony 鸿蒙Image Kit

harmony 鸿蒙Allocating Memory for Image Decoding (C/C++)

harmony 鸿蒙Allocating Memory for Image Decoding (ArkTS)

harmony 鸿蒙Image Decoding

harmony 鸿蒙Using ImageSource to Decode Images

harmony 鸿蒙Image Encoding

harmony 鸿蒙Using ImagePacker to Encode Images

harmony 鸿蒙Using Image_NativeModule to Process Image Information

harmony 鸿蒙Introduction to Image Kit

harmony 鸿蒙Using Image_NativeModule to Encode Images

0  赞