Pixelate characters with canvas, and draw generative art!
Tags: showdev, javascript, typescript, npm
Published: 2018-05-12 16:20:05

---
title: Pixelate characters with canvas, and draw generative art!
published: true
description: How to convert characters to a two-dimensional array and use it for generative art.
tags: showdev,javascript,typescript,npm
cover_image: https://thepracticaldev.s3.amazonaws.com/i/fro4v0qo5g5qfr62u1hc.png
---

[As I posted before](https://dev.to/ohbarye/what-i-felt-through-7-days-of-learning-generative-art-1fka), I'm learning generative art with [p5.js](https://p5js.org/).

In this article, I introduce a tool, "String Pixelater", which I made through the learning process.

- GitHub: https://github.com/ohbarye/string-pixelater
- npm: https://www.npmjs.com/package/string-pixelater

## What's String Pixelater

![image](https://user-images.githubusercontent.com/1811616/39958038-d70fbda2-5637-11e8-8b03-4b2d7bb21bf4.png)

This is a simple tool to pixelate any characters. `pixelate` means to "convert a character to a two-dimensional array" so that we can deal with the tabular data for several purposes. I actually compose this and [p5.js](https://p5js.org/) for painting generative art.

Let's dig into how it works... It has only one API so far though!

```javascript
> StringPixelater.pixelate('hello', {fontSize: 24})

[
  [0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,1,1,0,0,1,1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0],
  [0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0],
  [0,0,1,1,1,1,1,0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0],
  [0,0,1,1,1,1,0,0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,0,0],
  [0,0,1,1,1,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,1,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,1,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0,0,0,1,1,1,1,0,0,0,1,1,1,1,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,1,1,1,1,1,1,1,1,1,0,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1,1,1,1,0,0,0,0,0,0,1,1,0,0,0,1,1,1,0,0,0,0,0,1,1,1,1,1,1,1,0,0,0,0,0]
]
```

Could you vaguely see "hello" in the above?

## How does it work?

In short, it uses `<canvas>` element as a temporary _canvas_ to render characters. Then it extracts and parses rasterized image data. Its essential code is the following.

```typescript
const canvas = <HTMLCanvasElement> document.createElement('canvas');
const context = <CanvasRenderingContext2D> this.canvas.getContext('2d');
context.fillText("hello", 0, 0);

let table = new Array(canvas.height);

const imageData = context.getImageData(0, 0, canvas.width, canvas.height);

for (let row = 0; row < canvas.height; row++){
  table[row] = new Array(canvas.width);

  for (let col = 0; col < canvas.width; col++){
    const alpha = imageData.data[(canvas.width * row + col) * 4 + 3];
    if (alpha >= 64) {
      table[row][col] = 1;
    } else {
      table[row][col] = 0;
    }
  }
}
```

## Usage

Just install and call `StringPixelater.pixelate` method with a string which you want to pixelate.

```shell
$ npm install --save string-pixelater
or
$ yarn add string-pixelater
```

You can use as ES module or load through `<script>` tag

```javascript
import StringPixelater from 'string-pixelater';

const table = StringPixelater.pixelate('Hello, world');
```

```html
<script type="text/javascript" src="path/to/dist/js/string-pixelater.js"></script>
<script type="text/javascript">
  var table = StringPixelater.pixelate('Hello, world');
</script>
```

### `transpose`

If you use `p5.js` like me, `transpose` option is quite convenient because it has inverted axes,

```javascript
> StringPixelater.pixelate('B', {fontSize: 24, transpose: false})
[
  [0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0],
  [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,1,1,1,1,0,0,0],
  [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
  [0,0,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,1,1,1,0,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,0,0,0,0,0,0,0,0,0,1,1,1,0,0],
  [0,0,1,1,1,0,0,0,0,0,0,1,1,1,1,0,0,0],
  [0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0],
  [0,0,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0]
]

> StringPixelater.pixelate('B', {fontSize: 24, transpose: true})
[
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],
  [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,1],
  [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1],
  [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1],
  [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1],
  [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1],
  [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1],
  [1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,1,1],
  [1,1,1,0,0,0,0,1,1,1,0,0,0,0,0,0,1,1,1],
  [1,1,1,1,0,0,1,1,1,1,1,0,0,0,0,0,1,1,1],
  [0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0],
  [0,0,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0],
  [0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
  [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
]
```

The latter looks correct when it's rendered with simple and intuitive loops.

```javascript
// Note: This is just pseudo code!
function draw() {
  const imageData = StringPixelater.pixelate('B', {fontSize: 24, transpose: true})
  const pixelSize = 10;

  imageData.forEach(function(row, i) {
    row.forEach(function(cell, j) {
      if (cell === 1) {
        ellipse(i * pixelSize, j * pixelSize, pixelSize, pixelSize);
      }
    })
  })
}
```

This results like below:

<img width="200" alt="2018-05-12 22 49 04" src="https://user-images.githubusercontent.com/1811616/39957847-bd96294a-5634-11e8-93be-9efaac493833.png">

## Artworks with String Pixelater

Just with `StringPixelater.pixelate('hello')`:

<img width="848" alt="2018-05-12 22 49 04" src="https://user-images.githubusercontent.com/1811616/39958008-34941f78-5637-11e8-8ec9-271d87e58f76.png">

We can get pixelated emoji as like `StringPixelater.pixelate('🐈')`.

<img width="597" alt="2018-05-12 22 52 36" src="https://user-images.githubusercontent.com/1811616/39958009-34b9721e-5637-11e8-80c2-42b5e6661e23.png">

---

I would be glad if anyone would have an interest in generative art or [string-pixelater](https://github.com/ohbarye/string-pixelater) through this article. :)