How to Add Pixel Filter?
Tags: javascript, webdev, appwritehack, react
Published: 2022-04-24 13:23:58

Until now, I had only talked about the simple color to grayscale conversion.
Now it's time for the real stuff.

This is going to be about how I have converted an actual image to a text based filtered image.

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

I have discussed this in my previous post, which you can checkout here 👉[Adding Grayscale Filter](https://dev.to/thevinitgupta/adding-gray-scale-filter-pigshell-fhk) or you can access it at the top of this page.

Now, let's move on to the Pixel value to text conversion.

## Step 1 : Selecting the right characters

This is an important step. When you use characters to represent pixel brightness, you have to be really careful. 

If you choose the wrong character or the wrong size your image may end up looking distorted. 

There are multiple sources that suggest different set of characters for different range of brightness. But after some testing I found out the optimal character set as follows : 

```javascript
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
```

Once this is done, one more important thing is to set the `font-size` of each of these characters.
You can select `10px` or any other size that you prefer. 
We also have to use a `monospace` font for the characters so that the pixels are not distorted.

## Step 2 : Replacing the image data for the pixels

Now that we have the brightness values for each pixel, we can start assigning the characters. 
I started by making a different class for this process called `AsciiEffect`. 
You can check it out below : 

```javascript
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();
    }
}

```

## Step 3 : Replacing The Canvas Data

After the above returns the image data, we have to replace the canvas data with the new data. This is really simple : 

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


Now , I am working on the front end and will be released soon!