Creating ASCII Art! (with C#)

Dor Lugasi-Gal
5 min readMar 12, 2022

did you ever see those cool `letter` art?
][_, (][) ][_,
those that use some English letters and symbols to form some kind of text or an image?
I’m sure there are some people who actually sit behind the keyboard and try to create those letter by letter, but today we’re going to implement it by ourselves!

What Is ASCII Art?

basically, ASCII art is a text-based form of art.
Art or text used in programs or documents that are made of characters and symbols taken from ASCII characters.

Yeah, OK, But How Does It Work?

Great question!
To explain that, we have to understand what an image is made of.
An image, more specifically, a digital image consists of Pixels, based on the resolution of that image.
So an image with a resolution of 400 * 600 (height\width) has 240000 pixels.
A pixel is the smallest single component of a digital image.
Each pixel can contain data about the color of that pixel, pixels range from having different amount of bits which represent them, where each bit represents a color option,

  • 1 bpp, 2^1 = 2 colors (monochrome)
  • 2 bpp, 2^2 = 4 colors
  • 3 bpp, 2^3 = 8 colors
  • 4 bpp, 2^4 = 16 colors
  • 8 bpp, 2^8 = 256 colors
  • 16 bpp, 2^16 = 65,536 colors (“Highcolor” )
  • 24 bpp, 2^24 = 16,777,216 colors (“Truecolor”)

So how do we construct a Color?
There are multiple ways to define a Color using a color space, one of the most popular is sRGB.

sRGB stands for Standard Red Green Blue and is a color space, or a set of specific colors, created by HP and Microsoft in 1996 with the goal of standardizing the colors portrayed by electronics.

In other words which combination of red green and blue colors combined will create that color.
each value can range between 0 to 255, so an example for a color representation:
(R:255,G:0,B:0) = Red
(R:0,G:255,B:0) = Green
(R:0,G:0,B:255) = Blue
(R:255,G:255,B:255) = White
(R:0,G:0,B:0) = Black
(R:100,G:100,B:100) = Gray

There’s also RGBA that has an alpha value which determines how much transparency the specific color has, but that is not relevant for our small project.

lets cut to the code.

Printing An Image As ASCII Art

Let’s say, we would like to transform this image to ASCII art:

cute doggo

Notice we have some parts of the picture which are darker, and some parts that are lighter.
Thats exactly what we want to simulate when creating ASCII art,
some characters can represent a dark pixel, for example a space ‘ ’ or a dot ‘.’.
and some can represent a light pixel for example ‘@’ or ‘W’
but why did I choose those specifically?
that’s actually easy to understand, the more dense the letter is, the more light it would appear on a dark background right?
so lets define our `color palette`:

string asciiChars = "  .,:ilwW@@";

Those letters must be sorted by their density, in order for it to work.

Let’s say we have a pixel in our hands, and we know it’s RGB values
how can we transform it to an ASCII character,
it would be easier to understand how light or dark a pixel is if we look at the grayscale color of it.
A grayscale tone can be generated by an average of the RGB values altogether.

For example, the Red color (255,0,0) grayscale representation is (85,85,85).

From this part, all that is left to do is to take that average value that we have and get its position at the characters array that we created before.
So if we have [0,255] possibilities for a color average and only [0,10] possibility for an ASCII character, we want to take that relative part of that value inside the ASCII characters array that we choose,
the more letters we put in our characters array, the more diversity we would have in representing our lightness values.

I didn’t want to represent each and every pixel, because it would be too large.
so I resized the image to match a width of 130 pixels.
the end result:

cute doggo

THIS IS AWESOME!
I had to change the font for a font with even spacing between letters and fine-tune the line height to make the picture appear in the right dimensions and not squashed.
but how great is this? a picture came to life with help from a bunch of letters and some symbols!

Will It Work For A Video Too?

And then it came to my mind, a video is basically a collection of digital images!
what if I modify my code to extract the frames from a short mp4 video file?
that’s possible, I just need to find a way to extract the frames, and reuse my code.
So I found a Nuget package called NuGet Gallery | Emgu.CV
which is a cross-platform .NET wrapper to the known OpenCV image processing library.

In order to reduce console writing flickering, I collect every character that i needed to insert inside a string builder object, and when finishing processing every frame’s pixels, I pushed that StringBuilder value into the console. and also positioned the Console Cursor to the beginning of the text

Take a look at that:

How cool is that, right?

Final Step

One more step left for me to do,
what if I could parse a video in real-time?

using the same library, I could easily set the video capture to my web cam, and see myself as a bunch of ‘W’ and ‘@’ and ‘.’

Hope you had fun reading and learning,
Thanks!

--

--

Dor Lugasi-Gal

Back-End Developer with a passion for Architecture. focused on .NET/React and anything within that is related to architecture