Introduction
The main idea is about reading the intensity value of every group of the picture. (The mentioned group is a matrix formed from the adjacent pixels.) Then writing a digit either 1 or 0 and its color value is the average intensity value of the source group.
Background
First of all we have to distinguish between how the intensity is obtained, in this article I'll going to show two methods either:
- 1st intensity method (gives better visual results): in this method, intensity is obtained from the first pixel of the group.
- Average intensity method: while here we calculate the average intensity value of each group.
In both methods, after we get the intensity value we write a digit either 1 or 0 and its color value is the value which we got.
The previous mechanism is applied to the image by reading it as a matrix (2D array). Noticing that traversing through the array is "for each row of the image, visit each pixel".
The next figuures show the differences between the two methods:
|
Original picture |
| |
1st intensity method | Average intensity method |
Using the Code
Tools
class:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
namespace Image2Characters
{
public static class Tools
{
static String strImagesFolderName = "images";
static String strHtmlFolderName = "pages";
static String strHtmlFileHeader = "<html><head><title>{0} Image - {1}</title></head><body><pre><font><font style=\"font-size: 9px;\">";
static String strHtmlFileFooter = "</font></font></pre></body></html>";
static int iWidthRatio = 5, iHeightRatio = 12;
public static void InitEnviroment()
{
Directory.CreateDirectory(strImagesFolderName);
Directory.CreateDirectory(strHtmlFolderName);
}
public static int GetIntensity(Color color)
{
return (int)(0.3f * color.R + 0.59f * color.G + 0.11f * color.B);
}
public static String[] GetImages()
{
return Directory.GetFiles(strImagesFolderName + @"\", "*.jpg");
}
public static void ConvertImageToCharacter1stIntensity(String strImageName)
{
Bitmap img = (Bitmap)Image.FromFile(strImageName);
String strDigit = ""
, strImageNameWithoutExtension = Path.GetFileNameWithoutExtension(strImageName);
StringBuilder createdFileContent = new StringBuilder();
int k = 0;
createdFileContent.AppendFormat(strHtmlFileHeader, strImageNameWithoutExtension, System.Windows.Forms.Application.ProductName);
for (int i = 0; i < img.Height - 1; i += iHeightRatio)
{
for (int j = 0; j < img.Width - 1; j += iWidthRatio)
{
strDigit = (k % 2 == 0) ? "0" : "1";
k++;
createdFileContent.AppendFormat("<font color=\"#{0:x2}{0:x2}{0:x2}\">{1}</font>", Tools.GetIntensity(img.GetPixel(j, i)), strDigit);
}
createdFileContent.Append("<br/>");
}
createdFileContent.Append(strHtmlFileFooter);
File.WriteAllText(String.Format(@"{0}\{1}.html", strHtmlFolderName, strImageNameWithoutExtension), createdFileContent.ToString());
}
public static void ConvertImageToCharacterAverageIntensity(String strImageName)
{
Bitmap img = (Bitmap)Image.FromFile(strImageName);
String strDigit = ""
, strImageNameWithoutExtension = Path.GetFileNameWithoutExtension(strImageName);
StringBuilder createdFileContent = new StringBuilder();
int iAverageValue
, k = 0
, iItemsCountInSubMatrix = iWidthRatio * iHeightRatio
, iSubMatrixElementsSum;
createdFileContent.AppendFormat(strHtmlFileHeader, strImageNameWithoutExtension, System.Windows.Forms.Application.ProductName);
for (int i = 0; i < img.Height - 1; i += iHeightRatio)
{
for (int j = 0; j < img.Width - 1; j += iWidthRatio)
{
iSubMatrixElementsSum = 0;
for (int i2 = 0; i2 < iHeightRatio - 1; i2++)
{
if (i + i2 < img.Height)
{
for (int j2 = 0; j2 < iWidthRatio - 1; j2++)
{
if (j + j2 < img.Width)
{
iSubMatrixElementsSum += Tools.GetIntensity(img.GetPixel(j + j2, i + i2));
}
}
}
}
iAverageValue = iSubMatrixElementsSum / iItemsCountInSubMatrix;
strDigit = (k % 2 == 0) ? "0" : "1";
k++;
createdFileContent.AppendFormat("<font color=\"#{0:x2}{0:x2}{0:x2}\">{1}</font>", iAverageValue, strDigit);
}
createdFileContent.Append("<br/>");
}
createdFileContent.Append(strHtmlFileFooter);
File.WriteAllText(String.Format(@"{0}\{1}.html", strHtmlFolderName, strImageNameWithoutExtension), createdFileContent.ToString());
}
}
}
History
Notices
- The only accepted images are the ones that end with the "jpg" extension due to the implementation of my code.
- I chose the size of the group to be 12 rows and 5 columns. You can change these values if you didn't get the desired result. Either you can set them to 1 row and 1 column, this will map each pixel to a digit; of course this will give a bigger picture.
- This project is using C# 2.0 but was coded in Visual Studio 2008.
- I write "1st intensity method" from my practical tries, meaning this is not a referential contrary to "Average intensity method" that is a simple well known method. But I prefered to write "1st intensity method" because it showed better results.
Improvements
- Change the group size to be related to the size of the source image. This improvement will reduce the bad results when the source image is small. For example: width = 80~110px.