1 Replies - 5527 Views - Last Post: 29 March 2012 - 09:05 AM

#1 erik.price   User is offline

  • D.I.C Lover
  • member icon

Reputation: 486
  • View blog
  • Posts: 2,690
  • Joined: 18-December 08

Converting an Image to ASCII Art (with color!)

Posted 22 December 2009 - 04:26 PM

Description: I went a bit comment happy on this one, but there was a lot to explain, especially because of the HTML. Shoot me a PM if anything is unclear

Just remember, the smaller of a number you pass to the method, the larger the image will be! (I accidentally created a 2.1GB file. You have been warned)Creates either a greyscale plaintext ASCII image, or, for added awesomeness, creates a String containing HTML, which when written to a file and viewed in a browser, contains a full color ASCII'd copy of the original image!
import java.awt.image.BufferedImage;
import java.awt.Color;

public String toASCII(BufferedImage img, double shrinkFactor)  {
        BufferedImage image = img;

        char[] shades = new char[]{'H', '#', 'M', '8', '$', 'O', '=', '+',
            '*', '|', '-', '^', '~', ';', ',', ':', '.', ' '};
        //ASCII characters to use, ranging from darkest to lightest.
        //experiment with your own combinations!

        StringBuilder output = new StringBuilder();
        //using a StringBuilder so Java doesn't explode from creating thrirty million strings
        //(seriously). Running a profiler on the project, Java called the append method of
        //StringBuilder 10 million times. Granted it was a big picture - gabe's head blown
        //up 10 times.

        /*Take Note: The size of the StringBuilder will eventually exceed Java's
         *internal heap causing the program to burst into flames. If you are
         *with images that big, I would suggest to write it to a File directly
         *from within this method, instead of using a StringBuilder*/

        String red; //hex red value
        String green; //hex green value
        String blue;  //hex blue value
        Color col; //color to store RGB data in
        int avg = 0; //average of RGB

        //Uncomment below for HTML
        //output.append("<pre>");
        //for all you non HTML buffs out there (like me), the <pre> tag
        //means preformatted text. Because we don't want any webbrowser messing
        //with out spacing!


        //Why have the y loop go first? Due to the way BufferedImages are laid out
        //using for(int x //)
        //          for(int y//)
        //will create a sideways image

        for (double y = 0; y < image.getHeight(); y += shrinkFactor) {
            for (double x = 0; x < image.getWidth(); x += shrinkFactor) {

                //the reason for x and y being doubles is to allow for the method
                //to expand images as well as shrink them

                col = new Color(image.getRGB((int) x, (int) y));
                //truncate the values of x and y, meaning that it stays on the
                //same pixel for multiple iterations if the shrink factor
                //is less than 1

                avg = (col.getRed() + col.getGreen() + col.getBlue()) / 3;
                //find the average

                avg = avg / (256 / shades.length - 1);
                //makes the average usable to select an index in the char array

                while (avg > shades.length - 1) {
                    //make sure average will fit into the array
                    avg--;
                }

                red = Integer.toHexString(col.getRed()); //convert it to hex
                green = Integer.toHexString(col.getGreen());
                blue = Integer.toHexString(col.getBlue());
                
                
                //uncomment this next block for HTML
                
                /*
                red = (red.length() < 2) ? "0" + red.charAt(0) : red;
                green = (green.length() < 2) ? "0" + green.charAt(0) : green;
                blue = (blue.length() < 2) ? "0" + blue.charAt(0) : blue;
                */
                
                //what it does is prepend a 0 to the hex String if it is less
                //than 15 (F). Why you ask?
                //because HTML uses color codes like this: #RRGGBB, R being red
                //obviously, G green, and B blue. If we have an red value of 4,
                //the entire color gets messed up: #4GGBB, which reads the red 
                //value as 4G instead of just 4, and so on.
                //this method would provide this color code: #04GGBB. The day is saved!

                //undo the following block comments for HTML
                output.append(/*"<FONT COLOR="#"+(red+green+blue)+"">"+*/
                        shades[avg] + " " /*you can choose to remove the additional
                                           * space here if you'd like, I just find
                                           * that the images seem less squished 
                                           * with it*/
                        /*+"</FONT>"*/);

            }
            output.append("n");
        //comment out above line and use the below one instead for HTML
        //output.append("
"); //newline

        }

        //uncomment below for HTML
        //output.append(" </pre>");

        return output.toString();
    }

/*Example program usage*/

//inside main()
BufferedImage img = ImageIO.read(new File("src.gif"));
Writer output = new BufferedWriter(new FileWriter(new File("ascii.txt")));
output.append(toASCII(img, .1)); //10 times original size!
output.close();



Is This A Good Question/Topic? 0
  • +

Replies To: Converting an Image to ASCII Art (with color!)

#2 AlgodooJavaHead   User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 2
  • Joined: 20-March 12

Re: Converting an Image to ASCII Art (with color!)

Posted 29 March 2012 - 09:05 AM

I've just copied this directly from this page, and it's FULL of errors! It doesn't even have a main method!!!
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1