One of the trickiest modules in JavE is the image2ascii converter with its automatic conversion algorithms. Currently one can choose from about 9 different algorithms for conversion. As a lot of things can be adjusted, it should be no problem to spend some hours just playing around with the conversion options... I am asked quite often for information about those conversion algorithms and so I have decided to write this document. It started as a posting to a newsgroup (alt.ascii-art) in May 2002 and I try to extend it as I have time and inspiration.
If you have any questions or comments, feel free to contact me: markus@jave.de
low resolution:##### #### ## ##### # # # # # ## # # # # # # # #### ## # |
higher resolution:88888 8888 d8b 88888 8 8 ]b 8 8 88 Yb 8 8 8 o d8 8 8 8888 YP 8 |
Pattern: | .. .. |
.X .. |
X. .. |
.. X. |
.. .X |
XX .. |
.. XX |
X. X. |
.X .X |
.X XX |
XX .X |
XX X. |
XX XX |
Character: | ` |
' |
. |
, |
" |
_ |
( |
) |
J |
L |
7 |
P |
8 |
Note that there is also a tutorial about how they (and some simple greyscale algorithms) work in the www at [1].
![]() |
![]() |
##@H@@@ku=;^^?:^;;;;:^...`````;p#Ny=HHH NHHgH#fr;^;^.:lrrt?:^^^....``.;p#M@;m@H NNHHHz?:.^:=uyZyybfyl?;^..^=Zbbk@NH=yH@ gHN@r:^..?kH@@Hb?pqzvl?^`?mHkuH##NHtZ@@ NMqr;^.;rvtZyZZ;^;tzvt?``rvulz@H##@zrkH Mpt:.;Zut=????=?;;?ttr=.`:?lvyyg#H@Z?mH yt^^fgZvt=?::^^::;?=ttt^ ^;?trzkHH@p;mN t.;HHkurtl?;;::::;=ltrt; .;?ltu@#HHg?ZN :vMNmqZrtl=??;;;;?trtvr?``??lrpNHgHH?tN fNNNpkZvrtl=???;?=rruuut^^==tyHNH@HNr=@ #H##yfuvrtl===??;??=l??^^;=lZHNH@mH#p=b |
`.^.` .^ ..` `. ` ``..^.` .?fr?^..^.^;;:` `` ``?yp@@@@b=.?yVfppZ^^lvrt?. .@#@NHNNNV`.=pg@gfrtyVVyyyu=` :NMMNHfrl. ?yZyyy?.^^^. ?kHp. ` .Zyfyfr. ^=;. |
"state of the art"-algorithms use more than 1 pixel per character and the result shows more details. Here are the same examples using a 4 pixel per character algorithm:
MMMMHNNM0C++^+;.++++:+.....`` ?WMMKjMMH MMMHNMBZ+!+!^.+A&&++::..^^.....dMNN+HM@ N#NHMSC+``!JdAQmgkWHw++.^^.JXWmkH#MIdM@ mMMMZ+!`.JWMMMM#?WMwwOz` .HMHTMHHMMrdHH MM#Z+!..wwOTHXU+.?Owzwz`.UZUCjHMMMHPdkM NEZ!`.X0t=z111z1++1OtvI. ?1OwUWHMMMb?mH EZ!.+MXvtzz;;::::+1lOrO!`.+1trwWH@Mb+HM Z`.MMHXvrl=?;::;;+zlOvOz .+=lrwHHMM#+d# :JNMHHXvrtl=1++;?1OwOzwz. ==trXMHgMNzvM iMMMWHXzrtll=????zwwQAww+.=lOdMMMHMMZzM M@MMXHXzvrtll=????=zOI1!`+zOQMHMMHMMbjU |
.?! .` ..` . ....`` ..Q+.,...``+.. .JWHHHHR+..dXXkWk,.Juu&.. dNHMMMMM@ `"BHHHB6JXWWXXXX&. .MMMMMB"7! .XXXWX|`??!` 7WMY^ XWWXWY' ?7=! |
Simple 1 pixel per character algorithms use a "greyscale gradient" or "greyscale ramp" defined by ordering all or only a few characters depending on their brightness. Here are two examples of greyscale gradients only containing a few characters:
.:OI#M |
.:oO8@ |
A more sophisticated strategy is to create a greyscale table containing brightness values for each character in a font. Most converters only have one greyscale table derivated from the font the author of the program has used when writing the algorithm. JavE however now contains about 20 character tables containing greyscale values for the 1 and 4 pixel algorithms for different fixed width fonts.
For converting to a bigger result (>100 characters wide) it is a good idea to also use features like error diffusion (with 1-pixel algorithms) or to combine both of the above algorithms (and maybe to use some other tricks). An algorithm doing that can be found in version 5.0 (or greater) of JavE. As with that I believe that the limit of what can be achieved with pure greyscale algorithms has be reached.
In fact I only know about two of those algorithms. There is a very simple one for edge tracing, but it is so simple that it is more like cheating than a real algorithm:
![]() |
______ ________ _/ \_ _/ \___/ \ /__ __ __\ // \/ _| | _/ _ \ / / | _ | / __ | \ | \_ / |__/ | / \__ | \ \ | | \_/ / / / | | / | | / | | | | | | | | |_ /_ ___\ \ |
It is not hard to find out how the algorithm works. Here is the pseudocode, I have once posted it to the newsgroup along with more demo images [4]:
FOR ALL PIXELS x,y IN THE IMAGE DO: IF IS_SET(x,y) IF NOT_SET(x-1,y) AND NOT_SET(x,y-1) PRINT / ELSEIF NOT_SET(x+1,y) AND NOT_SET(x,y-1) PRINT \ ELSEIF NOT_SET(x-1,y) AND NOT_SET(x,y+1) PRINT \ ELSEIF NOT_SET(x+1,y) AND NOT_SET(x,y+1) PRINT / ELSEIF NOT_SET(x,y+1) PRINT _ ELSEIF NOT_SET(x-1,y) OR NOT_SET(x+1,y) PRINT | END ELSEIF IS_SET(x,y+1) AND IS_SET(x-1,y+1) AND IS_SET(x+1,y+1) PRINT _ END ENDAs JavE also contains some optimizing algorithms for line drawing I have managed to slightly improve the result by some kind of filtering the ascii art after conversion:
![]() |
______ ________ _/ \_ _/ \___/ \ /__ __ __\ // \/ _| | _/ _ \ / / | _ | / __ | \ | \_ / |__/ | / \__ | \ \ | | \_/ / / / | | / original | | algorithm / | result | | | | | | | |_ /_ ___\ \ |
______ ________ ,' `. ,' `-._/ \ /__ __ __\ /' \/ _| | ,' _ \ / / | _ | / __ | \ | `. / |,-' | / `-. | \ \ | | \_/ / / / | | / result when | | running some / | optimizing | | algorithm afterwards | | | | | |_ /_ ___\ \ |
Finally there is a very complicated real edge detection algorithm:
,--.---. / -'''''-._ .-' -\ '| _ L' ../-- <'' `'' '| '-. ,-' U :\_ | v- /`. ``. | / ,'| | | |'`|./ /_,,' / | `._ | - ' | | `'| .- | | .' | | | | | | | | | | | .' | _ _ ]_, |
I think (for beginners) it is a good idea to convert an image trying to find a good algorithm. Then paste the result into your favorite text editor and make changes by hand until it looks best.
::::d88 :::d888 ::d8888 |
::::/88 :::/888 ::/8888 |
-
+ |
= +
o
+ d
= d
/
+ \
= X
But this algorithm is only defined for about 200 combinations and there are about 90x90=8100. Also first tests have shown that it does not work that well [4]...
(BTW: More often than once I have considered creating a very simple plugin architecture for JavE, so that everybody with basic Java programming skills can easily write his/her own conversion algorithm, w/o having to care about loading, scaling and preprocessing images etc. Is there any need for this or is implementing it just wasted time?)