8

canvas中getImageData改变大小及颜色

 1 year ago
source link: https://www.haorooms.com/post/canvas_getimagedata
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

关于getImageData

ctx.getImageData(),可以获取canvas的data图片数据,这个图片数据返回的data是一个对象,该对象包含指定的 ImageData 对象的图像数据。 对于 ImageData 对象中的每个像素,都存在着四方面的信息,即 RGBA 值:

R - 红色 (0-255)
G - 绿色 (0-255)
B - 蓝色 (0-255)
A - alpha 通道 (0-255; 0 是透明的,255 是完全可见的)

color/alpha 以数组形式存在,并存储于 ImageData 对象的 data 属性中。

ImageData.datalength 可以作这样计算:300(width) X 150(height) X 4(r,g,b,a 4个分量) = 180000

关于getImageData,我之前文章也有写过 https://www.haorooms.com/post/canvas_imageData 里面有利用getImageData,过滤视频纯色背景,吸取视频颜色,防锯齿,图片灰色及反色,图片下载等

今天在这个基础上再补充一些,主要是封装成函数,更方便调用,之前主要是demo案例,大家可以看看这些demo案例https://www.haorooms.com/post/canvas_imageData

canvas 应用补充

之前文章有写过,今天补充一下。

两个canvas画布

var canvasa = document.getElementById("canvasa")
var contexta = canvasa.getContext("2d")

var canvasb = document.getElementById("canvasb")
var contextb = canvasb.getContext("2d")
function greyEffect(){
    var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var pixelData = imageData.data
    for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){
        var r = pixelData[i*4+0]
        var g = pixelData[i*4+1]
        var b = pixelData[i*4+2]

        var grey = r*0.3+g*0.59+b*0.11

        pixelData[i*4+0] = grey
        pixelData[i*4+1] = grey
        pixelData[i*4+2] = grey
    }

    contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
}
function blackEffect(){
    var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var pixelData = imageData.data
    for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){
        var r = pixelData[i*4+0]
        var g = pixelData[i*4+1]
        var b = pixelData[i*4+2]

        var grey = r*0.3+g*0.59+b*0.11
        if(grey > 125){
            pv = 255
        }
        else{
            pv = 0
        }

        pixelData[i*4+0] = pv
        pixelData[i*4+1] = pv
        pixelData[i*4+2] = pv
    }
    contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height )
}
function reverseEffect(){
    var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var pixelData = imageData.data
    for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){

        var r = pixelData[i*4+0]
        var g = pixelData[i*4+1]
        var b = pixelData[i*4+2]

        pixelData[i*4+0] = 255 - r
        pixelData[i*4+1] = 255 - g
        pixelData[i*4+2] = 255 - b
    }

    contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
}
function blurEffect(){
    var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var tmpPixelData = tmpImageData.data

    var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var pixelData = imageData.data

    var blurR = 3
    var totalnum = (2*blurR + 1)*(2*blurR + 1)

    for( var i = blurR ; i < canvasb.height - blurR ; i ++ )
        for( var j = blurR ; j < canvasb.width - blurR ; j ++ ){

            var totalr = 0 , totalg = 0 , totalb = 0
            for( var dx = -blurR ; dx <= blurR ; dx ++ )
                for( var dy = -blurR ; dy <= blurR ; dy ++ ){

                    var x = i + dx
                    var y = j + dy

                    var p = x*canvasb.width + y
                    totalr += tmpPixelData[p*4+0]
                    totalg += tmpPixelData[p*4+1]
                    totalb += tmpPixelData[p*4+2]
                }

            var p = i*canvasb.width + j
            pixelData[p*4+0] = totalr / totalnum
            pixelData[p*4+1] = totalg / totalnum
            pixelData[p*4+2] = totalb / totalnum
        }

    contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
}
function mosaicEffect(){
    var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var tmpPixelData = tmpImageData.data

    var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
    var pixelData = imageData.data

    var size = 16
    var totalnum = size*size
    for( var i = 0 ; i < canvasb.height ; i += size )
        for( var j = 0 ; j < canvasb.width ; j += size ){

            var totalr = 0 , totalg = 0 , totalb = 0
            for( var dx = 0 ; dx < size ; dx ++ )
                for( var dy = 0 ; dy < size ; dy ++ ){

                    var x = i + dx
                    var y = j + dy

                    var p = x*canvasb.width + y
                    totalr += tmpPixelData[p*4+0]
                    totalg += tmpPixelData[p*4+1]
                    totalb += tmpPixelData[p*4+2]
                }

            var p = i*canvasb.width+j
            var resr = totalr / totalnum
            var resg = totalg / totalnum
            var resb = totalb / totalnum

            for( var dx = 0 ; dx < size ; dx ++ )
                for( var dy = 0 ; dy < size ; dy ++ ){

                    var x = i + dx
                    var y = j + dy

                    var p = x*canvasb.width + y
                    pixelData[p*4+0] = resr
                    pixelData[p*4+1] = resg
                    pixelData[p*4+2] = resb
                }
    }

    contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height )

}

常用遍历方法:

let imgData = ctx.getImageData(0, 0, WIDTH, HEIGHT).data;
// 找到画布像素中的有色位置 index
// 第一行第一列 width * 4 
// 第二行第二列
// ......
for(var y = 0; y < HEIGHT; y += skip) { // 遍历y轴方向的像素点
    for(var x = 0; x < WIDTH; x += skip) { // 遍历x轴方向的像素点
        idx = (x + y * WIDTH) * 4 - 1; 
        // y * width * 4 表示下一行(第几行)的意思
        // x * 4 表示 index 相对的位置
        // - 1 表示长度 - 1
        // x*4 + y*width*4 -1 

        if(imgData[idx] > 0) {
           // console.log('idx+++: ', idx)
           // some code ......
        } else{
            // 表示小于0或等于0的情况
            // some other code ......
            // console.log('idx---: ', imgData[idx])
        }
    }
}

Canvas中对ImageData数据缩放

// imageData 要改版的数据,scale是缩放的尺寸,outCtx是输出的canvas ctx

  function scaleImageData(imageData, scale, outCtx) {
    var scaled = outCtx.createImageData(imageData.width * scale, imageData.height * scale)
    for (var row = 0; row < imageData.height; row++) {
      for (var col = 0; col < imageData.width; col++) {
        var sourcePixel = [imageData.data[(row * imageData.width + col) * 4 + 0], imageData.data[(row * imageData.width + col) * 4 + 1], imageData.data[(row * imageData.width + col) * 4 + 2], imageData.data[(row * imageData.width + col) * 4 + 3]]
        for (var y = 0; y < scale; y++) {
          var destRow = Math.floor(row * scale) + y
          for (var x = 0; x < scale; x++) {
            var destCol = Math.floor(col * scale) + x
            for (var i = 0; i < 4; i++) {
              scaled.data[(destRow * scaled.width + destCol) * 4 + i] = sourcePixel[i]
            }
          }
        }
      }
    }
    return scaled
  }

温故而知新,之前的总结比较笼统,今天再次总结一下,比较使用的方法,可以直接项目中使用。比较方便。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK