前端上传图片添加水印

在最近 haoyo择校 功能中,需要上传各个高校的招生计划图片;为申明版权,故需要在上传图片时添加水印。

技术栈:

vue2.x+element-ui+more...

实现思路:

  1. 利用 element-ui 的 upload 组件,监听http-request事件,获取到上传的文件信息。
  2. 将获取到的文件信息file, 转为base64格式。
  3. 将base64格式的图片转为canvas格式,并获取到canvas的图片对象。
  4. 给canvas图层添加水印。
  5. 将canvas图层转为图片格式(.jpg, .png….)。
  6. 将图片转为文件格式去上传。

代码示例:

入口方法

beforeUpload(file) {
  console.log(file)
  return new Promise((resolve, reject) => {
    //把文件转换为base64
    this.fileByBase64(file, async (base64) => {   // 1.调用方法1: 把文件转换为base64字符串
      // 把文件转换为Canvas
      let tempCanvas = await this.imgToCanvas(base64) // 2. 调用方法2:把base64转换为Canvas
      // 把水印写入
      const canvas = this.addWatermark(tempCanvas, '考研公众号:HaoYo') //3.调用方法3: 写入水印到Canvas
      // canvas转成img
      const img = this.convasToImg(canvas, file.type) //4. 调用方法4:把Canvas转换为image文件
      //被canvas转换为文件
      let newFile = this.base64ToFile(img.src, file.name) //5.调用方法5:被image转换为File文件
      resolve(newFile)
    })
  })
},

文件转base64

/**
 * 文件转base64
 * @param  file 文件流
 * @param  callback 回调函数
 */
fileByBase64(file, callback){
  let reader = new FileReader();
  // 传入一个参数对象即可得到基于该参数对象的文本内容
  reader.readAsDataURL(file);
  reader.onload = function (e) {
    // target.result 该属性表示目标对象的DataURL
    callback(e.target.result)
  };
},

Base64转成canvas

/**
 * Base64转成canvas
 * @param  base64
 */
async imgToCanvas(base64) {
  // 创建img元素
  const img = document.createElement('img')
  img.setAttribute('src', base64)
  await new Promise((resolve) => (img.onload = resolve))
  // 创建canvas DOM元素,并设置其宽高和图片一样
  const canvas = document.createElement('canvas')
  console.log(img.height)
  console.log(img.width)
  canvas.width = img.width
  canvas.height = img.height
  // 坐标(0,0) 表示从此处开始绘制,相当于偏移。
  canvas.getContext('2d').drawImage(img, 0, 0)
  return canvas
},

给canvas添加水印

/**
 * canvas添加水印
 * @param  canvas 对象
 * @param text 水印文字
 */
addWatermark(canvas, text) {
  const ctx = canvas.getContext('2d')
  ctx.fillStyle = '#aaa'
  ctx.textBaseline = 'middle'
  ctx.font = (ctx.canvas.width / 20) + 'px Arial'
  ctx.textAlign = 'center'
  ctx.textBaseline = 'middle'
  // ctx.rotate(45);
  // ctx.rotate((45 * Math.PI) / 180);
  ctx.fillText(text, canvas.width / 2, canvas.height / 2)
  return canvas
},

canvas转成img

/**
 * canvas转成img
 * @param {canvas对象} canvas
 */
convasToImg(canvas, type) {
  // 新建Image对象,可以理解为DOM
  let image = new Image()
  // canvas.toDataURL 返回的是一串Base64编码的URL
  // 指定格式 PNG
  image.src = canvas.toDataURL(type)
  return image
},

将img图片转为file类型的文件(用于上传)

/**
 * @param urlData  base64
 * @param fileName 文件名称
 * @returns {File}
 */
base64ToFile(urlData, fileName) {
  let arr = urlData.split(',');
  let mime = arr[0].match(/:(.*?);/)[1];
  let bytes = atob(arr[1]); // 解码base64
  let n = bytes.length
  let ia = new Uint8Array(n);
  while (n--) {
    ia[n] = bytes.charCodeAt(n);
  }
  return new File([ia], fileName, { type: mime });
},

最后图片,就开开心心的被加上水印了呀~
图片示例1
图片示例2

created_at:zhanghaoran’s blog 2022-04-27

原文地址:https://blog.zhanghaoran.ren/article/html/QianDuanShangChuanTuPianTianJiaShuiYin.html

### 实现前端上传图片添加满屏水印的Java与MinIO方案 在图片上传过程中,前端通常负责接收用户上传的原始文件,而添加满屏水印的逻辑则主要由后端实现。后端接收图片后,使用`BufferedImage`和`Graphics2D`对图片进行处理,通过循环绘制水印文字,使其铺满整个图像区域,最后通过MinIO客户端将处理后的图片上传至对象存储服务[^1]。 #### 图片处理:添加满屏水印 使用`BufferedImage`和`Graphics2D`可以实现对图片的绘制操作。通过设置水印文字的字体、颜色、透明度等属性,并结合嵌套循环控制横向和纵向的绘制位置,使水印文字均匀分布在图像的各个区域,达到铺满效果。 ```java import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.IOException; public class FullWatermarkHandler { public static ByteArrayOutputStream addFullWatermark(BufferedImage originalImage, String watermarkText) throws IOException { BufferedImage bufferedImage = new BufferedImage( originalImage.getWidth(), originalImage.getHeight(), BufferedImage.TYPE_INT_RGB); Graphics2D g = bufferedImage.createGraphics(); g.drawImage(originalImage, 0, 0, null); g.setColor(new Color(211, 211, 211)); // 浅灰色 g.setFont(new Font("Arial", Font.ITALIC, 36)); g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.3f)); // 设置透明度 FontMetrics fontMetrics = g.getFontMetrics(); int textWidth = fontMetrics.stringWidth(watermarkText); int textHeight = fontMetrics.getHeight(); int xGap = textWidth + 50; int yGap = textHeight + 50; for (int y = yGap / 2; y < originalImage.getHeight(); y += yGap) { for (int x = xGap / 2; x < originalImage.getWidth(); x += xGap) { g.drawString(watermarkText, x, y); } } g.dispose(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); ImageIO.write(bufferedImage, "jpg", outputStream); return outputStream; } } ``` #### MinIO上传处理后的图片添加水印后的图片上传至MinIO,需要构建`MinioClient`实例,并使用`putObject`方法上传字节流。上传前需确保目标存储桶存在,并设置正确的访问权限。 ```java import io.minio.MinioClient; import io.minio.PutObjectArgs; import java.io.ByteArrayInputStream; public class MinIOUploader { public static String uploadWatermarkedImage(byte[] imageBytes, String bucketName, String objectName) throws Exception { MinioClient minioClient = MinioClient.builder() .endpoint("https://minio.example.com") .credentials("YOUR_ACCESS_KEY", "YOUR_SECRET_KEY") .build(); minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .stream(new ByteArrayInputStream(imageBytes), imageBytes.length, -1) .contentType("image/jpeg") .build() ); return "https://" + bucketName + ".minio.example.com/" + objectName; } } ``` #### 完整上传流程整合 从前端接收图片上传请求后,后端将其转换为`BufferedImage`对象,调用`addFullWatermark`方法添加水印,再通过`uploadWatermarkedImage`上传至MinIO。以下是一个完整的上传处理示例: ```java import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.InputStream; public class ImageUploadHandler { public static String handleUpload(InputStream inputStream, String watermarkText, String bucketName, String objectName) throws Exception { BufferedImage originalImage = ImageIO.read(inputStream); ByteArrayOutputStream watermarkedStream = FullWatermarkHandler.addFullWatermark(originalImage, watermarkText); return MinIOUploader.uploadWatermarkedImage(watermarkedStream.toByteArray(), bucketName, objectName); } } ``` 前端上传图片时,只需将图片文件作为输入流传递给`handleUpload`方法,并指定水印内容、存储桶名称和对象名称,即可完成自动添加满屏水印上传至MinIO的操作。 ---
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值