利用画布canvas,实现图片编辑马赛克效果。canvas.putImageData()实现不一样的马赛克

接到需求修改马赛克的样式,不知所措~,开始研究,实现效果如下图

在这里插入图片描述
重点都在代码注释中,就不多解释了

	drawImageToCanvas(image) {
      const canvas = document.querySelector('#canvas')
      const ctx = canvas.getContext('2d')
      return new Promise((resolve, reject) => {
        image.onload = function() {
          while (this.width > 1360 || this.height > 780) {
            this.width = this.width * 0.8 //图片的大小
            this.height = this.height * 0.8
          }
          canvas.width = this.width
          canvas.height = this.height
          ctx.drawImage(this, 0, 0, this.width, this.height)//宽高为图片尺寸,防止上传的图片大小使图片失真
          resolve(ctx)//返回画布对象信息
        }
      })
    },
	toEditImage() {//画布初始化
      this.editDialogVisible = true
      this.isEditImage = true
      const image = new Image()//创建图片信息
      image.crossOrigin = 'Annoymous'
      image.src = this.previewImgObj.fileUrl
      const that = this
      setTimeout(() => {//延迟开启画布
        that.drawImageToCanvas(image).then((ctx) => {//封装的方法,开启canvas
          canvas.onmousedown = function(ev){//通过鼠标事件来实现打码效果
            var quan = 9; //马赛克的大小
            var num = 3; //一次操作包含马赛克的个数
            var ev=ev || window.event;
            var dx = ev.layerX //鼠标中心位置
            var dy = ev.layerY //鼠标中心位置
            drawLine(image,dx,dy);
            document.onmousemove = function(ev){
              // console.log(canvas.offsetTop,canvas.offsetLeft,ev.layerX);
              var ev = ev || window.event;
              var mx = ev.layerX
              var my = ev.layerY
              if(Math.pow(dx-mx,2)+Math.pow(dy-my,2)>= Math.pow(quan*num,2)){  //(quan*马赛克个数*2)的平方
                drawLine(image,mx,my);
                dx = mx;
                dy = my;
              }
            };
            document.onmouseup = function(){
              that.dataURL = document.querySelector('#canvas').toDataURL('image/png')
              document.onmousemove = null;
              document.onmouseup = null;
            };
            function drawLine(obj,dx,dy){
              //原始图像
              var originalImgData = ctx.getImageData(0,0,canvas.width,canvas.height);
              var originalPxData = originalImgData.data;//获取图片像素信息
              for(var i=dx-quan*num;i<dx+quan*num;i = i+2*quan+1){//通过循环修改像素颜色
                  for(var j=dy-quan*num;j<dy+quan*num;j = j+2*quan+1){
                    //中心点(dx,dy)
                    if(!((i==dx-quan*num&&j==dy-quan*num)||(i==dx-quan*num&&j==dy-quan*num+2*quan+1)||
                      (i==dx-quan*num&&j==dy-quan*num+4*quan+2)||(i==dx-quan*num&&j==dy-quan*num+12*quan+6)||
                      (i==dx-quan*num&&j==dy-quan*num+14*quan+7)||(i==dx-quan*num&&j==dy-quan*num+16*quan+8)||
                      (i==dx-quan*num+16*quan+8&&j==dy-quan*num)||(i==dx-quan*num+16*quan+8&&j==dy-quan*num+2*quan+1)||
                      (i==dx-quan*num+16*quan+8&&j==dy-quan*num+4*quan+2)||(i==dx-quan*num+16*quan+8&&j==dy-quan*num+12*quan+6)||
                      (i==dx-quan*num+16*quan+8&&j==dy-quan*num+14*quan+7)||(i==dx-quan*num+16*quan+8&&j==dy-quan*num+16*quan+8)||
                      (i==dx-quan*num+2*quan+1&&j==dy-quan*num)||(i==dx-quan*num+4*quan+2&&j==dy-quan*num)||
                      (i==dx-quan*num+12*quan+6&&j==dy-quan*num)||(i==dx-quan*num+14*quan+7&&j==dy-quan*num)||
                      (i==dx-quan*num+2*quan+1&&j==dy-quan*num+16*quan+8)||(i==dx-quan*num+4*quan+2&&j==dy-quan*num+16*quan+8)||
                      (i==dx-quan*num+12*quan+6&&j==dy-quan*num+16*quan+8)||(i==dx-quan*num+14*quan+7&&j==dy-quan*num+16*quan+8))){

                      for(var x = -quan;x<=quan;x++){
                        for(var y = -quan;y<=quan;y++){
                          var xx = i+x;
                          var yy = j+y;
                          var pp = yy*canvas.width+xx; //周围的元素。
                          originalPxData[pp*4+0] = 255;//马赛克颜色
                          originalPxData[pp*4+1] = 255;
                          originalPxData[pp*4+2] = 255;
                        }
                      }
                    }
                  }
                }
                ctx.putImageData(originalImgData,0,0,0,0,canvas.width,canvas.height);//修改的信息放回画布
              }
            }
        })
      }, 20)
    },
    clearMasic() {//清除刚做的马赛克效果
      const canvas = document.querySelector('#canvas')
      const ctx = canvas.getContext('2d')
      const image = new Image()
      image.crossOrigin = 'Annoymous'
      image.src = this.previewImgObj.fileUrl
      image.onload = function() {
          ctx.drawImage(this, 0, 0, canvas.width, canvas.height)
      }
    },

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Tkinter的Canvas画布实现图片翻页,你可以使用PIL库(Python Imaging Library)来加载和处理图像,并通过Canvas对象的`create_image`方法将图像显示在画布上。以下是一个示例代码: ```python import tkinter as tk from PIL import ImageTk, Image root = tk.Tk() canvas = tk.Canvas(root, width=400, height=400) canvas.pack() # 图片列表 image_list = ["image1.jpg", "image2.jpg", "image3.jpg"] current_image = 0 def show_next_image(): global current_image current_image = (current_image + 1) % len(image_list) show_image() def show_previous_image(): global current_image current_image = (current_image - 1) % len(image_list) show_image() def show_image(): canvas.delete("image") image = Image.open(image_list[current_image]) image = image.resize((400, 400), Image.ANTIALIAS) photo = ImageTk.PhotoImage(image) canvas.create_image(0, 0, image=photo, anchor=tk.NW, tags="image") canvas.image = photo next_button = tk.Button(root, text="下一张", command=show_next_image) next_button.pack() previous_button = tk.Button(root, text="上一张", command=show_previous_image) previous_button.pack() show_image() root.mainloop() ``` 在这个示例中,我们创建了一个Canvas对象并设置其大小。我们定义了一个图片列表和一个当前图片的索引变量`current_image`。然后,我们定义了两个按钮,分别用于显示下一张和上一张图片。 `show_next_image`和`show_previous_image`函数用于切换到下一张和上一张图片,并调用`show_image`函数来在画布上显示图片。`show_image`函数首先删除之前的图片(通过`canvas.delete("image")`),然后加载当前图片并调整大小,最后通过`canvas.create_image`方法将图片显示在画布上。 通过点击按钮,你可以在画布上翻页显示不同的图片
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值