Introduction

Behind the scenes: I like C# and I like ASCII art. So I asked myself if somebody has written some image to ASCII application in C#. I Googled but found nothing. I did image manipulation stuff for my company and so I decided to build a basic image-to-ASCII conversion library in C#.

I loop through the image's pixels and because I don't want one ASCII character per pixel, I take one per 10/5. To let every pixel influence the resulting ASCII char, I loop them and calculate the brightness of the amount.

That's all

Thanks to The Code Project and Chris Maunder, newtelligence and greetings to all C# coders out there.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Comments and Discussions

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

Create an Application in IIS (The windows web server) and drop the files there. Next call the URL of the application in your browser...

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

Howdy, I ported another ASCII art generator from this site to Ajax by using my companies Open Source Ajax library (Gaia) and the results can be seen here; ASP.NET ASCII Art generator Ajaxified
It's also open source and free to use as you wish

I'm currently trying to make your C# code into C++ but I'm confused as to why you use getpixel method (which returns pixel's rgb value) when in grayscale, one pixel is one byte (0-255). Can you tell me why this is necessary? I would think you'll just read the pixel value (grayscale) and calculate the brightness, which also confuses me. To calculate brightness (using algorithm from easyrgb.com), it requires, as you are doing, RGB values, but again, the grayscale is limiting me to one pixel one byte.

First of all Daniel, please. And it would have been nice if you have provided your name

1. GetPixel() returns the color of one pixel of your image.
2. GetBrightness() returns the brightness of this color

I just use a factor (* 100) and add all values i get from each segment, which is is a group of pixels that will be converted to a character. the sum of that calculation is divided and the amount of the second calc is used to decide which character will be used.

clear? Come back to me if not, k.

Daniel

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

First of all Daniel, please. And it would have been nice if you hav provided your name

1. GetPixel() returns the color of one pixel of your image.
2. GetBrightness() returns the brightness of this color

I just use a factor (* 100) and add all values i get from each segment, which is is a group of pixels that will be converted to a character. the sum of that calculation is divided and the amount of the second calc is used to decide which character will be used.

clear? Come back to me if not, k.

Daniel

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

While I understood your article and your explanation to my question, but your algorithm, whether because it's my pure c++ or steep learning curve, does not allow me to understand it. For instance you said you're getting a byte, but in MSDN getpixel returns the rgb color (even though image by this point is already in grayscale). GetBrightness returns 0 - 1 of HSV, which toHSV function I implemented from easyrgb.com returns a value within that range.

Perhaps you can look at my attempt (variables should be familiar) of porting your C# code:

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

As I understood You take a 10x5 sample of the picture for one Ascii char. I wrote a similar program a while ago, and wanted to do the same thing, but instead i thought that cropping the picture to a smaller size might be easier. That way i can use one Ascii per pixel:

Of coures you can do that - it's less calcualtion but also less detailed, right.

Daniel

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

I'm new here... I wonder, could you explain to me what kind of me
what kind of methods that you use to convert picture to ascii art...
I mean, for every step that you use... for grayscaling image, is that include
image compressing (what methods?) or that's vector quantitasing methods?

I think my article tells it already if you wan't more have a look at the source code.

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

There is an improvement you can make that may improve dramatiacly the image sharpness:

-You are calculating the correct ascii char only by the brightness. You could also calculate by it's shape. For example imagine that a "P" has the same brightness (or almost!) that of a "J". Which one u choose? It won't matter in most cases, but in border areas, it can make a lot of difference! If the correct char is chosen, it can dramatiacly improve sharpness. How can it be done? One approach would be looking for the pixel distribuition in each small sample area... One problem is that some non-border areas, it may look more fuzzy, so you could find the border areas first and just apply this criteria on those areas. To find border areas, just derive (i dont know if it is the correct english word) the image and then apply a B&W transformation with a variable threshold. Varying that threshold will be kind of a sharpness amount control.

kawzaki wrote:for a first thought, in .net applications made in different langages shall have no speed difference since all are compiled and translated to Microsoft ML.

year but ho it is translated matters, eh.

thx,

Daniel

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

Thx - i sent the updated code a while ago. I sent it again today. hope it will be updated soon.

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

Would you send me the vb sources to post them (including your name) here?

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/

# THIS CODE AND INFORMATION ARE PROVIDED
# "AS IS" WITHOUT WARRANTY OF ANY
# KIND, EITHER EXPRESSED OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE
# IMPLIED WARRANTIES OF MERCHANTABILITY
# AND/OR FITNESS FOR A PARTICULAR PURPOSE.
# http://www.lennybacon.com/