Original Usenet thread from alt.ascii-art, started 26 Mar 2001.
_ _ _ _ _ _ | | | |___ ___ _ __ ___| |_ / \ _ __ ___| |__ (_)_ _____ | | | / __|/ _ \ '_ \ / _ \ __| / _ \ | '__/ __| '_ \| \ \ / / _ \ | |_| \__ \ __/ | | | __/ |_ / ___ \| | | (__| | | | |\ V / __/ \___/|___/\___|_| |_|\___|\__| /_/ \_\_| \___|_| |_|_| \_/ \___|
-Very Simple Java JPG to ASCII Converter
alt.ascii-art
· 6 messages · 26 Mar 2001 - 27 Mar 2001
// Very simple JPG to ASCII converter.
// Written on a saturday night by Heinz Flug .. flu...@online.no
// The code cries out for improvement....
import java.awt.image.BufferedImage;
import java.io.*;
import com.sun.image.codec.jpeg.*;
public class Application1 { // Application1 -- good name, isn't it?
public static void main(String[] args) {
int brightnes = 100;
String fName = "C:/XXX"; // <- Put your filename here..
BufferedImage img = readJPEGImage(fName+".jpg"); // Read the JPG Image
int h = img.getHeight();
int w = img.getWidth();
// Some debug information:
System.out.println(fName+".jpg"+'\t'+"Heigth = "+h+'\t'+"Width = "+w);
// No more dubug info..
String line = null;
writeText(fName+".txt", "", false);
for (int y=1; y<h-2; y=y+2) { // an ASCII char is about
line =""; // 1 pixel wide og 2 pixels high
for (int x=1; x<w; x++) { // (or mabye not..)
int pixel=(getGreyValue(img.getRGB(x,y))+
getGreyValue(img.getRGB(x,y+1)))/2;
pixel = pixel * brightnes / 100;
line = line + getASCIIChar(pixel); //Build line by line..
}
writeText(fName+".txt", line, true); // ..and write it to a txt file
}
}
public static BufferedImage readJPEGImage(String filename) {
BufferedImage image = null;
try { // read the JPG file and return it as an image..
FileInputStream fis = new FileInputStream(filename);
JPEGImageDecoder decoder = JPEGCodec.createJPEGDecoder(fis);
image = decoder.decodeAsBufferedImage();
fis.close();
}
catch (FileNotFoundException ex) {
System.out.println(ex);
System.exit(0);
}
catch (IOException ex) {
System.out.println(ex);
System.exit(0);
}
return image;
}
public static int getBValue(int rgb) {
return rgb & 0x00FF; // Some sort of magic..
}
public static int getGValue(int rgb) {
return (rgb & 0x00FF00) / 0x100; // another kind of magic..
}
public static int getRValue(int rgb) {
return (rgb & 0x00FF0000) / 0x10000; // pure voodoo..
}
public static int getGreyValue(int rgb) {
return (getRValue(rgb)+ getGValue(rgb) + getBValue(rgb))/3;
}
public static String getASCIIChar(int v) {
String charSets[] = {
"Wmi;. ", // char set #0
"#*+-' ", // char set #1
"@- ", // char set #2
"81: ", // char set #3
"01 ", // char set #4
"81:' " }; // feel free to add whatever you like.
String charSet = charSets[3]; // Choose one of the "character sets".
if (v<0) v = 0; if (v>255) v = 255; // Maybe a good thing to do?
int charPos = v/(1+(255/charSet.length())); // Calculate ASCII char
return charSet.substring(charPos, 1+charPos); // and return it.
}
public static void writeText(String tfile, String txt, boolean append) {
try {
PrintWriter pw = new PrintWriter(
new BufferedWriter(
new FileWriter(tfile,append)));
pw.println(txt); // appends lines to a text file.
pw.close();
}
catch (IOException e) {
System.out.println(e);
System.exit(0);
}
}
} // That's almost all...
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::1:1:::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::11::8:::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::1:1111:8::::::::::::::::::::::::::::::::
:::::::::::::::::::::::11:::::::::::::::11881881:::::::::::::::::::::::::::::::
:::::::::::::::::::::::111:1::::::::::::::181:1811::::::::::::::::::::::::::::::
::::::::::::::::::::::::818111::::::::::::11::18::::::::::::::::::::::::::::::::
:::::::::::::::::::::::1:18811:::::::::::::::11:::::::::::::::::::::::::::::::::
:::::::::::::::::11111:18111811:::::::::::::::1:1:::::::::::::::::::::::::::::::
1:::::::::::::::::11:1111111:::::::::::::::::1::::::::::::::::::1:::::::::::::::
8818:::::::::::::888111188:11:::::::::::::::::::::::::::::::::11::1:::::::::::::
8188:1::::::::::18888881:1::::::::::1:1::::::::::::::::::::::1:::111::::::::::::
881:11:::::::::1: 888811:::::::::::::::1:::11:::1::::::::1111:111:1:::::::::::::
::::::::::::::::::881:: : : ::::::::::::::::::::::::::: : : :: ::::::::::::
1:::::::::::::::::8:: : :::::::::::::: : : : : ::1:::1
81:::::::::::::::1: ::::::: : :::: :::: 111::
111811:::::::::::8: :::: :: ::1:::
811181:1::1:::::::: ::: : ::::1::
1881:888811:::::::: :: ::: :::11:
:881::118818111:::::: :: :::::::::11
18181::::88188881811: ::::::::::::::
118181:::1188888881: :::::::::::::
:118888::::::11881: ::::::::::::1
1:111888888888:: :::::::::::111
:::1:1888881: :::::: :::::::::::::1
::::1888881 : :1811:1 : :::1:1118881111181: : ::::::::11::
::111188881:::881::8188881:::: :::11:: ::18: :::::::::1::
:1188118888 :8: ::1:1:: : : :::881:::::1:11:8
8:111181888:8: ::1:1:: ::: : : : : : :181:11:::: 1
8881:18888811: ::: ::11: ::: ::11:::::::11111::::::
:11881:188818881:: ::::: :: ::: : ::: : 11:::11111:11::::
:1111:1:1881818181888888881::1 : :1111818188111:1::11:::::1::::: 1
1:1888:::88::1888888:181:: ::: :11111818111: :::1:::::1
8 81888::11: :881:: : : :1111:: ::::::::111
8::81881:1: :::::1:::1:8
81111:1:1: :::1:1::1:18
1881::::111 :::::111:1:88
8181:::::18: :: ::: : :::1111111188
8888:::::181: : ::::: ::::::11188118111
11:1::::::11: ::: ::::: :: :::::181188181181
11::::::::811: :111::::111881:::1 :::::11181818818:1
:::::::81181: 8818811188111181: ::::::11118181111 11
1811818811:: :::1:::: :::::111181888181::1:
188888111::: ::: : 1: :::::::11111811888:::11
188181111:: ::: :::::: : :: ::::::::1:11111181118188
:888:1:181:: :111111181111111881811:: :::::::::::111111881811:
111811:8:: : :188818881:111::8:188181811: : :::::::::1118188811:88
: :18881:1:: :181111 1:81181: : :: ::::::::1111188881818
: :1111:11:: 88118:1 :1:188111 : ::::::::1118881818::
:1188881:::::: ::: :88811111::1111811881: :: :: ::::::::::1118188881888
: ::18818111:::: ::: :81881111111181811 : ::::::::::::::111118188888188
111118181:::::: :: :11888888811:: :: ::::::::::::::::111881181818888
: :1811811::::::: : :: : :: ::::::::::::::::11188818881181811
8181881:::: : ::::::::::::::111111118188818::::11
::11111881::: ::::::::::::::::::1111188181188181:::::::
:::11:118111::: ::::::::::::::11111888881111111::::::::
::::::::::1811::::: :: : : ::::::::11111188888888111111181::::::::
:: : : :::8881:::::: :::: ::::::::1111188881888818181118181::::::::
:: : : : 8188811111111111111111818188181181181181111111:81::::::::
: : :::::: ::: 88188888118181818818888888818118118118111:::1:18:::::::::
:: : ::: :::::::::: 18888188888188818888888888881888188111:::::::1:8 ::::::::
:::::::::::::::::::::: :1181118888888888888888888188888111:::(c) Heinz Flug 2001
--
.hF
http://home.online.no/~flug/
Heinz Flug wrote: > > // Very simple JPG to ASCII converter. > // Written on a saturday night by Heinz Flug .. flu...@online.no > // The code cries out for improvement.... Cool, but you should mention that your code needs Java2 and will not run in Java 1.1. If your looking for improvement, I have an improved piece of Java work: Jave. It has a much more complicated image2ascii algorithm included. I have written and designed it from scratch and I think one should have had a look at it: http://www.jave.de regards, Markus PS: I do not plan to make my source codes public, but I would be glad to hear your opinions and discuss about image2ascii conversion. PPS: Here is a sample: MBMMMMMEmMmmyMMTxZ0-:---(x>:--(({zv=>::------` . -3XMMMMBB(J#MMBMM MBMBMmMMMBMMmZSxf=cz(---(3>-(zz====:((((--------. .(d#MMMB#i(#BMBMB MBMEMB#MBMMMTgF%(=>>{~----(awxz>>>::(-(((---------.. .(4mMMMMBm(dMMMMM MMMEMEmMMMMSg+:::-(z=---(d@99#SmQQga--(((:--------`...__ggMMMMBBE-3MMBMM MMMMmQMMMWn2%(>--(z>-_JQQxxwy{4ZZ@MM#Q{(>((-------(ag##H#QQMMMMBB-zdMBMM MMMMMMMMT4f:(:-._(-(aMmmMMMMMmMMmQDZZZOxoz>---`--ugQgMMMMMBMMMMEM{zQMMMM mgMMMMMTe+->(-`--_aMMMMMMMMMBfVWMMMQwZO[xz>-` ._gMMMMF@MMBMMMMBEM|(#MMMM MMMMMENg+->-----_##MMMBXM#MmW: .?MZ#QQZO[v>- a@MMMM#1?dMMMMBMBEMi(dXBMM MMMMBSZ!(>----JZXZOO0#WQQZ@+-..-cvXZXQZZOv>` .XAx9@9%(udMMMMMMMBM](dM#MM MMMMGZ%(>--.(XXZOvO[[[0OZXZZ4nZ{-(z4ZZZZOx>- .({xxQGQ#MMM#MMMMBMME>4M#MM MMMnZ%(:-`_Z#XZO[vzzvvvvvvvvvv=>>=zZOOZZZO{- ->zvvOZZZ#X#MMMMMBME>(dBMM MWuZ%:--_aM#QZZ[[xvz{>>((>>>(::>>>zOx44ZZO{- -((zzxOZZZXSMBBMBMMm=(dBMM W4X}--`_MBM#ZZZO[[vz>((((:(((:(((zvxxxZOZO[~ -((czzO4ZZZQMMBMBMME{(dMMB uQ%/--_MBB#XQZZZO[zxzc(((--((:(({zxxxx4wZO[: .(>{zz[OZZZdMMBMBMME{3zMMB XC-`_gMBMB#QQZZZxxxvzz{>:((((((>zzxxx[ZZZO[=- (czzx[[ZZQ#MMMMBMMB{(xdMB Y``_MMMEMB#XQZZZOO[vzzz={(>(>>>>zzOOOZZQZZO{- ({zzx[OZZdMMMBMMMMBk([dMB ~_(MMMMEMB##QZZZOOx[vvvzzzzc{>{zz[wQZOZZZZOo: .ozzzxZZdMMBMBMMMMBm([3MM >aMMMMME#B#XQZZZZOOx[xvzzzzzzzzv[zdXOxxx4ZZ[-- _[xx[OZQgMMBMBBBMMBm{=xdM gMMMMMME#B#XQQZZZOx[[[zzzvzzzzzzvvZQxdMWSQQQx--czxzxOZgMMMBBBMBMBMB[(OdM MBBMMMMEdM#SXZZZZOOxxxxz[vzzzzzzzvvOOZZOOUV=:-({zz[OZQMMMMBBB#BMMMMP(OdM MBMMMMMmd##XZZZZZZ[[xxxx[vzzzzzzzzzv[[v=~(>---(zx[[OgMMMMMBMEMBMMBMm{OdH
On Mon, 26 Mar 2001 22:12:32 +0200, Markus Gebhard <ukg...@rz.uni-karlsruhe.de> enlightened us with: > Heinz Flug wrote: > > > > // Very simple JPG to ASCII converter. > > // Written on a saturday night by Heinz Flug .. flu...@online.no > > // The code cries out for improvement.... > > Cool, but you should mention that your code needs Java2 and will not run > in Java 1.1. > > If your looking for improvement, I have an improved piece of Java work: > Jave. It has a much more complicated image2ascii algorithm included. I > have written and designed it from scratch and I think one should have > had a look at it: > http://www.jave.de > > regards, > Markus > Markus, I hope I'm not overstepping the line by saying you're plugging your program a bit too much here. Yes, it's a very good piece of software, but you seem to be responding to a lot of posts saying "yes, that's good, but use this - it's better". It is starting to get a bit repetative, to me at least What I would find more interesting as far as image > ascii goes is a "competition" where several people convert the same image(s) using their preffered converters, to give us a full comparison of the results. Anyone with web space willing to host something like that? -- o |\ _[] L_ === Stuart Moore []\, stm
In the last episode, stu...@bigfoot.com (Stuart Moore) wrote: >Markus, I hope I'm not overstepping the line by saying you're plugging your >program a bit too much here. Yes, it's a very good piece of software, but you >seem to be responding to a lot of posts saying "yes, that's good, but use this - >it's better". It is starting to get a bit repetative, to me at least Sounds fair to me ... although I wish I'd written it :) >What I would find more interesting as far as image > ascii goes is a >"competition" where several people convert the same image(s) using their >preffered converters, to give us a full comparison of the results. Anyone with >web space willing to host something like that? I think you are reaching here ... Lemming -- Curiosity *may* have killed Schrodinger's cat.
In alt.ascii-art, Markus Gebhard <ukg...@rz.uni-karlsruhe.de> wrote: > Heinz Flug wrote: > > // Very simple JPG to ASCII converter. > > // Written on a saturday night by Heinz Flug .. flu...@online.no > > // The code cries out for improvement.... > Cool, but you should mention that your code needs Java2 and will not run > in Java 1.1. > > If your looking for improvement, I have an improved piece of Java work: > Jave. It has a much more complicated image2ascii algorithm included. I ... Personally, I feel that if it needs a network connection (or browser) to run, it is going to be too slow. (But I do things like make ASCII art movies.) Here's a PGM to ASCII script I wrote last year, as an example of a different, simple conversion. It is designed to work from the command line. Like all good PBM/PGM/PPM tools, it can take the input from a file or from standard input. (PBM: portable bitmap (black and white); PGM: portable graymap (grayscale); PPM: portable pixmap (full color); PBM/PGM/PPM tools are an old Unix graphics suite, perfect for automated processing of images.) Typical usage of this would be something like: djpeg image.jpg | pnmscale -yscale 0.5 | pnmscale -xsize 64 | \ ppmtopgm | pgmnorm | pgmtoascii This gives much better results than the pbmtoascii that comes with the PBM/PGM/PPM tools. The first pnmscale adjusts for the non-square pixels of ascii art, the second resizes to a the number of columns wide the picture will be. The ppmtopgm converts a color image to grayscale, the pgmnorm "normalizes the contrast in a portable graymap". I assume white text on a black background. Throw in a pnminvert after the normalization to change that. Then use pbmtext if you want an image version of the text. By way of sample output here is Mr T, 40 chars wide: . ,. ;;. ,. .+, ,. ,++, .,++;;, ...,;;;;+++;++xxx+;. .. .,;+xzzzmmmmmzzzzzzz+ .mx,,;..,;xzmXXXYYYYXXmmmXXXX+ .,mmxmX+,;+zXXYUUUCCCCUYYUUUUCY. .;.,,+XUx,;+mYUUUUUCCCOCUUOWWWWU; ;x..,+xx;,;+mUUUUUUUCCCCUUWWWWUz+, ,+,,mCY,..,;zYUCOUUCCOCUUUOWWCzx+, ;m+XYUU+.,,+++zXYYYYYXmmzzXMWWmx; ,m+Om;;,;+mYX+;zYUYmzzx+zmYWWWYx. ++Um,;+zzmmz+,xYUYYYYYUUUUUWWY+ ;+UY;;+zzmmx;;zYUYUCCCCCUYCWCm; .;+Yz,,;+mmx;;+mUYXYUOOCUYYWWX+. ,+Xx,,;xzx;,,;mUYXYUUUUUYCWU+, .;mz,.,,,,..,+mzzzXYYUYYXUUz; ;++, .;xzzXXmx+;++xxxxxx, ;z+;.. .+xmmXYYYXz+,,,,;+xx. .;m+,;,. .,+xmYUYXm+,,,;;xYUX;. ..;;;z; ,;, .,,;+xx+,. ,;+zYCUCUz+;, .;,;,,. . .,;++;. ,+mUCUUCUYzmzx ,;;;,+. .,xYCUUYYUUUmzzz .++++m+,.. .;xXYYYYYmUUUXzzz ;;;;;,+mYXmx+;,.... .,;+zzXUYUUUXUUUmzzz ... .+mUYUYmXmzxxx;;zXXYYYUUUUUUCCUzzzz .... .;zUYUUmYXXmzm+;mYXXYYUUUYUUOOCmz A better tool would use edge detection to emphasize changes of "color" and some sort of de-speckle method to produce less "noisy" output. Elijah ------ #!/usr/bin/perl -w # Convert PGM to ASCII art. # Eli the Bearded 27 Dec 1999 use strict; use integer; use vars qw( $in $type $x $y $max $id %map $custommap $i $last ); $id = $0; $id =~ s:.*/::; $custommap = 0; %map = ( # The keys are the letter 'd' followed by a decimal number of a character. # Alternatively the raw character can be used, but the 'd' form will # override if both are defined. # Thirty-two 'color' scale derived from Scarecrow's ASCII Art FAQ. d000 => ' ', d016 => '.', d032 => ',', d048 => ';', d064 => '+', d080 => 'x', d096 => 'z', d112 => 'm', d128 => 'X', d144 => 'Y', d160 => 'U', d186 => 'C', d202 => 'O', d218 => 'M', d234 => 'W', d256 => '%', ); # Fill in holes. $last = ' '; for ($i = 0; $i < 256; $i++) { $i = sprintf("%03d", $i); if (defined($map{"d$i"})) { $last = $map{"d$i"}; } else { $map{"d$i"} = $last; } } while (defined($ARGV[0]) and $ARGV[0] =~ /^-(.*)/) { my $arg = $1; shift; if ($arg eq '-help' or $arg eq '-version' or $arg eq 'v') { &usage(0); } elsif ($arg eq 'm' or $arg eq '-map') { &readmap($ARGV[1]); } } # Add to map the character versions of the numerical mappings. my @map = keys %map; foreach (@map) { s/^d//; $map{chr($_)} = $map{"d$_"}; } if ($ARGV[0]) { open(STDIN,"< $ARGV[0]") or die "$id: Can't open '$ARGV[0]': $!\n"; } $in = '#'; while($in =~ /^#/) { $in = <STDIN> } if ($in =~ s/^P([25])\s*//) { $type = $1; } else { warn "$id: no portable graymap image file found\n"; exit(1); } read(STDIN,$in,1024,length($in)); # Eat comments, if the version allows comments if ($type < 4 and $in =~ tr:#:#:) { while ($in =~ s/(^|\cm|\cj)#[^\cj\cm]*([\cm\cj])/$1$2/g) { read(STDIN,$in,256,length($in)); } } if ($in =~ s/^\s*(\d+)\s+(\d+)\s+//) { $x = $1; $y = $2; } else { warn "$id: no dimensions found in image\n"; exit(1); } if ($in =~ s/^\s*(\d+)\s+//) { $max = $1; } else { warn "$id: no max value found in image\n"; exit(1); } if ($max != 255 and !$custommap) { warn "$id: Internal map is for 255 grays, this has $max grays\n"; } my $done = 0; my $col = 0; my $pixel = 0; while(!$done) { if (length($in) < 4) { if (!read(STDIN,$in,1024,length($in))) { $done = 1; } elsif ($type == 2) { # Nuke any leading whitespace if this is a text based PGM file. $in =~ s/^\s+//; } } my $chr; if ($type == 5) { $in =~ s/^(.)//s; $chr = $1; } else { if ($done) { ($chr) = $in =~ s/^(\d+)\s*//s; } else { ($chr) = $in =~ s/^(\d+)\s+//s; } if (!defined($chr)) { warn "$id: Missing gray value!\n"; next; } $chr = sprintf("d%03d", $chr); } if (!defined($map{$chr})) { my $pchar = $chr; my $new = ' '; if (!($pchar =~ /^d(\d+)/)) { $pchar = sprintf("%03d",$1); } if ($pchar > ($max /2)) { $new = 'M'; } warn "$id: Gray $pchar missing from map using <$new>\n"; $map{$chr} = $new; } print $map{$chr}; $pixel ++; $col++; if ($col == $x) { print "\n"; $col = 0; } if ($pixel > ($x * $y)) { die "Too many pixels\nin=$in\n" unless $done; } } print "\n"; exit(0); sub usage ($) { my $exit = shift; print "$id: usage\n", <<USAGEnotes; pgmtoascii [option] [file] Options: -h --help print this message -m --map MAPFILE use MAPFILE for gray to ascii map USAGEnotes exit($exit); } # end &usage # A really crude way to read in the graymapping file. sub readmap ($) { my $file = shift; do $file or die "$id: Can't read map: $!\n" } # end &readmap __END__
Stuart Moore wrote: > > Markus, I hope I'm not overstepping the line by saying you're plugging your > program a bit too much here. Ok, I guess you are right. I am sorry and I want to apologize for that. > ... "yes, that's good, but use this - it's better". ... Hm, I think I rather wanted to say: "try this, it's new, it is different and I would like to know what you think about it". You know, I have spent a lot of work on that tool and I wanted to make other people know that it is there and they can check it out. It is not a good feeling to develop a piece of software and being the only one who uses it... I think I got a bit too enthusiastic about it... :-( Again: I am sorry and I will stop that. Markus
About this thread.
These messages were posted publicly to the newsgroup
alt.ascii-art
in 2001 and are mirrored here unchanged as part of the Historic Archives – only email addresses are masked.
The artwork and text belong to their original authors: if you copy a piece, keep the artist's initials or signature intact and credit them where you can.
Are you one of the authors? Contact us to get your posts attributed, connected to your artist profile, or removed.