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工程。

效果图:


相关推荐
qizayaoshuap8 分钟前
# [特殊字符] 指南针 — 鸿蒙ArkTS方向计算与方位跟踪系统
华为·harmonyos
达子66625 分钟前
第5章_图解harmonyos Ability基础知识
华为·harmonyos
国服第二切图仔27 分钟前
02-breakpoint-system
运维·harmonyos
Helen_cai40 分钟前
EntryAbility 全局初始化 + 网络请求 HttpUtil 完整源码
网络·华为·harmonyos
SuperHeroWu743 分钟前
【HarmonyOS AI】DevEco CLI、Skills、知识库运用AI Coding提效详解
人工智能·华为·harmonyos
熊猫钓鱼>_>1 小时前
ArkUI 动画实战:从理论到交互,构建流畅的鸿蒙动效体验
华为·架构·交互·harmonyos·arkts·arkui·native
翰德恩咨询1 小时前
华为DSTE咨询洞察:如何撬动文化与氛围以支撑战略落地
华为·文化与氛围
Catrice01 小时前
HarmonyOS ArkTS 实战:实现一个校园宿舍电费查询与分摊应用
华为·harmonyos
2301_768103491 小时前
HarmonyOS趣味相机实战第31篇:图片文档List、详情弹层与删除状态闭环
list·harmonyos·arkts·状态管理·arkui
woshihuanglaoshi2 小时前
数据迁移与版本管理 - Flutter在鸿蒙平台实现数据库升级策略
数据库·学习·flutter·华为·harmonyos·鸿蒙·鸿蒙系统