canvas - 5-像素级操作

1.理解ImageData() 对象的获取方式。

1.1. ImageData 是什么?

ImageData 是图片的数据化,它具备以下属性:

  1. data:Uint8ClampedArray [r,g,b,a, r,g,b,a, r,g,b,a, r,g,b,a]
  2. width:整数
  3. heidth:整数

注:Uint8ClampedArray 翻译过来是 8位无符号整型固定数组,其取值范围是[0,255]。若小于0,则为0,大于255,则为255。若为小数,则取整,取整的方法是银行家舍入。

1.2 怎么拿到 ImageData() 对象?
  1. 直接建立ImageData() 对象(相当于自己新建了一张图片)。
  • new ImageData()

    new ImageData(width, height)

    new ImageData(Uint8ClampedArray, width, height)

  • ctx.createImageData()

    ctx.createImageData(width, height)

    ctx.createImageData(ImageData)

  1. 获取canvas 的ImageData() 对象(可以以此原理获取真实图片的数据)

    ctx.getImageData(x, y, width, height)

  2. 在canvas 中显示ImageData
    使用: putImageData(ImageData, dx, dy, x, y, w, h)
    在这里插入图片描述

const imgDt=ctx.createImageData(width,height);
    console.log('imgDt', imgDt)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>ImageData </title>
    <style>
        body{margin: 0;overflow: hidden}
        #canvas{background: antiquewhite;}
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    const canvas=document.getElementById('canvas');
    //canvas充满窗口
    canvas.width=window.innerWidth;
    canvas.height=window.innerHeight;
    //画笔
    const  ctx=canvas.getContext('2d');

    /*
    * 图片尺寸:宽,高
    * */
    const [width,height]=[400,200];

    /*ImageData 对象的建立
    *   new ImageData(Uint8ClampedArray, width, height)
    *   new ImageData( width, height)
    * */
    /*const imgDt=new ImageData(width,height);

    imgDt.data.forEach((ele,ind)=>{
        imgDt.data[ind]=255;
    })
    console.log(imgDt);

    ctx.putImageData(imgDt,0,0);*/


    /*用上下文建立ImageData 对象
    *   ctx.createImageData(width, height)
    *   ctx.createImageData(ImageData)
    * */
    const imgDt=ctx.createImageData(width,height);
    imgDt.data.forEach((ele,ind)=>{
        imgDt.data[ind]=255;
    })
    ctx.putImageData(imgDt,0,0);


    /*getImageData(x, y, width, height) 获取canvas 中的像素*/
    const imgDt2=ctx.getImageData(0,0,1,1);
    console.log(imgDt2);

</script>
</body>
</html>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>putImageData</title>
    <style>
        body{margin: 0;overflow: hidden}
        #canvas{background: antiquewhite;}
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    const canvas=document.getElementById('canvas');
    //canvas充满窗口
    canvas.width=window.innerWidth;
    canvas.height=window.innerHeight;
    const ctx=canvas.getContext('2d');

    const img=new Image();
    img.src='./images/dog.jpg';
    img.onload=function(){
        //获取图片宽高
        const {width,height}=img;

        /*1.在canvas 中绘制图像*/
        ctx.drawImage(img,0,0);

        /*2.从canvas 中获取图像的ImageData*/
        const imgDt=ctx.getImageData(0,0,width,height);

        /*3.在canvas 中显示ImageData*/
        ctx.putImageData(
            imgDt,
            0,height,
            width/2,height/2,width/2,height/2);


    };

</script>
</body>
</html>


  1. 理解 ImageData 中的像素集合和图像栅格的对应关系
    ImageData 对象的属性:
    data:Uint8ClampedArray [0,1,2,3, 4,5,6,7,8,9,10,11,12,13,14,15]
    width:2
    heidth:2
    在这里插入图片描述

  2. 遍历像素的方法

  • 1.逐像素遍历:每隔4 个数据遍历一次,简单快捷
for(let i=0;i<arr.length;i+=4){
        let r=data[i+0];
        let g=data[i+1];
        let b=data[i+2];
        let a=data[i+3];
        console.log(r,g,b,a)
}
  • 2.行列遍历:基于行列遍历,可获取像素点的位置信息
for(let y=0;y<h;y++){
       for(let x=0;x<w;x++){
            let ind=(y*w+x)*4;
            let r=data[ind];
            let g=data[ind+1];
            let b=data[ind+2];
            let a=data[ind+3];
            console.log(r,g,b,a)
        }
    }
  1. 图像置灰
    要点:灰度算法 const lm =0.299r + 0.587g + 0.114*b ;

在这里插入图片描述
操作像素:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>图像置灰</title>
    <style>
        body{margin: 0;overflow: hidden}
        #canvas{background: antiquewhite;}
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    const canvas=document.getElementById('canvas');
    //canvas充满窗口
    canvas.width=window.innerWidth;
    canvas.height=window.innerHeight;
    const ctx=canvas.getContext('2d');

    const img=new Image();
    img.src='./images/river.jpg';
    img.onload=draw;

    /*灰度算法: 0.299*r+0.587*g+0.114*b */

    function draw(){
        //图像尺寸
        const {width,height}=img;

        /*1.在canvas 中绘制图像*/
        ctx.drawImage(img,0,0);

        /*2.从canvas 中获取图像的ImageData*/
        const imgDt=ctx.getImageData(0,0,width,height);
        const data=imgDt.data;

        /*像素遍历*/
        // 修改像素中的数据
        for(let i=0;i<data.length;i+=4){
            const [r,g,b]=[
                data[i],
                data[i+1],
                data[i+2],
            ]
            const lm=0.299*r+0.587*g+0.114*b;
            data[i]=lm;
            // data[i+1]=lm;
            // data[i+2]=lm;
        }


        /*3.在canvas 中显示ImageData*/
        ctx.putImageData(imgDt,0,height);

    }

</script>
</body>
</html>


  1. 马赛克效果:
    要点:获取一区域的像素颜色,然后将此颜色赋给此区域的所有像素。

原图:
在这里插入图片描述
设置的马赛克效果:
在这里插入图片描述
8. 求r 在像素集合里的索引位置 ind
在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>马赛克效果</title>
    <style>
        body{margin: 0;overflow: hidden}
        #canvas{background: antiquewhite;}
    </style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
    const canvas=document.getElementById('canvas');
    //canvas充满窗口
    canvas.width=window.innerWidth;
    canvas.height=window.innerHeight;
    const ctx=canvas.getContext('2d');

    //图像源
    const img=new Image();
    img.src='./images/wns.jpg';
    img.onload=render;

    //色块尺寸
    let size=50;

    function render() {
        //图像尺寸
        const {width,height}=img;

        /*1.在canvas 中绘制图像*/
        ctx.drawImage(img,0,0);

        /*2.从canvas 中获取图像的ImageData*/
        const imgDt=ctx.getImageData(0,0,width,height);
        const data=imgDt.data;

        /*行列遍历*/
        for(let y=0;y<height;y+=size){
            for(let x=0;x<width;x+=size){
                const i=(y*width+x)*4;
                const [r,g,b]=[
                    data[i],
                    data[i+1],
                    data[i+2],
                ]
                ctx.fillStyle=`RGB(${r},${g},${b})`;
                ctx.fillRect(x,y,size,size);
            }
        }

    }
</script>
</body>
</html>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值