65.9K
CodeProject 正在变化。 阅读更多。
Home

使用强度将图像转换为字符

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.60/5 (9投票s)

2008年10月14日

CPOL

2分钟阅读

viewsIcon

38052

downloadIcon

511

本文档展示了如何使用数字 1 和 0 来显示图像。

引言

主要思想是读取图像每个分组的强度值。(这里所说的分组是由相邻像素组成的矩阵。)然后写入数字 1 或 0,其颜色值是源分组的平均强度值。

背景

首先,我们需要区分强度值的获取方式。在本文中,我将展示两种方法:

  1. 第一种强度方法(提供更好的视觉效果):在这种方法中,强度值从分组的第一个像素获取。
  2. 平均强度方法:在这里,我们计算每个分组的平均强度值。

在两种方法中,获取强度值后,我们都会写入数字 1 或 0,其颜色值就是我们获取到的值。

上述机制应用于图像,通过将其读取为矩阵(二维数组)。注意,遍历数组的方式是“对于图像的每一行,访问每个像素”。

下图显示了两种方法之间的差异

WindowsLogo.jpg
原始图像

 

WindowsLogoDigits.gif WindowsLogoDigits.gif
第一种强度方法 平均强度方法

Using the Code

Tools
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());
        }
    }
}

历史

  • v1.0 15/10/08

注意事项

  • 由于我的代码实现的原因,只有以“jpg”扩展名结尾的图像才被接受。
  • 我选择的分组大小为 12 行和 5 列。如果您没有获得所需的结果,可以更改这些值。或者,您可以将其设置为 1 行和 1 列,这将把每个像素映射到一个数字;当然,这将生成更大的图像。
  • 该项目使用 C# 2.0,但在 Visual Studio 2008 中编写。
  • 我根据我的实际尝试编写了“第一种强度方法”,这意味着它不是参考性的,与“平均强度方法”相反,后者是一种简单且众所周知的方法。但我更喜欢编写“第一种强度方法”,因为它显示了更好的结果。

改进

  • 将分组大小与源图像的大小相关联。 这种改进将减少源图像较小时出现不良结果的情况。 例如:宽度 = 80~110px。
© . All rights reserved.