Click here to Skip to main content
15,891,423 members
Articles / Multimedia / GDI+
Article

Image to Characters Converter using Intensity

Rate me:
Please Sign up or sign in to vote.
4.60/5 (10 votes)
17 Oct 2008CPOL2 min read 37.1K   480   30   6
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)


Written By
Software Developer
Syrian Arab Republic Syrian Arab Republic
I'm currently studying IT engineering. My general computer skills can be outlined :

• Programming languages :
C/C++, C#, Databases(Oracle and MySQL), PHP, ASP.NET.

• Operating systems :
Windows and Linux

• Frameworks and environments :
Borland development environment (C++), Windows SDK/Shell/GDI, MFC

• Programs and tools :
Adobe Dreamweaver, Adobe Photoshop, Adobe Flash

• Also :
Web Development skills (HTML, CSS, Javascript).

I'm interested in computer vision applications. Also I'm giving some tries to OS programming.

I hope to gain both the applied and theoretical knowledge of image processing field.

Comments and Discussions

 
QuestionAny comments ?? Pin
Redwan Albougha17-Oct-08 15:42
Redwan Albougha17-Oct-08 15:42 
AnswerRe: Any comments ?? Pin
TobiasP20-Oct-08 23:52
TobiasP20-Oct-08 23:52 
GeneralRe: Any comments ?? Pin
Redwan Albougha21-Oct-08 4:04
Redwan Albougha21-Oct-08 4:04 
GeneralRe: Any comments ?? Pin
Redwan Albougha22-Oct-08 14:01
Redwan Albougha22-Oct-08 14:01 
GeneralRe: Any comments ?? Pin
TobiasP23-Oct-08 0:36
TobiasP23-Oct-08 0:36 
Well, the fact that the number of (printable ASCII) characters are less than the number of gray levels are easy so solve: You can for example map each interval of intensity level to a characters: Level 0-9 => A, level 10-19 => B, ..., level 250-255 => Z, etc., with adjustments for your selected set of characters of course.

One set of shapes would be directions, such as -/|\ to indicate that the image (or in this case, small part of an image) contains a line in the specified direction. I think calculating a (mathematical) vector describing the direction of an image is a fairly basic operation in image analysis.
GeneralRe: Any comments ?? Pin
Redwan Albougha23-Oct-08 0:49
Redwan Albougha23-Oct-08 0:49 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.