픽셀 필터를 추가하는 방법?

지금까지는 단순한 색상에서 회색조로의 변환에 대해서만 이야기했습니다.
이제 진짜 물건을 볼 시간입니다.

이것은 실제 이미지를 텍스트 기반 필터링 이미지로 변환하는 방법에 관한 것입니다.

Well, the first thing was to to load the image into a canvas element. This had to be followed by converting to grayscale image.



이전 게시물에서 이에 대해 논의했으며 여기 👉에서 확인하거나 이 페이지 상단에서 액세스할 수 있습니다.

이제 픽셀 값을 텍스트로 변환하는 방법으로 넘어가겠습니다.

1단계: 올바른 문자 선택



이것은 중요한 단계입니다. 문자를 사용하여 픽셀 밝기를 나타낼 때는 정말 주의해야 합니다.

잘못된 문자나 잘못된 크기를 선택하면 이미지가 왜곡되어 보일 수 있습니다.

다양한 범위의 밝기에 대해 서로 다른 문자 세트를 제안하는 여러 소스가 있습니다. 그러나 약간의 테스트 후에 다음과 같이 최적의 문자 집합을 찾았습니다.

convertToSymbol(g){
        if(g> 245) return 'G';
        else if(g > 225) return 'H';
        else if(g > 200) return '&';
        else if(g > 185) return 'S';
        else if(g > 165) return '%';
        else if(g > 145) return 'W';
        else if(g > 120) return '+';
        else if(g > 100) return '=';
        else if(g > 80) return '-';
        else if(g > 60) return ':';
        else if(g > 45) return '.';
        else return ' ';

    }
// here 'g' is the brightness value of a particular pixel


이 작업이 완료되면 한 가지 더 중요한 것은 이러한 각 문자의 font-size를 설정하는 것입니다.10px 또는 원하는 다른 크기를 선택할 수 있습니다.
또한 픽셀이 왜곡되지 않도록 문자에 monospace 글꼴을 사용해야 합니다.

2단계: 픽셀의 이미지 데이터 교체



이제 각 픽셀의 밝기 값이 있으므로 문자 할당을 시작할 수 있습니다.
나는 AsciiEffect라는 이 프로세스를 위한 다른 클래스를 만드는 것으로 시작했습니다.
아래에서 확인할 수 있습니다.

class AsciiEffect {
    #imageCellArray = [];
    #pixels = [];
    #ctx;
    #width;
    #height;
    constructor(ctx, width, height, image){
        this.#ctx = ctx;
        this.#width = width;
        this.#height = height;
        this.#ctx.drawImage(image, 0, 0, this.#width, this.#height);
        this.#pixels = this.#ctx.getImageData(0, 0, this.#width, this.#height);
    }
    #convertToSymbol(g){
        if(g> 245) return 'G';
        else if(g > 225) return 'H';
        else if(g > 200) return '&';
        else if(g > 185) return 'S';
        else if(g > 165) return '%';
        else if(g > 145) return 'W';
        else if(g > 120) return '+';
        else if(g > 100) return '=';
        else if(g > 80) return '-';
        else if(g > 60) return ':';
        else if(g > 45) return '.';
        else return ' ';

    }
    #scanImage(cellSize, color){
        this.#imageCellArray = [];
        for(let y  = 0; y < this.#pixels.height; y += cellSize){
            for(let x = 0; x < this.#pixels.width; x += cellSize){
                let posX = (x*4), posY = y*4;
                const pos = (posY*this.#pixels.width) + posX;
                if(this.#pixels.data[pos+3]>120){
                    let total = this.#pixels.data[pos]+this.#pixels.data[pos+1]+this.#pixels.data[pos+2];
                    const avgColorValue = total/3;
                    const symbol = this.#convertToSymbol(avgColorValue);
                    this.#imageCellArray.push(new Cell(x,y, symbol, color));
                }
            }
        }
        console.log(this.#imageCellArray);
    }
    #drawAscii(){
        this.#ctx.fillStyle = "#000000"
        this.#ctx.fillRect(0,0, this.#width, this.#height);
        for(let i=0;i<this.#imageCellArray.length;i++){
            this.#imageCellArray[i].draw(this.#ctx);
        }
    }
    draw(cellSize, color){
        this.#scanImage(cellSize, color);
        this.#drawAscii();
    }
}



3단계: 캔버스 데이터 바꾸기



위의 이미지 데이터를 반환한 후 캔버스 데이터를 새 데이터로 교체해야 합니다. 이것은 정말 간단합니다.

ctx.font = '7px Fira Code';
effect.draw(7,"#ffffff");


지금은 프론트엔드 작업중이고 곧 출시될 예정입니다!

좋은 웹페이지 즐겨찾기