当前位置 博文首页 > 文章内容

    Canvas基本图片操作与处理

    作者: 栏目:未分类 时间:2020-09-15 15:00:41

    本站于2023年9月4日。收到“大连君*****咨询有限公司”通知
    说我们IIS7站长博客,有一篇博文用了他们的图片。
    要求我们给他们一张图片6000元。要不然法院告我们

    为避免不必要的麻烦,IIS7站长博客,全站内容图片下架、并积极应诉
    博文内容全部不再显示,请需要相关资讯的站长朋友到必应搜索。谢谢!

    另祝:版权碰瓷诈骗团伙,早日弃暗投明。

    相关新闻:借版权之名、行诈骗之实,周某因犯诈骗罪被判处有期徒刑十一年六个月

    叹!百花齐放的时代,渐行渐远!



    前言

    Canvas是H5中新增的技术,主要运用在图片的处理和动画的绘制上,随着Canvas的使用场景越来越多,了解Canvas对平时开发大有裨益,这篇文章将介绍Canvas基本图片操作与处理

     

    图片上传与绘制

    将图片上传并绘制到Canva中是最常见的Canvas的图片处理,这个上传与绘制的过程是怎么实现的呢?下面举个例子:

    <canvas id="myCanvas"></canvas>
    <input type="file" id="file">
    let upload = document.getElementById('file')
    upload.onchange = (event) => {
      let file = event.target.files[0]
      let fileReader = new FileReader()
      fileReader.onload = (e) => {
        let img = new Image()
        img.src = e.target.result
        img.onload = () => {
          let canvas = document.getElementById('myCanvas')
          canvas.width = img.width
          canvas.height = img.height
          let context = canvas.getContext('2d')
          context.drawImage(img, 0, 0)
        }
      }
      fileReader.readAsDataURL(file)
    }

    这个上传与绘制的过程可以总结为两步:

    • 通过FileReader对象将input上传的file对象转化为base64格式的图片
    • 创建Image对象,将对象绘制在canvas上

    这里为什么要将base64格式的地址复制给Image对象,然后再将Image对象绘制到Canvas上而不是直接绘制呢?
    这是因为Canvas上绘制时并不支持url作为图片源,Canvas只支持下面几种图片源:

    • Image()函数构造的或者任何<img>元素
    • <video>元素作为图片源,可以抓取当前帧作为图像
    • 另一个<canvas>元素作为源
    • 高性能位图作为图片源

    Canvas在绘图时还有一个需要注意的点就是:Canvas在绘制不同域名下的图片会出现跨域的错误,如图:

    被污染的Canvas,其实就是因为图片跨域的问题的,这时需要两步走:

    • 图片服务器响应头添加Access-Control-Allow-Origin为*或者指定域名
    • 设置Image的crossOrigin属性img.setAttribute("crossOrigin",'Anonymous')

    简单示例代码:

    let img = new Image()
    img.setAttribute("crossOrigin",'Anonymous')
    img.src = './images/avatar.jpeg'
    img.onload = () => {
      let canvas = document.getElementById('myCanvas')
      canvas.width = img.width
      canvas.height = img.height
      let context = canvas.getContext('2d')
      context.drawImage(img, 0, 0)
      console.log(canvas.toDataURL('image/png', 1.0))
    } 

    更多跨域相关内容可以看这里

     

    图片变换

    图片缩放

    Canvas中图片缩放的实际上是通过画布的缩放来达到的,因此默认的缩放中心是在画布原点(0, 0),但是一般情况下我们做缩放时都希望图片中心是缩放中心,这里有两种办法能达到图片中心作为缩放中心的缩放效果,接下来分别来看这两种办法的示例:
    第一种:

    let canvas = document.getElementById('myCanvas')
    canvas.width = img.width
    canvas.height = img.height
    let context = canvas.getContext('2d')
    context.translate(img.width / 2, img.height / 2)
    context.scale(0.5, 0.5)
    context.translate(-img.width / 2, -img.height / 2)
    context.drawImage(img, 0, 0, img.width, img.height)

    第一种方法就是画布平移,先将画布原点移到图像中心,然后再做画布缩放,再将画布平移还原,最后绘制图片,此时绘制的图片就是以图片中心做的缩放

    第二种:

    let canvas = document.getElementById('myCanvas')
    canvas.width = img.width
    canvas.height = img.height
    let context = canvas.getContext('2d')
    let paintWidth = img.width / 2
    let paintHight = img.height / 2
    let originX = 0 // 原图片X坐标
    let originY = 0 // 原图片Y坐标
    let paintX = originX + (img.width - paintWidth) / 2 // 缩放后的图片X坐标
    let paintY = originY + (img.height - paintHight) / 2 // 缩放后的图片Y坐标
    context.drawImage(img, paintX, paintY, paintWidth, paintHight)

    第二种就是最直接的计算当图片以左上角作为缩放中心,缩放后的图片位置产生的位置偏移,将位置偏移加上在进行图片绘制

    图片旋转

    Canvas的图片旋转和图片缩放一样,默认的旋转中心也是画布的原点(0, 0),此时也需要平移画布来实现图片的中心旋转,举个例子

    let img = new Image()
    img.setAttribute("crossOrigin",'Anonymous')
    img.src = './images/avatar.jpeg'
    img.onload = () => {
    let canvas = document.getElementById('myCanvas')
      canvas.width = img.width
      canvas.height = img.height
      let context = canvas.getContext('2d')
      context.translate(img.width / 2, img.height / 2)
      context.rotate(30 * Math.PI / 180)
      context.translate(-img.width / 2, -img.height / 2)
      context.drawImage(img, 0, 0, img.width, img.height)
    }

    镜像变换

    镜像变换可以以图片垂直中线为对称轴,左右镜像的变换叫水平镜像,或者水平中线为对称轴,上下镜像的变换叫垂直镜像,一般水平镜像用的比较多,这里就来看一个水平镜像的例子:

    let img = new Image()
    img.setAttribute("crossOrigin",'Anonymous')
    img.src = './images/avatar.jpeg'
    img.onload = () => {
      let canvas = document.getElementById('myCanvas')
      canvas.width = img.width
      canvas.height = img.height
      let context = canvas.getContext('2d')
      context.translate(img.width / 2, img.height / 2)
      context.scale(-1 , 1)
      context.translate(-img.width / 2, -img.height / 2)
      context.drawImage(img, 0, 0, img.width, img.height)
    }

    原图:

    水平镜像:

    镜像操作的原理其实很简单:就是将scale设置为负值,当x轴的缩放为负值时,就是水平镜像,当y轴的缩放为负值时就是垂直镜像

    对称轴翻转

    对称轴翻转指的是图片沿着左上角至右下角的对角线翻转,来看用代码Canvas是怎么实现的:

    let img = new Image()
    img.setAttribute("crossOrigin",'Anonymous')
    img.src = './images/avatar.jpeg'
    img.onload = () => {
      let canvas = document.getElementById('myCanvas')
      canvas.width = img.width
      canvas.height = img.height
      let context = canvas.getContext('2d')
      context.translate(img.width / 2, img.height / 2)
      context.scale(-1 , 1)
      context.rotate(90 * Math.PI / 180)
      context.translate(-img.width / 2, -img.height / 2)
      context.drawImage(img, 0, 0, img.width, img.height)
    }

    翻转图:

    实现原理:先做水平镜像,然后顺时针旋转90度,由于先做的水平镜像,坐标轴会被水平翻转,顺时针旋转90度实际是逆时针旋转90度

    广州vi设计公司 http://www.maiqicn.com 我的007办公资源网 https://www.wode007.com

    图片灰度

    图片的灰度效果是Canvas非常常见的一个图片处理效果,先来看实现灰度效果的代码:

    let img = new Image()
    img.setAttribute("crossOrigin",'Anonymous')
    img.src = './images/avatar.jpeg'
    img.onload = () => {
      let canvas = document.getElementById('myCanvas')
      canvas.width = img.width
      canvas.height = img.height
      let context = canvas.getContext('2d')
      context.drawImage(img, 0, 0, img.width, img.height)
      let imageData = context.getImageData(0, 0, img.width, img.height)
      let data = imageData.data
      for (let i = 0; i < data.length; i += 4) {
        let average = (data[i] + data[i + 1] + data[i + 2]) / 3
        data[i] = average
        data[i + 1] = average
        data[i + 2] = average
      }
      context.putImageData(imageData, 0, 0)
    }

    灰度效果图:


    实现思路:

    • 先将图片绘制在canvas上
    • 利用getImageData方法获取每个像素点的rgb值
    • 求出每个像素点的rgb平均值,然后重新赋值
    • 利用putImageData将重新计算的imageData对象绘制到图片上

    这里可能会有人对getImageData和putImageData这两个api不是很熟悉,想要了解这个两个api的可以点getImageDataputImageData