Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / multimedia / GDI+

Image to Characters Converter using Intensity

4.60/5 (10 votes)
17 Oct 2008CPOL2 min read 1   482  
This article shows how you can display a picture in digits 1 and 0.

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:

  1. 1st intensity method (gives better visual results): in this method, intensity is obtained from the first pixel of the group.
  2. 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:

WindowsLogo.jpg
Original picture

 

WindowsLogoDigits.gifWindowsLogoDigits.gif
1st intensity methodAverage intensity method

Using the Code

Tools class:
C#
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
    {
        /// <summary>
        /// folder names both input and output folder
        /// </summary>
        static String strImagesFolderName = "images";
        static String strHtmlFolderName = "pages";

        /// <summary>
        /// Result html file content
        /// </summary>
        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>";

        /// <summary>
        /// How many pixels fit in each group
        /// here the group size is 12 * 5
        /// </summary>
        static int iWidthRatio = 5, iHeightRatio = 12;



        /// <summary>
        /// Make sure program needed directories is exists
        /// </summary>
        public static void InitEnviroment()
        {
            Directory.CreateDirectory(strImagesFolderName);
            Directory.CreateDirectory(strHtmlFolderName);
        }

        /// <summary>
        /// Calculates the Intensity of each given pixel
        /// </summary>
        /// <param name="color">the image pixel</param>
        /// <returns>the Intensity</returns>
        public static int GetIntensity(Color color)
        {
            return (int)(0.3f * color.R + 0.59f * color.G + 0.11f * color.B);
        }

        /// <summary>
        /// Retrieves the available images that should be converted
        /// </summary>
        /// <returns></returns>
        public static String[] GetImages()
        {
            return Directory.GetFiles(strImagesFolderName + @"\", "*.jpg");
        }

        /// <summary>
        /// Converts a given image file to its matching html file
        /// in "pages" folder using "1st Intensity" value
        /// </summary>
        /// <param name="strImageName">Image to be converted path</param>
        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; // for switching between 1 and 0

            createdFileContent.AppendFormat(strHtmlFileHeader, strImageNameWithoutExtension, System.Windows.Forms.Application.ProductName);

            // looping through the image
            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);

            // save html output file in "pages" folder
            File.WriteAllText(String.Format(@"{0}\{1}.html", strHtmlFolderName, strImageNameWithoutExtension), createdFileContent.ToString());
        }

        /// <summary>
        /// Converts a given image file to its matching html file
        /// in "pages" folder using "Average Intensity" value
        /// </summary>
        /// <param name="strImageName">Image to be converted path</param>
        public static void ConvertImageToCharacterAverageIntensity(String strImageName)
        {
            Bitmap img = (Bitmap)Image.FromFile(strImageName);
            String strDigit = ""
                , strImageNameWithoutExtension = Path.GetFileNameWithoutExtension(strImageName);
            StringBuilder createdFileContent = new StringBuilder();

            int iAverageValue // intensity average value for each group
                , k = 0 // for switching between 1 and 0
                , iItemsCountInSubMatrix = iWidthRatio * iHeightRatio // the count of elements in group
                , iSubMatrixElementsSum; // the total value of group elements

            createdFileContent.AppendFormat(strHtmlFileHeader, strImageNameWithoutExtension, System.Windows.Forms.Application.ProductName);

            // looping through the image
            for (int i = 0; i < img.Height - 1; i += iHeightRatio)
            {
                for (int j = 0; j < img.Width - 1; j += iWidthRatio)
                {
                    iSubMatrixElementsSum = 0;
                    // looping inside the group
                    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));
                                }
                            }
                        }
                    }
                    // calculating the average intensity value
                    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);

            // save html output file in "pages" folder
            File.WriteAllText(String.Format(@"{0}\{1}.html", strHtmlFolderName, strImageNameWithoutExtension), createdFileContent.ToString());
        }
    }
}

History

  • v1.0 15/10/08

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. 

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)