 |
|
|
 |
|
 |
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
-- http://ajaxwidgets.com - THE Open Source Commercial Ajax Component vendor for ASP.NET and Mono
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, i tried out your example it is great. Here is a question? Converting from Image to Ascii is fine, but what about Converting from Ascii to Image?
Naveen S.
-- modified at 8:13 Thursday 13th July, 2006
|
| Sign In·View Thread·PermaLink | 1.36/5 (7 votes) |
|
|
|
 |
|
 |
Mr. Fisher,
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.
Learning by doing
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Daniel,
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:
for(lheight = 0; lheight<height/10; lheight++) { startY = lheight * pixheight; for(lwidth = 0; lwidth<width/5; lwidth++) { startX = lwidth * pixwidth; brightness = 0; for(y = 0; y<pixwidth; y++) { tempval = startX*(y+startY); array[0] = rbuffer[tempval]; array[1] = rbuffer[tempval+1]; array[2] = rbuffer[tempval+2]; hsvValue = toHSV(array[0],array[1],array[2])*100; brightness += hsvValue; }
threshold = brightness/pixsegment;
if (threshold < 10 ) { ascii = '#'; afile<<ascii; } ....
HSV function:
float toHSV(int r, int g, int b) { float nr = float(r/255.0); float ng = float(g/255.0); float nb = float(b/255.0);
float min,max,delta,V; float H,S,dr,dg,db;
if(nr>=ng) { min = ng; if(min>=nb) min = nb; } else { min = nr; if(min>=nb) min = nb; } if(nr<=ng) { max = ng; if(max<=nb) max = nb; } else { max = nr; if(max<=nb) max = nb; }
delta = (max - min); V = max;
if(!delta) { H = 0; S = 0; } else { S = delta/V; dr = ( ( ( max - nr ) / 6 ) + ( delta / 2 ) ) / delta; dg = ( ( ( max - ng ) / 6 ) + ( delta / 2 ) ) / delta; db = ( ( ( max - nb ) / 6 ) + ( delta / 2 ) ) / delta;
if( nr == max ) H = db - dg; else if ( ng == max ) H = ( 1 / 3 ) + dr - db; else if ( nb == max ) H = ( 2 / 3 ) + dg - dr;
if ( H < 0 ) H += 1; if ( H > 1 ) H -= 1; }
return H;
}
Regards, Gabriel
Learning by doing
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
many ways lead to rome - the only question that matters if your algorithm.
Maybe it helps you to look at my code as c++
public: static System::String __gc * ConvertImage(System::IO::Stream __gc * stream, System::String __gc * ImageSize, System::String __gc * Quick) { System::Int32 num1; System::Int32 num2; System::String __gc * text2; System::Text::StringBuilder __gc * builder1 = __gc new System::Text::StringBuilder(); System::Drawing::Image __gc * image1 = System::Drawing::Image::FromStream(stream); System::Drawing::Bitmap __gc * bitmap1 = __gc new System::Drawing::Bitmap(image1, (image1->Width, image1->Height)); image1->Dispose(); System::Drawing::Rectangle rectangle1 = (0, 0, bitmap1->Width, bitmap1->Height); System::Drawing::Imaging::ColorMatrix __gc * matrix1 = __gc new System::Drawing::Imaging::ColorMatrix(); matrix1[0, 0] = 0.3333333; matrix1[0, 1] = 0.3333333; matrix1[0, 2] = 0.3333333; matrix1[1, 0] = 0.3333333; matrix1[1, 1] = 0.3333333; matrix1[1, 2] = 0.3333333; matrix1[2, 0] = 0.3333333; matrix1[2, 1] = 0.3333333; matrix1[2, 2] = 0.3333333; System::Drawing::Imaging::ImageAttributes __gc * attributes1 = __gc new System::Drawing::Imaging::ImageAttributes(); attributes1->SetColorMatrix(matrix1); System::Drawing::Graphics __gc * graphics1 = System::Drawing::Graphics::FromImage(bitmap1); graphics1->DrawImage(bitmap1, rectangle1, 0, 0, bitmap1->Width, bitmap1->Height, System::Drawing::GraphicsUnit::Pixel, attributes1); graphics1->Dispose(); if ((text2 = ImageSize) != 0) { text2 = System::String::IsInterned(text2); if (text2 != S"1") { if (text2 == S"2") { num1 = 2; goto Label_0162; } if (text2 == S"4") { num1 = 6; goto Label_0162; } if (text2 == S"5") { num1 = 8; goto Label_0162; } } else { num1 = 1; goto Label_0162; } } num1 = 3; Label_0162: num2 = (num1 * 2); System::Int32 num3 = (num1 * num2); for (System::Int32 num4 = 0; (num4 < (bitmap1->Height / num2)); num4++) { System::Int32 num5 = (num4 * num2); for (System::Int32 num6 = 0; (num6 < (bitmap1->Width / num1)); num6++) { System::Int32 num7 = (num6 * num1); System::Int32 num8 = 0; if (Quick == S"True") { for (System::Int32 num9 = 0; (num9 < num1); num9++) { try { System::Drawing::Color color1 = bitmap1->GetPixel(num7, (num9 + num5)); System::Int32 num10 = *static_cast<__box System::Int32*>((color1.GetBrightness() * 100)); num8 += num10; } catch (System::Object __gc * obj1) { num8 += 50; } } } else { for (System::Int32 num11 = 0; (num11 < num1); num11++) { for (System::Int32 num12 = 0; (num12 < num2); num12++) { System::Int32 num13 = (num11 + num5); System::Int32 num14 = (num12 + num7); try { System::Drawing::Color color2 = bitmap1->GetPixel(num14, num13); System::Int32 num15 = *static_cast<__box System::Int32*>((color2.GetBrightness() * 100)); num8 += num15; } catch (System::Object __gc * obj2) { num8 += 50; } } } } System::Int32 num16 = (num8 / num3); if (num16 < 10) { builder1->Append(S"#"); } else if (num16 < 17) { builder1->Append(S"@"); } else if (num16 < 24) { builder1->Append(S"&"); } else if (num16 < 31) { builder1->Append(S"$"); } else if (num16 < 38) { builder1->Append(S"%"); } else if (num16 < 45) { builder1->Append(S"|"); } else if (num16 < 52) { builder1->Append(S"!"); } else if (num16 < 59) { builder1->Append(S";"); } else if (num16 < 66) { builder1->Append(S":"); } else if (num16 < 73) { builder1->Append(S"\'"); } else if (num16 < 80) { builder1->Append(S"`"); } else if (num16 < 87) { builder1->Append(S"."); } else { builder1->Append(S" "); } } builder1->Append(S"\n"); } bitmap1->Dispose(); return builder1->ToString(); }
# 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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi, nice work.
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:
Graphics g = Graphics.FromImage(bmpblock); // Crop image g.DrawImage(bitmap, new Rectangle(0,0,bmpblock.Width,bmpblock.Height),0,0, bitmap.Width,bitmap.Height,GraphicsUnit.Pixel);
g.Dispose();
where bitmap is the original (grayscaled) image and bmpblock is the resized image.
Cheers ac
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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 am waiting for your answer. Thank you so much.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Hi. First of all, nice article 
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.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
I always thought that it was done this way, but you actually showed that it was. Nice work. Good, fun article.
Microsoft makes Digital Photos fun with Photo Story 3 and its free.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
really nice job.
i would like to test the VB.net version too. 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.
and knowing DESKTOP APPLICATIONS are faster than web based applications, there must be something that causes the delay and makes it run slower.
the spanish version with colors seems wonderful. hopefully u can include that as an option in your project too 
Great work.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
kawzaki wrote: i would like to test the VB.net version too.
Me to.
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
yeah, I don't understand how to put on the add in. atleast, I tried to use the files you provided, and visual studio would throw errors when trying to set them up as add ins.
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
Who ever talked about an Add in?
# 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/
|
| Sign In·View Thread·PermaLink | 5.00/5 (1 vote) |
|
|
|
 |
|
 |
Check against same value in your code :
else if (_sb < 60) { _asciiart.Append("~"); } else if (_sb < 60) { _asciiart.Append("·");
Regards 
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
 |
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/
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
 |
Your suggestion is painfully simpler than what the author is doing in this article. I did this back in high school after I learned how to read bmp files. On the fly vb.net air code (i.e. untested):
Public function BmpToHTML(Bitmap Bmp) As String Dim rgb As Integer Dim c As Color Dim x As Integer, y As Integer Dim str As String
str = "<TABLE BORDER=0 WIDTH=" & (Bmp.Width() * 2).ToString() & " HEIGHT=" & (Bmp.Height() * 2).ToString() & " CELLPADDING=0 CELLSPACING=0>"
For y = 0 to Bmp.Height - 1 str = str & "<TR>"
For x = 0 to Bmp.Width - 1 c = Bmp.GetPixel(x,y) str = str & "<TD BGCOLOR=""" & [Color].toHtml(c) & """ WIDTH=1 HEIGHT=1></TD>" Next x
str = str & "</TR>" Next y
str = str & "</TABLE>"
BmpToHTML = str End Function
|
| Sign In·View Thread·PermaLink | |
|
|
|
 |
|
|
 |
|
|
 |