Use canvas to add watermark to pictures

Continued from the article "Image Processing"

The canvas element is actually a canvas, we can easily draw some text, lines, graphics, etc., and it can also draw an image rendered in an img tag on the canvas.

When we upload a file to the backend, what we get after reading the user's local file using the input tag is actually a Blob object (more precisely, a File object, a special Blob object); and displaying a picture on the page uses img tag; the drawing function is implemented with canvas.

The function of adding a watermark needs to be converted between the img tag, canvas, and Blob object. This work can be done through some APIs:

We can read the picture blob locally, then render it to the img tag, use canvas to draw the img content and draw the watermark content to the canvas, and then convert the canvas content into a blob object and upload it to the server, thus fully realizing the function of picture + watermark.

1. Locally read the image file and render it to the img tag

Reading the image file locally will get a Blob object. We can use the FileReader.readAsDataURL method to read the content of the Blob and get a Base64-encoded file content. We can assign the content to img.src to render it on the browser. local images. Of course, img does not have to be rendered to the DOM tree.

The read operation is an asynchronous operation, and the load event will be triggered when the read is completed. In order to facilitate subsequent calls, we can wrap this operation with a Promise, and finally return a Promise object.

function blobToImg (blob) {
  return new Promise((resolve, reject) => {
    let reader = new FileReader()
    reader.addEventListener('load', () => {
      let img = new Image()
      img.src = reader.result
      img.addEventListener('load', () => resolve(img))
    })
    reader.readAsDataURL(blob)
  })
}

2. Draw the content of the img tag to the canvas canvas

Call the drawImage method of the canvas context object of the canvas element to draw the img content to the canvas.


function imgToCanvas (img) {
  let canvas = document.createElement('canvas')
  canvas.width = img.width
  canvas.height = img.height
  let ctx = canvas.getContext('2d')
  ctx.drawImage(img, 0, 0)
  return canvas
}

The drawImage method can pass in multiple parameters to define the range of the drawn image. The 0, 0 passed in here defines the drawing from the upper left corner of the image. Later, you can continue to pass in two parameters to define the drawing end of the image, but here The entire picture must be drawn to the canvas, so the default value can be used.

3. Draw a watermark on the canvas and convert it to a Blob object

When uploading pictures, we usually use FormData, and the picture file is placed in FormData in the form of a Blob object, so we need to convert the canvas to a Blob for file upload and other operations. Using the HTMLCanvasElement.toBlob method:

function watermark (canvas, text) {
  return new Promise((resolve, reject) => {
    let ctx = canvas.getContext('2d')
    // 设置填充字号和字体,样式
    ctx.font = "24px 宋体"
    ctx.fillStyle = "#FFC82C"
    // 设置右对齐
    ctx.textAlign = 'right'
    // 在指定位置绘制文字,这里指定距离右下角20坐标的地方
    ctx.fillText(text, canvas.width - 20, canvas.height - 20)
    canvas.toBlob(blob => resolve(blob))
  })
}

4. Complete interface for adding watermark to pictures

Combining the above three steps, adding a watermark from an image is fully realized. The following is a simple usage example: select an image file locally, add a watermark, and preview the watermarked image under the incoming dom element picture.


function imgWatermark (dom, text) {
  let input = document.createElement('input')
  input.setAttribute('type', 'file')
  input.setAttribute('accept', 'image/*')
  input.onchange = async () => {
    let img = await blobToImg(input.files[0])
    let canvas = imgToCanvas(img)
    let blob = await watermark(canvas, text)
    // 此处将Blob读取到img标签,并在dom内渲染出来;如果是上传文件,可以将blob添加到FormData中
    let newImage = await blobToImg(blob)
    dom.appendChild(newImage)
  }
  input.click()
}

Add a div element with the id of container to the page, and then call it as follows:


let dom = document.querySelector('#container')
imgWatermark(dom, '水印文字')

In this way, the watermark effect is completely added to the picture. Let's take a look at the actual effect.

Before adding watermark:

 

After adding watermark (watermark content: "watermark added by canvas"):

V. Summary

This article only introduces the simple implementation of image + watermark text, but some of the interfaces involved are actually very useful. For example, sometimes a function encountered is the preview and clipping of uploaded avatars. At this time, you can use FileReader to read the preview of the file content, and use CanvasRenderingContext2D.drawImage to realize the clipping function.

Guess you like

Origin blog.csdn.net/baidu_38493460/article/details/130849794