HarmonyOS:照片添加多样式的水印信息

前言:ArkTS语言中照片添加水印常见用法总结和整理,目前常见的旋转铺满全屏水印,区域水印,底部带背景色的水印,以及图文混排的水印。

这篇文章对各种用法都进行了归纳整理。

HomePage示例图片显示

复制代码
Button('Single: Diagonal Watermark')
          .onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.Default))
          .height(30)
        Button('Single: Top-Left Watermark')
          .onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.LeftTop))
          .height(30)
        Button('Single: Bottom-Right Watermark')
          .onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.RightBottom))
          .height(30)
        Button('Multiple: Diagonal Watermark')
          .onClick(() => this.handleWaterMarkAddition(LXWaterMarkStyle.MoreDefault, true))
          .height(30)

各种样式水印添加方法如上所示。

核心的代码封装类:

复制代码
LXWaterMarkMgr.ets

水印信息封装类:

复制代码
LXWaterMarkInfo

水印信息配置类:

复制代码
LXWaterMarkFillOption

水印样式配置枚举:

复制代码
LXWaterMarkStyle

照片信息类:

复制代码
LXImagePixelMap

水印绘制器抽象:

复制代码
LXWaterMarkDrawer

好处是,所有的水印都继承于LXWaterMarkDrawer的方法实现,简单明了。

复制代码
// 水印绘制器抽象
abstract class LXWaterMarkDrawer {
  abstract draw(
    offScreenCanvas: OffscreenCanvasRenderingContext2D,
    imagePixelMap: LXImagePixelMap,
    waterMarkInfoList: LXWaterMarkInfo[],
    option: LXWaterMarkFillOption,
    scale: number,
    canvasSize?:SizeOptions
  ): Promise<void>;
}
// 默认水印绘制器
class DefaultWaterMarkDrawer extends LXWaterMarkDrawer {
  async draw(
    iOffScreenContext: OffscreenCanvasRenderingContext2D,
    imagePixelMap: LXImagePixelMap,
    waterMarkInfoList: LXWaterMarkInfo[],
    option: LXWaterMarkFillOption,
    scale: number,
    canvasSize?:SizeOptions
  ): Promise<void> {
    const waterInfo = waterMarkInfoList.length>0?waterMarkInfoList[0]:'';
    const waterMarkInfo = (waterInfo&&waterInfo.content.length>0)?waterInfo.content:'水印信息';
    const waterMarkW = 120;
    const waterMarkH = 120;
    const rotationAngle = -30;

    iOffScreenContext.font = `${16 * scale}vp`;
    const iWidth = canvasSize?canvasSize.width: DisplayUtil.getWidth();
    const iHeight = canvasSize?canvasSize.height: DisplayUtil.getHeight();

    const colCount = Math.ceil(iWidth as number / waterMarkW);
    const rowCount = Math.ceil(iHeight as number / waterMarkH);

    for (let col = 0; col < colCount; col++) {
      for (let row = 0; row <= rowCount; row++) {
        iOffScreenContext.save();
        iOffScreenContext.translate(col * waterMarkW, row * waterMarkH);
        iOffScreenContext.rotate((rotationAngle * Math.PI) / 180);
        iOffScreenContext.fillText(waterMarkInfo, 0, 0);
        iOffScreenContext.restore();
      }
    }
  }
}

核心的水印信息绘制代码如下:

1.创建画布

2.绘制原始图片

3.设置画布的属性

4.绘制水印(通过水印绘制器工厂get到每个样式的绘制器进行单独绘制)

复制代码
export async function addWaterMarkWithContext(
  context: UIContext,
  imagePixelMap: LXImagePixelMap,
  waterMarkInfoList?: LXWaterMarkInfo[],
  waterMarkFillOption?: LXWaterMarkFillOption,
  customDrawer?: (ctx: OffscreenCanvasRenderingContext2D) => void
): Promise<image.PixelMap> {
  if (!context) {
    LogUtil.error('Context is undefined, returning original image');
    ToastUtil.showToast('Context为空,返回原图');
    return imagePixelMap.pixelMap;
  }
  // 创建离屏画布
  const iHeight = context.px2vp(imagePixelMap.height);
  const iWidth = context.px2vp(imagePixelMap.width);
  const offScreenCanvas = new OffscreenCanvas(iWidth, iHeight);
  const offScreenContext = offScreenCanvas.getContext('2d');

  if (!offScreenContext) {
    throw new Error('Failed to create offscreen context');
  }
  // 绘制原始图片
  offScreenContext.drawImage(imagePixelMap.pixelMap, 0, 0, iWidth, iHeight);

  // 自定义或自动水印
  if (customDrawer) {
    customDrawer(offScreenContext);
  } else if (waterMarkFillOption && waterMarkInfoList?.length) {
    const scale = await calculateImageScale(context, iWidth);
    const drawer = WaterMarkDrawerFactory.getDrawer(waterMarkFillOption.waterMartStyle);
    // 设置全局画布属性
    offScreenContext.textAlign = waterMarkFillOption.textAlign || 'left';
    offScreenContext.fillStyle = waterMarkFillOption.textFillStyle || '#A2FFFFFF';
    offScreenContext.globalAlpha = waterMarkFillOption.textGlobalAlpha || 1.0;
    //绘制水印
    await drawer.draw(offScreenContext, imagePixelMap, waterMarkInfoList, waterMarkFillOption, scale,{width:iWidth,height:iHeight});
  }

  return offScreenContext.getPixelMap(0, 0, iWidth, iHeight);
}
详细demo工程:

https://gitcode.com/luxingxing1/LightNoteBook
如有使用请注明来源,不要直接上传的官方Demo工程。

效果图:


相关推荐
左手厨刀右手茼蒿4 小时前
Flutter 三方库 k_m_logic 的鸿蒙化适配指南 - 构建声明式的业务逻辑状态机、助力鸿蒙端复杂交互流程的解耦与重构
flutter·harmonyos·鸿蒙·openharmony·k_m_logic
钛态4 小时前
Flutter 三方库 result_type 深入鸿蒙强类型返回栈跨界交互适配:肃清空指针回调与运行时崩溃、大幅增注接口安全壁垒且提升多隔离桥接数据抛出健壮性-适配鸿蒙 HarmonyOS ohos
flutter·交互·harmonyos
lxysbly4 小时前
鸿蒙街机模拟器app下载
华为·harmonyos
左手厨刀右手茼蒿4 小时前
Flutter 三方库 invertible 的鸿蒙化适配指南 - 实现极致的撤销与重做流、助力鸿蒙端高交互编辑类应用开发
flutter·harmonyos·鸿蒙·openharmony
加农炮手Jinx4 小时前
Flutter 三方库 fast_i18n 的鸿蒙化适配指南 - 掌握类型安全的国际化编译技术、助力鸿蒙应用构建全球化且极速响应的多语言交互体系
flutter·harmonyos·鸿蒙·openharmony·fast_i18n
钛态4 小时前
Flutter 三方库 test_process 的鸿蒙化适配指南 - 实现具备外部进程交互与命令行输出校验的集成测试套件、支持端侧 CLI 工具与自动化脚本协同实战
flutter·harmonyos·鸿蒙·openharmony·test_process
想你依然心痛5 小时前
HarmonyOS 5.0车机应用开发实战:基于方舟引擎的智能座舱多模态交互系统
华为·交互·harmonyos
前端郭德纲5 小时前
JavaScript原生开发与鸿蒙原生开发对比
开发语言·javascript·harmonyos