Canvas의 ImageData를 더 쉽게 처리하는 클래스

개요



Canvas 객체의 함수의 하나로 getImageData 함수라고 하는 것이 있습니다. ImageData 는, 1 픽셀을 (적, 녹색, 청, 투명도)의 4 개의 요소로 나타내고, 배열의 총수는, 4 × 폭 width × 높이 height 입니다. 이 값을 다시 작성하면 Canvas에 그려진 내용을 변경할 수 있습니다.
구조는 간단합니다만, 실제 처리를 쓰려고 하면 배열 번호를 여러가지 생각할 필요가 스마트가 아니었기 때문에, 보다 간단하게 쓸 수 있는 클래스를 만들었습니다.

수업



SimpleImageData.js
class SimpleImageData{
    constructor(canvasId, x = 0, y = 0, width, height){
        const canvas = document.getElementById(canvasId);
        this._context = canvas.getContext("2d")

        this._offset = {x: x, y: y};
        if(typeof width  === "undefined") width  = canvas.width;
        if(typeof height === "undefined") height = canvas.height;

        this._image = this._context.getImageData(x, y, width, height);
        this._x = -1;
        this._y = 0;
    }
    get hasNext(){
        if(++this._x >= this.width){
            this._x = 0;
            this._y++;
        }
        return this._y < this.height;
    }
    get r(){
        return this._image.data[this._index + 0];
    }
    set r(newValue){
        this._image.data[this._index + 0] = newValue;
    }
    get g(){
        return this._image.data[this._index + 1];
    }
    set g(newValue){
        this._image.data[this._index + 1] = newValue;
    }
    get b(){
        return this._image.data[this._index + 2];
    }
    set b(newValue){
        this._image.data[this._index + 2] = newValue;
    }
    get a(){
        return this._image.data[this._index + 3];
    }
    set a(newValue){
        this._image.data[this._index + 3] = newValue;
    }
    setRGB(r, g, b){
        this.r = r;
        this.g = g;
        this.b = b;
    }
    load(){
        this._context.putImageData(this._image, this._offset.x, this._offset.y);
    }
    get x(){
        return this._x;
    }
    get y(){
        return this._y;
    }
    get width(){
        return this._image.width;
    }
    get height(){
        return this._image.height;
    }
    get _index(){// private
        return (this._x + this._y * this.width) * 4;
    }
}

사용법



예를 들어, 황색( #FFFF00 )을 X축, 파란색( #0000FF )을 Y축 증가에 따라 그라데이션해 봅시다. for 문보다 hasNext와 while 문을 사용하는 것이 더 짧습니다.

javascript.js
const data = new SimpleImageData("canvas");
while(data.hasNext){
    const yellow = data.x / data.width;
    const blue = data.y / data.height;

    data.r = 255 * yellow;
    data.g = 255 * yellow;
    data.b = 255 * blue;
    data.a = 255;
}
data.load();

결과는 다음과 같습니다.


이 코드를 클래스없이 작성한다면. 이렇게 됩니다.

javascript.js
const canvas = document.getElementById("canvas");
const image = canvas.getContext("2d").getImageData(0, 0, canvas.width, canvas.height);
const data = image.data;

for(let i=0; i<data.length; i+=4){

    const index = i / 4;
    const x = index % image.width;
    const y = Math.floor(index / image.width);

    const yellow = x / image.width;
    const blue = y / image.height;

    data[i + 0] = 255 * yellow;
    data[i + 1] = 255 * yellow;
    data[i + 2] = 255 * blue;
    data[i + 3] = 255;
}
canvas.getContext("2d").putImageData(image, 0, 0);

좋은 웹페이지 즐겨찾기