Introduction
In this article I will show you how to convert images to ASCII art.
To convert images to ASCII we will need some basic programming knowledge of C# 3.0 which includes:
- Loops
- Math operands
- Imaging
Background
ASCII - American Standard Code for Information Interchange, is often used for telegraphic codes and for other uses such as for fun.
ASCII has 128 keyboard characters and 33 control characters.
Encoding on the World-Wide-Web also used ASCII encoding until UTF-8 was preferred. Nowadays ASCII is often referred to as sometimes art to draw pictures with only using keyboard characters.
Using the code
To convert images to ASCII, we are going to first need to convert all of the colors to console colors since
Console applications are limited to 16 colors.
Let's first create a class file used to print ASCII characters with a console color and character.
public class CString
{
public ConsoleColor Color;
public string String;
public CString(string s, ConsoleColor color)
{
String = s;
Color = color;
}
public CString()
{
}
}
Now that we have a class file for storing a console color and character let's get to converting the colors.
For more information on converting colors there is a well written article on converting colors
here.
Let's first retrieve all of the console colors.
static Color[] ConsoleColors()
{
Color[] array = new Color[16];
string[] names = Enum.GetNames(typeof(ConsoleColor));
for (int i = 0; i < names.Length; i++)
array[i] = Color.FromName(names[i]);
return array;
}
Now let's create a function to find the closest color to these colors.
static ConsoleColor Closest(Color _1)
{
if (_1.IsSystemColor)
return (ConsoleColor)Enum.Parse(typeof(ConsoleColor), _1.Name);
double dbl_input_red = Convert.ToDouble(_1.R);
double dbl_input_green = Convert.ToDouble(_1.G);
double dbl_input_blue = Convert.ToDouble(_1.B);
double distance = 500.0;
double dbl_test_red;
double dbl_test_green;
double dbl_test_blue;
Color nearest_color = Color.Empty;
foreach (object o in ConsoleColors())
{
dbl_test_red = Math.Pow(Convert.ToDouble(((Color)o).R) - dbl_input_red, 2.0);
dbl_test_green = Math.Pow(Convert.ToDouble
(((Color)o).G) - dbl_input_green, 2.0);
dbl_test_blue = Math.Pow(Convert.ToDouble
(((Color)o).B) - dbl_input_blue, 2.0);
double temp = Math.Sqrt(dbl_test_blue + dbl_test_green + dbl_test_red);
if (temp == 0.0)
{
nearest_color = (Color)o;
break;
}
else if (temp < distance)
{
distance = temp;
nearest_color = (Color)o;
}
}
return (ConsoleColor)Enum.Parse(typeof(ConsoleColor), nearest_color.Name);
}
Now that we have a function for finding the closest console color, let's create a function that finds the closest ASCII character for a specified color.
static string Brightness(Color _1)
{
int factor = _1.R + _1.G + _1.B;
if (factor >= 602)
return "M";
if (factor >= 572)
return "@";
if (factor >= 532)
return "#";
if (factor >= 502)
return "8";
if (factor >= 472)
return "0";
if (factor >= 432)
return "&";
if (factor >= 402)
return "%";
if (factor >= 372)
return "?";
if (factor >= 332)
return "<";
if (factor >= 302)
return "/";
if (factor >= 252)
return "*";
if (factor >= 200)
return ".";
return " ";
}
Let's create another function to implement to CString
class:
static CString CSimiliarity(Color _1)
{
CString str = new CString();
str.String = Brightness(_1);
str.Color = Closest(_1);
return str;
}
Lastly, convert the Bitmap
object to a multidimensional array of CString
s.
static CString[,] ImageToASCII(Bitmap b)
{
Image.GetThumbnailImageAbort myCallback = null;
if (b.Width > 80)
b = (Bitmap)b.GetThumbnailImage(80, 60, myCallback, IntPtr.Zero);
CString[,] map = new CString[80, b.Height];
for (int y = 0; y < b.Height; y++)
for (int x = 0; x < 80; x++)
map[x, y] = CSimiliarity(b.GetPixel(x, y));
return map;
}
Since you probably want to see the end result, let's create a function to print the array.
static void PrintCStringMult(CString[,] mult)
{
int width = mult.GetLength(0);
int height = mult.GetLength(1);
for (int y = 0; y < height; y++)
{
for (int x = 0; x < width; x++)
{
CString m = mult[x, y];
Console.ForegroundColor = m.Color;
Console.Write(m.String);
}
}
}
Points of Interest
For best results make sure you resize the picture to exactly 80, it doesn't work well with anything below 80. Note: Console screen width is 80 characters (pixels in this case).
Thanks
I have used a small bit of code from this article published on The Code Project:
http://www.codeproject.com/Articles/17044/Find-the-Nearest-Color-with-C-Using-the-Euclidean.
History
N\A.