# 如何为图片、视频添加水印

#### 问题现象

在图片、视频绘制过程中，如何添加水印（文字或emoji表情）？

#### 背景知识

*   Stack：堆叠容器，子组件按照顺序依次入栈，后一个子组件覆盖前一个子组件。
*   overlay：在当前组件上，增加遮罩文本或者叠加自定义组件以及ComponentContent作为该组件的浮层。浮层的定位同样基于当前组件进行计算。浮层不通过组件树进行渲染，部分接口（例如getRectangleById）不支持获取浮层中的组件。
*   mp4parser：一个读取、写入操作音视频文件编辑的工具。可通过ohpm install @ohos/mp4parser安装。
*   OpenGL：跨平台的图形API，用于为3D图形处理硬件指定标准的软件接口。

#### 解决方案

*   图片添加水印。
    
    *   方案一：使用overlay属性或Stack布局，将水印图文（支持emoji表情）覆盖在原图上层显示。
    *   方案二：使用图片编解码获取图片的像素数据信息，将获取的像素数据创建新的PixelMap实例应用到画布上进行绘制，最后使用getPixelMap获取绘制后的图片，并将绘制后图片写进指定文件中。
        
        OffscreenCanvas默认单位是vp，而PixelMap宽高是px，在创建OffscreenCanvas的时候将OffscreenCanvas宽高按vp和px比例缩放转换单位，即可避免绘制后的图片内存变大。
        
        完整示例可参考官方文档及示例demo。
        
    
    两种方案对比：
    
    | 方案 | 性能 | 是否修改源数据 | 适用场景 |
    | --- | --- | --- | --- |
    | 方案一 | 在UI层进行布局操作，使用简单，性能较好。 | 不会修改图像源数据。如果用户保存图片，水印不会被保存。 | 1. 图像原始数据不能被修改的场景； 2. 图片不需要保存的场景，如数据预览等。 |
    | 方案二 | 需要对图片进行编解码和像素数据处理，尤其是在处理大图片或多张图片时，性能开销较大。 | 水印会嵌入到图片的像素数据中，会修改图像原始数据，生成新的图片文件，水印会永久保存在图片中。 | 适用于需要将水印永久保存在图片中的场景，如版权保护、标记等。 |
    
*   视频添加水印。
    
    *   方案一：通过Stack组件或overlay属性实现图片水印效果（支持emoji表情），使用第三方库mp4parser调用FFmpeg命令合成加水印的视频。完整示例可以参考视频静态水印添加。
    *   方案二：通过Drawing模块绘制水印，使用glTexImage2D方法将水印纹理（支持emoji表情）与视频纹理绑定完成水印添加，最终通过XComponent进行显示。完整示例可参考视频添加水印。
        
        OH\_Drawing\_TypographyHandlerAddText接口中入参为char\*，只能输入单字节编码表示的emoji表情，不可以传入u16\_string表示的emoji表情。
        
    
    两种方案对比：
    
    | 方案 | 是否修改源数据 | 适用场景 |
    | --- | --- | --- |
    | 方案一 | 水印会嵌入到视频文件中，会修改图像原始数据，生成新的视频文件，水印会永久保存在视频中。 | 适用于需动态调整水印位置（如用户拖拽）、视频编辑类应用（如添加多个贴纸/文字）等。 |
    | 方案二 | 支持修改，可以跟具体场景决定是否修改。 | 适用场景广泛。如添加时间、视频弹幕等。 |