功能介绍

对图片生成图片水印或者文字水印 ,用户可以自定义自己的图片水印

思路就是将文字和图片水印合成到一张图片上面去,前台展示合成效果

后台合成后保存到cos上面,并在数据库保存相关信息,方便用户下次引用

前台样式


后端代码

接参DTO


@Data
public class WatermarkTemplateDTO extends BasePageParamDTO{/*** 主键ID*/@ApiModelProperty(value="主键ID")private Long id;/*** 用户名*/@ApiModelProperty(value="用户名")private Long userId;/*** 水印名称*/@ApiModelProperty(value="水印名称")private String watermarkName;/*** 合成后的水印图片地址*/@ApiModelProperty(value="合成后的水印图片地址")private String watermarkUrl;/*** 素材图片URL地址*/@ApiModelProperty(value="素材图片URL地址")private String picUrl;/*** 图片透明度*/@ApiModelProperty(value="图片透明度")private Integer picOpacity;/*** 图片左边距*/@ApiModelProperty(value="图片左边距")private Integer picLeft;/*** 图片上边距*/@ApiModelProperty(value="图片上边距")private Integer picTop;/*** 图片宽度*/@ApiModelProperty(value="图片宽度")private Integer picWidth;/*** 图片高度*/@ApiModelProperty(value="图片高度")private Integer picHeight;/*** 水印文字*/@ApiModelProperty(value="水印文字")private String watermarkText;/*** 文字透明度*/@ApiModelProperty(value="文字透明度")private Float textOpacity;/*** 文字字体大小*/@ApiModelProperty(value="文字字体大小")private Integer textSize;/*** 文字字体颜色*/@ApiModelProperty(value="文字字体颜色")private String textColor;/*** 文字位置-距离图片的左边距*/@ApiModelProperty(value="文字位置-距离图片的左边距")private Integer textLeft;/*** 文字位置-距离图片的上边距*/@ApiModelProperty(value="文字位置-距离图片的上边距")private Integer textTop;/*** 文字字体*/@ApiModelProperty(value="文字字体")private String textFont;/*** 图片翻转,0:不翻转  1: 水平翻转  2 : 垂直翻转*/@ApiModelProperty(value="图片翻转,0:不翻转  1: 水平翻转  2 : 垂直翻转")private Integer picTurn;/*** 图片旋转角度*/@ApiModelProperty(value="图片旋转角度")private Integer picRotate;/*** 创建时间*/@ApiModelProperty(value="创建时间")private Date createDate;}

数据库实体类

/*** 水印模板表*/
@ApiModel(value = "com-menglar-soap-item-pojo-mysql-WatermarkTemplate")
@Data
@NoArgsConstructor
@TableName(value = "item_watermark_template")
public class WatermarkTemplate implements Serializable {/*** 主键ID*/@ApiModelProperty(value = "主键ID")private Long id;/*** 用户名*/@ApiModelProperty(value = "用户名")private Long userId;/*** 水印名称*/@ApiModelProperty(value = "水印名称")private String watermarkName;/*** 合成后的水印图片地址*/@ApiModelProperty(value = "合成后的水印图片地址")private String watermarkUrl;/*** 素材图片URL地址*/@ApiModelProperty(value = "素材图片URL地址")private String picUrl;/*** 图片透明度*/@ApiModelProperty(value = "图片透明度")private Integer picOpacity;/*** 图片左边距*/@ApiModelProperty(value = "图片左边距")private Integer picLeft;/*** 图片上边距*/@ApiModelProperty(value = "图片上边距")private Integer picTop;/*** 图片宽度*/@ApiModelProperty(value = "图片宽度")private Integer picWidth;/*** 图片高度*/@ApiModelProperty(value = "图片高度")private Integer picHeight;/*** 水印文字*/@ApiModelProperty(value = "水印文字")private String watermarkText;/*** 文字透明度*/@ApiModelProperty(value = "文字透明度")private Float textOpacity;/*** 文字字体大小*/@ApiModelProperty(value = "文字字体大小")private Integer textSize;/*** 文字字体颜色*/@ApiModelProperty(value = "文字字体颜色")private String textColor;/*** 文字位置-距离图片的左边距*/@ApiModelProperty(value = "文字位置-距离图片的左边距")private Integer textLeft;/*** 文字位置-距离图片的上边距*/@ApiModelProperty(value = "文字位置-距离图片的上边距")private Integer textTop;/*** 文字字体*/@ApiModelProperty(value = "文字字体")private String textFont;/*** 图片翻转,0:不翻转  1: 水平翻转  2 : 垂直翻转*/@ApiModelProperty(value = "图片翻转,0:不翻转  1: 水平翻转  2 : 垂直翻转")private Integer picTurn;/*** 图片旋转角度*/@ApiModelProperty(value = "图片旋转角度")private Integer picRotate;/*** 创建时间*/@ApiModelProperty(value = "创建时间")private Date createDate;private static final long serialVersionUID = 1L;
}

水印生成方法

/*** 上传水印模板* @param wtDto* @return*/@Overridepublic Result uploadWatermarkPic(WatermarkTemplateDTO wtDto) {if (StringUtils.isBlank(wtDto.getPicUrl()) && StringUtils.isBlank(wtDto.getWatermarkText())) {throw new BusinessException("素材图片/水印文字不能为空");}try {BufferedImage output = new BufferedImage(800, 800, BufferedImage.TYPE_INT_ARGB);Graphics2D g2 = output.createGraphics();output = g2.getDeviceConfiguration().createCompatibleImage(800, 800, Transparency.TRANSLUCENT);g2 = output.createGraphics();//调制透明度for (int j1 = output.getMinY(); j1 < output.getHeight(); j1++) {for (int j2 = output.getMinX(); j2 < output.getWidth(); j2++) {int rgb = output.getRGB(j2, j1);rgb = ((0 * 255 / 10) << 24) | (rgb & 0x00ffffff);output.setRGB(j2, j1, rgb);}}//1、先画一张完全透明的背景图g2.drawImage(output, 0, 0, 800, 800, null);//图片水印if(StringUtils.isNotBlank(wtDto.getPicUrl())){log.info("图片参数:opacity:{},height:{},picLeft:{},picTop:{},picWidth:{}", wtDto.getPicOpacity(), wtDto.getPicHeight(), wtDto.getPicLeft(), wtDto.getPicTop(), wtDto.getPicWidth());Integer alpha = wtDto.getPicOpacity();if(alpha == null|| wtDto.getPicOpacity() == null|| wtDto.getPicHeight() == null|| wtDto.getPicLeft() == null|| wtDto.getPicTop() == null|| wtDto.getPicWidth() == null){throw new BusinessException("图片参数错误!");}//检查透明度是否越界if (alpha < 0) {alpha = 0;} else if (alpha > 10) {alpha = 10;}InputStream inputStream = CompositeWatermarkUtil.downloadFile(wtDto.getPicUrl());BufferedImage image = ImageIO.read(inputStream);//2、再画水印素材图片g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,alpha.floatValue()/10));g2.drawImage(image, equalRatioCalculation(wtDto.getPicLeft()), equalRatioCalculation(wtDto.getPicTop()), equalRatioCalculation(wtDto.getPicWidth()), equalRatioCalculation(wtDto.getPicHeight()), null);}//文字水印if (StringUtils.isNotBlank(wtDto.getWatermarkText())) {log.info("文字参数:textLeft:{},TextLeft:{},TextOpacity:{},TextColor:{},TextSize:{},TextFont:{}", wtDto.getTextLeft(), wtDto.getTextTop(), wtDto.getTextOpacity(), wtDto.getTextColor(), wtDto.getTextSize(), wtDto.getTextFont());if(wtDto.getTextLeft() == null|| wtDto.getTextTop() == null|| wtDto.getTextOpacity() == null|| wtDto.getTextColor() == null|| wtDto.getTextSize() == null|| wtDto.getTextFont() == null){throw new BusinessException("文字参数错误!");}try {String[] availableFontFamilyNames = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();log.info("测试环境字体列表数组为:" + availableFontFamilyNames);if(availableFontFamilyNames != null){log.info("测试环境字体列表数组长度:" + availableFontFamilyNames.length);log.info("测试环境字体列表获取首个:" + availableFontFamilyNames[0]);}for(String s : availableFontFamilyNames){log.info(s);}} catch (Exception e) {e.printStackTrace();}//3、画文字String textColor = wtDto.getTextColor();//字体Font font = new Font(wtDto.getTextFont(), Font.BOLD, wtDto.getTextSize());//水印字体,大小//颜色Color color = new Color(Integer.decode(textColor));g2.setFont(font);g2.setColor(color);g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, wtDto.getTextOpacity()));log.info("画文字开始");g2.drawString(wtDto.getWatermarkText(), equalRatioCalculation(wtDto.getTextLeft()), equalRatioCalculation(wtDto.getTextTop()));log.info("画文字结束");}//上传合成的水印ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();ImageIO.write(output, "png", arrayOutputStream);byte[] bytes = arrayOutputStream.toByteArray();ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);Long userId = SecurityUtils.getUserId();//如果是编辑后保存,则有水印模板URL,使用原水印模板地址,新水印模板会替换掉旧的if (BeanUtil.isNotEmpty(wtDto.getId())) {WatermarkTemplate watermarkTemplate = watermarkTemplateMapper.selectOne(Wrappers.lambdaQuery(WatermarkTemplate.class).eq(WatermarkTemplate::getId, wtDto.getId()));String key = cosClient.buildKey(watermarkTemplate.getWatermarkUrl());cosClient.uploadFile(byteArrayInputStream, key);BeanUtil.copyProperties(wtDto, watermarkTemplate, CopyOptions.create().setIgnoreError(true).ignoreNullValue());watermarkTemplateMapper.updateByPrimaryKeySelective(watermarkTemplate);} else {//没有水印模板URL则是新增水印模板,生成新的String key = cosClient.buildStoragePath(FileTypeEnum.IMAGE, "png", userId);String watermarkTemplateUrl = cosClient.uploadFile(byteArrayInputStream, key);WatermarkTemplate watermarkTemplate = new WatermarkTemplate();BeanUtil.copyProperties(wtDto, watermarkTemplate, CopyOptions.create().setIgnoreError(true).ignoreNullValue());watermarkTemplate.setWatermarkUrl(watermarkTemplateUrl);watermarkTemplate.setCreateDate(new Date());watermarkTemplate.setUserId(userId);watermarkTemplateMapper.insert(watermarkTemplate);}return Result.ok(StatusCode.SUCCESS, "保存水印成功");} catch (Exception e) {e.printStackTrace();return Result.errorMessage("保存水印失败,系统异常", StatusCode.FAILURE.code());}}/*** 水印素材位置等比例计算* @param value* @return*/private Integer equalRatioCalculation(Integer value){BigDecimal waterSize = new BigDecimal(800);//水印最大尺寸BigDecimal editerSize = new BigDecimal(500);//前端编辑框尺寸BigDecimal ratio = editerSize.divide(waterSize);BigDecimal valBd = new BigDecimal(value);BigDecimal finalVal = valBd.divide(ratio);int i = finalVal.intValue();return i;}

记录一个制作图片水印的功能相关推荐

  1. 服务器文件如何防止盗链,怎么在Apache服务器中实现一个防止图片盗链功能

    怎么在Apache服务器中实现一个防止图片盗链功能 发布时间:2020-12-15 16:06:51 来源:亿速云 阅读:104 作者:Leah 这篇文章将为大家详细讲解有关怎么在Apache服务器中 ...

  2. 【python 水印生成器】python制作图片水印

    制作一个水印生成器,方便训练水印图片数据采集. 图片水印生成器,可以给指定图片文件或者目录添加水印,水印支持自定义文本.位置.颜色.大小. # -*- encoding=utf-8 -*- impor ...

  3. 利用Python自制一个批量图片水印添加器

    前段时间写了个比较简单的批量水印添加的python实现方式,将某个文件夹下面的图片全部添加上水印. 今天正好有时间就做了一个UI应用的封装,这样不需要知道python直接下载exe的应用程序使用即可. ...

  4. 周末自制了一个批量图片水印添加器!

    前段时间写了个比较简单的批量水印添加的python实现方式,将某个文件夹下面的图片全部添加上水印. [阅读全文] 今天正好有时间就做了一个UI应用的封装,这样不需要知道python直接下载exe的应用 ...

  5. canvas制作图片水印

    概述 以前都是后端同学来处理的,现在有了canvas, 前端同学也可以做出水印来了, 而且要比后端同学做的要精美漂亮. 制作水印的几个步骤 在html中准备好canvas标签 将图片绘制到canvas ...

  6. unity实现图片轮播效果_Unity 制作图片轮播功能

    功能:自动播放移动 首尾相接  鼠标移到图片上 时 移动停止并 该图片变大  鼠标离开图片恢复原形 轮播效果继续 效果如下 界面布局 大体是这个样子 scrollView就是一个底板带Image组件 ...

  7. Unity 制作图片轮播功能

    功能:自动播放移动 首尾相接  鼠标移到图片上 时 移动停止并 该图片变大  鼠标离开图片恢复原形 轮播效果继续 效果如下 界面布局 大体是这个样子 scrollView就是一个底板带Image组件 ...

  8. ps从零开始之制作图片水印制作网站水印

    原文地址:http://xiqingchun.com/forum.php? ... 1&extra=#pid297 我们经常需要给喜爱的图片加上具有自己特色的水印标志,以对这个图片宣誓我们对这 ...

  9. python给图片添加水印图片_使用Python编写批量添加图片水印程序

    文章目录 一.为什么要为图片添加水印 二.利用Python为图片添加水印 遍历文件夹下所有图片文件 三.利用QT for Python制作图片水印添加程序 一.为什么要为图片添加水印 在互联网写文章最 ...

最新文章

  1. mutt使用小技巧 指定发件人 添加附件
  2. 用实例给新手讲解RSA加密算法
  3. Slab,小对象也能搞出大事情
  4. eplan模板_EPLAN之3D箱柜清单自动生成
  5. OpenGL绘制二个不同颜色的三角形的实例
  6. 【Numpy学习记录】np.transpose讲解
  7. ORACLE中创建如何创建表,并设置结构和默认值
  8. WinForm 之 程序退出
  9. Docker 安装 ES 7.7.0 及 Head、Kibana、IK分词器、Logstash、Filebeat 插件
  10. Keras及其前端配置
  11. ctfmon是什么启动项_我MSCONFIG启动项里面没有ctfmon怎么处理?
  12. plsql 安装使用教程
  13. matlab时域数据转频域,从时域和频域来解析傅里叶变换(含代码和性质)
  14. photoshop设置A4纸张大小
  15. 易灵思FPGA-报告总结篇
  16. keepalived+nginx,haproxy
  17. chipping rate码片速率
  18. 了解C语言中的pipe()系统调用
  19. 从单个系统到云翼一体化支撑,京东云DevOps推进中的一波三折
  20. Recycleview 虐我千百遍 我待Recycleview如初恋

热门文章

  1. 什么是驱动程序,为什么有些设备需要安装驱动程序,有些却不需要
  2. ida pro 最新版下载 使用基础 快捷键
  3. Xpath工具 Chrome插件 XPath Helper下载安装与使用
  4. Wget下载整个网站(包含图片/JS/CSS)
  5. 完美通行证身份证号格式_使用通行证js进行节点js身份验证
  6. 15 个非常棒的 CSS3 效果教程
  7. 吃惊---西昌卫星发射中心年发射能…
  8. 职称计算机考试输入破折号,电脑上破折号是哪个键
  9. 按钮,干簧管,霍尔,声音,震动,倾斜,红外开关小谈
  10. Shell脚本编写计算器代码