• [Release] ASCII Art Generator
    26 replies, posted
Well, I got it to a usable state so I figured I should release it. Please post any comments and criticism you have, I want to hear it! Also, post any cool images you come up with. Download: [url]http://www.mediafire.com/?mzjbe0t03hm[/url] (Poodle's request): I wrote it in C#, using VS2010. I can release source code if you like, I just haven't gotten around to uploading it all yet. Edit: Source is uploaded [url]http://www.mediafire.com/?ztyyhzynjow[/url] Edit: My girlfriend had a go, came up with this (click for full-size) [img_thumb]http://www.cubeupload.com/files/4d1c00untitled.png[/img_thumb] I thought it was quite cute :v:
What language? Any information?
Of course, sorry. Updated the OP.
If you type a scale that isn't an integer it complains about it not being between 0.1 and 4.0. Maybe it's just me tho... :v:
Really good, Here's one I really like: [img_thumb]http://www.cubeupload.com/files/7bce00blu.png[/img_thumb] Edit: This one too: [img_thumb]http://www.cubeupload.com/files/259000guitar.png[/img_thumb]
Pretty sweet, good work!
Since you didn't bother with smoothing, I implemented it. My Program.cs: [cpp]*using System; using System.IO; using System.Windows.Forms; using System.Drawing; namespace ASCII_Generator { static class Program { /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Setup mySetup = new Setup(); if(mySetup.ShowDialog() != DialogResult.OK) return; string shades = mySetup.CharSet; float ixscale = 1 / mySetup.XScale, iyscale = 1 / mySetup.YScale; OpenFileDialog ofd = new OpenFileDialog(); ofd.Title = "Select input file"; ofd.Filter = "Supported image files|*.bmp;*.gif;*.jpg;*.jpeg;*.png;*.ico"; if (ofd.ShowDialog() == DialogResult.OK) { // Choose a save location and setup the file stream SaveFileDialog sfd = new SaveFileDialog(); sfd.Filter = "Text files|*.txt|All files|*.*"; if(sfd.ShowDialog() != DialogResult.OK) return; FileStream fs = new FileStream(sfd.FileName, FileMode.Create); StreamWriter sw = new StreamWriter(fs); Bitmap image = new Bitmap(ofd.FileName); // Iterate over each pixel for (float fy = 0; fy < (float)image.Height; fy += iyscale) { int y = Convert.ToInt32(fy), ycount; float yfract, iyfract; if(y >= image.Height) { y = image.Height-1; ycount = (int)Math.Floor(fy) - y; yfract = 0; iyfract = 1; } else { ycount = (int)Math.Ceiling(iyscale); yfract = (float)Math.Ceiling(fy) - fy; iyfract = 1 - yfract; } for (float fx = 0; fx < (float)image.Width; fx += ixscale) { int x = Convert.ToInt32(fx), xcount; float ul, ur, ll, lr; //upper-left, upper-right, lower-left, lower-right if(x >= image.Width) { x = image.Width-1; xcount = (int)Math.Floor(fx) - x; ul = iyfract; ur = yfract; ll = 0; lr = 0; } else { xcount = (int)Math.Ceiling(ixscale); float xfract = (float)Math.Ceiling(fx) - fx, ixfract = 1 - xfract; ul = ixfract * iyfract; ur = ixfract * yfract; ll = xfract * iyfract; lr = xfract * yfract; } float avShade = 0; for(int smoothy = y; smoothy < Math.Min(fy + iyscale, image.Height - 1); ++smoothy) for(int smoothx = x; smoothx < Math.Min(fx + ixscale, image.Width - 1); ++smoothx) { avShade += image.GetPixel(smoothx, smoothy).GetBrightness() * ul; avShade += image.GetPixel(smoothx + 1, smoothy).GetBrightness() * ur; avShade += image.GetPixel(smoothx, smoothy + 1).GetBrightness() * ll; avShade += image.GetPixel(smoothx + 1, smoothy + 1).GetBrightness() * lr; } int count = ((ul == 0) ? 0 : 1) + ((ur == 0) ? 0 : 1) + ((ll == 0) ? 0 : 1) + ((lr == 0) ? 0 : 1); //how many did actually contribute? avShade /= count * xcount * ycount; avShade = shades.Length - avShade * (shades.Length - 1) - 1; sw.Write(shades[Convert.ToInt32(avShade)]); } sw.WriteLine(); } sw.Flush(); sw.Close(); } } } }[/cpp] I also replaced your spaces with tabs, removed the temporary string and instead write directly to the file as well as removing the temporary string for the filename. I read on this forums that it's faster to access pixel data with unsafe code, so you could look into that to make it faster. I probably should but a bunch of comments on my algorithm, I don't think it's too easy to follow without them. I might add some after I slept; if there are any questions about it I'd be pleased to answer :) The difference of befores version and my smoothing version: no smoothing/before: [img_thumb]http://anyhub.net/file/1before.png[/img_thumb] smoothing/after: [img_thumb]http://anyhub.net/file/1after.png[/img_thumb] reference picture: [img_thumb]http://a778.ac-images.myspacecdn.com/images01/78/l_b0370fea0387d4937c33a183e8880869.png[/img_thumb]
[QUOTE=ZeekyHBomb;22033590]Since you didn't bother with smoothing, I implemented it. My Program.cs: *code* I also replaced your spaces with tabs, removed the temporary string and instead write directly to the file as well as removing the temporary string for the filename. I read on this forums that it's faster to access pixel data with unsafe code, so you could look into that to make it faster. I probably should but a bunch of comments on my algorithm, I don't think it's too easy to follow without them. I might add some after I slept; if there are any questions about it I'd be pleased to answer :) The difference of befores version and my smoothing version: no smoothing/before: [img_thumb]http://anyhub.net/file/1before.png[/img_thumb] smoothing/after: [img_thumb]http://anyhub.net/file/1after.png[/img_thumb] reference picture: [img_thumb]http://a778.ac-images.myspacecdn.com/images01/78/l_b0370fea0387d4937c33a183e8880869.png[/img_thumb][/QUOTE] Images aren't loading for me. Also, I know unsafe code is faster for accessing pixels, but this thing is so fast anyway, I didn't think it was worth it :P Thanks for the replies!
[QUOTE=Chris220;22038448]Images aren't loading for me.[/QUOTE] Works for me.
XD Thanks for updating the post, this is really cool XD
[QUOTE=turb_;22038664]Works for me.[/QUOTE] Yeah I see them now. [editline]12:11PM[/editline] [QUOTE=Dj-J3;22030386]If you type a scale that isn't an integer it complains about it not being between 0.1 and 4.0. Maybe it's just me tho... :v:[/QUOTE] That's odd... Works fine for me :O What OS are you on? And which .NET framework?
[QUOTE=Chris220;22039912]Yeah I see them now. [editline]12:11PM[/editline] That's odd... Works fine for me :O What OS are you on? And which .NET framework?[/QUOTE] Windows 7, .NET Framework 3 [editline]02:18PM[/editline] [QUOTE=Chris220;22039912]That's odd... Works fine for me :O What OS are you on? And which .NET framework?[/QUOTE] Oh wait, it works if i type "," and not ".". :v:
[QUOTE=Dj-J3;22040571]Oh wait, it works if i type "," and not ".". :v:[/QUOTE] Ah, that's a Windows setting, whether you use , or . for decimal point notation. I'm not sure how you change it :P
I can use both in Linux :buddy: Though if I use the , then it will just be parsed as 5 o.O I guess I broke something when I installed LXDE upon Openbox. [editline]04:38PM[/editline] Alright, so here's a fixed and improved version of my smoothing asciiart generator. [url]http://anyhub.net/file/asciiart.zip[/url] Includes binary compiled with Mono 2.4.4 (should run on .NET 3(.5?) or higher as well) and source-code. Additions apart from the smoothing are individual x and y scaling, a bigger default charset and radio-buttons to tell the program if the charset is ordered from dark to bright or the other way. [editline]04:38PM[/editline] Aww, no bump :( [editline]04:42PM[/editline] I also wanted to profile my code, but MonoDevelop doesn't include a profiler ._. SharpDevelop <3 Too bad there's no official Linux port.
GetPixel vs unsafe code: unsafe version: [code]z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.671s user 0m0.540s sys 0m0.090s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.647s user 0m0.600s sys 0m0.030s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.667s user 0m0.590s sys 0m0.050s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.650s user 0m0.580s sys 0m0.050s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ [/code] GetPixel version: [code]z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.654s user 0m0.580s sys 0m0.070s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.664s user 0m0.530s sys 0m0.110s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.697s user 0m0.660s sys 0m0.020s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ time mono ./smoothing_asciiart.exe real 0m0.686s user 0m0.590s sys 0m0.070s z33ky@mobileblahbuntu:~/Projects/smoothing_asciiart/smoothing_asciiart/bin/Release$ [/code] Conclusion: Almost the same; difference negligible. Unsafe code might just make a difference when writing to the pixels. And a link to a version with more accurate brightness calculation and minor improvements (detecting if the file could not be opened, yay): [url]http://anyhub.net/file/2asciiart.zip[/url] Again includes binary and source. Edit: Fixed rounding-issue that would cause an IndexOutOfRangeException. Link updated.
Actually quite cool.
--------------------------- --------------------------- Error: Scale must be a numerical value between 0.1 and 4.0 --------------------------- OK --------------------------- Sigh, its a valid nunber. runnig Vista without UAC [editline]08:42PM[/editline] Figured it out, had to use 1,0 instead of the default settting: 1.0
It just picks a symbol for the greyscale of a pixel, yes? It should actually find edges and shit. That'd be awesome.
Why would you make it do that though?
It'll look like hand-created ASCII-art (Better)?
Ahhh right yeah I get what you mean now. Also that mean you could change settings to thicken lines etc.
Wow, this is really cool. Thanks.
[QUOTE=Tobba;22045990]--------------------------- --------------------------- Error: Scale must be a numerical value between 0.1 and 4.0 --------------------------- OK --------------------------- Sigh, its a valid nunber. runnig Vista without UAC [editline]08:42PM[/editline] Figured it out, had to use 1,0 instead of the default settting: 1.0[/QUOTE] Hmm yeah, someone else had that issue. I wish I could fix it on my end :/ Sorry :) [editline]09:49PM[/editline] [QUOTE=Mindtwistah;22047694]Wow, this is really cool. Thanks.[/QUOTE] Thank ye :) And, you're welcome
Maybe you can somehow detect which one the system needs and then just replace the , or . with the appropriate one.
Just replace commas with decimal points.
Well I for example need points. Dj-J3 and Tobba on the other hand need commas for it to work. [editline]11:34PM[/editline] Actually a point [i]should[/i] be the one working fine: [url]http://msdn.microsoft.com/en-us/library/system.globalization.numberformatinfo.numberdecimalseparator.aspx[/url] I guess you could try to explicitly tell it the format and see if that works. Edit: For future use: It's probably be better to use NumberFormatInfo.InvariantInfo instead of cloning NumberFormatInfo.CurrentInfo. It's not in the code of the zip-archive from down there, that small change is not work re-uploading it ;) [editline]11:41PM[/editline] Works. [url]http://anyhub.net/file/3asciiart.zip[/url]
Fixed accidentally (and partially) broken smoothing and throwing of an ArgumentException when the scale cannot add up to the image resolution (e.g. xscale is 2 and the image has a width of 3; 1 * 2 < 3 > 2 * 2). [url]http://anyhub.net/file/5asciiart.zip[/url]
Sorry, you need to Log In to post a reply to this thread.