Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Sunday, August 28, 2011

Your own Images to ASCII arts application - Part IV (Implementation)

NEW!! Executable project is @ http://code.google.com/p/image-to-ascii/

Hi...!! In my previous post I discussed about opening an image using java. Now it is time to work with the image. Java 2D has two classes to represent images. java.awt.image and java.awt.image.BufferedImage. Buffered image is the most flexible one for some processing. Because it allow us to work on the image data.
Here what I'm going to do first is to open the image. Then I will convert the image in to a gray scale image with user defined dimensions. There we will have to do two things. 


1. How to change a color image to a gray scale image using java 2D?
2. How to change the dimensions of an image?


Both the questions will answered in the below line of codes. There first I will create a new gray scale Buffered image (answer to the question one) with custom dimensions (answer to the question two). After that I will draw the current image on the newly created image.

BufferedImage imgEdted = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
Graphics graphicEdted = imgEdted.getGraphics();
graphicEdted.drawImage(imgIn, 0, 0, width, height, 0, 0, w, h, null);
Here the image imgEdited is the new image and imgIn is the original image (The full source code is shown below). First we will get the graphic object of the newly created image (graphicEdted) and we will use it to draw the original image on the new image.  Here width and height are the custom widths and heights and w and h are the width and height of the original image. The "drawImage()" method do the trick here. It convert the color and also re scale the image. Here are some of the very important usages of this method.


http://download.oracle.com/javase/tutorial/2d/images/drawimage.html
http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Graphics.html

After the new gray-scale image is created we will use a multilevel threshold to create our ASCII image. For that purpose we have to go through each and every pixel of the image.  For the simplicity I will use read the color value of the pixel and determine it group. That is how we are going to do the multilevel threshold. For each group of color value I will assign a letter (an ASCII) that will eventually produce a ASCII image. The quality of the output image will depend on two facts. The first one is the number of groups and the other is the letter we assign for a color group.
Because I need to create an ASCII image I will collect the ASCII letter for each pixel to a string buffer. After a row of pixel in the image I will append a line break to the string buffer. 


Below code is showing the complete source code for the section I above discussed. It shows a method which take a image (buffered image) and a user defined width and height to create an ASCII image of user defined size. 

package img2ascii.core;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

public class AsciiCreator {
  public static StringBuffer getASCII(BufferedImage imgIn, int width,int height){
    //change the color mode - and reset the size as we need
    int w = imgIn.getWidth(null);
     int h = imgIn.getHeight(null);
 BufferedImage imgEdted = new BufferedImage(width,height,BufferedImage.TYPE_BYTE_GRAY);
 Graphics graphicEdted = imgEdted.getGraphics();
 graphicEdted.drawImage(imgIn, 0, 0, width, height, 0, 0, w, h, null); 
 //create ASCII image by multilevel threshloding and save the result to a String buffer
 StringBuffer asciiBuffer = new StringBuffer();
 
 for(int i=0;i 230){
     System.out.print("`");
     asciiBuffer.append("`");
   }else{
      if(color>200){
      System.out.print("'");
      asciiBuffer.append("'");
   }else{
      if(color>160){
         System.out.print(";");
         asciiBuffer.append(";");
      }else{
         if(color>120){
            System.out.print("O");
     asciiBuffer.append("O");
  }else{
      if(color>80){
     System.out.print("8");
     asciiBuffer.append("8");
      }else{
   if(color>40){
      System.out.print("N");
      asciiBuffer.append("N");
   }else{
      System.out.print("M");
      asciiBuffer.append("M");
    }
      }
   }
        }
      }
     }
   }
  System.out.println("");
  asciiBuffer.append(System.getProperty("line.separator"));
  }
  return asciiBuffer;
 }
}

Saturday, August 20, 2011

Your own Images to ASCII arts application - Part III (Implementation)

NEW!! Executable project is @ http://code.google.com/p/image-to-ascii/


Image to ASCII art application was not that much hard to implement. Now we will talk about the implementation. Since I'm going to cover the basics, here I will describe even the very basic things. In a nutshell, the application will open an image file and do some processing and then that text file will be saved to somewhere. If the user needs to preview it before saving the text file, he/she can also do it. Here I will describe the application functionality as questions (in a new way ;)) )


1.  How to open an Image in java?
"javax.ImageIO" class provides all the facilities to read an image to an application. We can use it to read an image as a BufferedImage to our application. In java2D API images are mainly represented in two ways. Either as an Image ("java.awt.Image") or as an Buffered Image (java.awt.image.BufferedImage"), which is a descended class of image and which provides more options for image manipulations. 
BufferedImage img = ImageIO.read(new File(fileChooser.getSelectedFile().getAbsolutePath()));     
Here the purpose of "new File(fileChooser.getSelectedFile().getAbsolutePath())" is to create a new File (java.io.File) which is pointing to image that we want to open. Here I also have used a File Cooser to browse for files. I will explain how to use a JFileCooser now.  


2. How to use a JFileCooser?
"javax.swing.JFileChooser is ideal for opening and saving files. The most important point here we have to understand is "JFileChooser cannot open or save a files" :)) . It can only point a file. The saving or opening part is up to us to handle. When a JFileCooser (either to open  a file or to save a one)  is shown a user can either select a file or press cancel. If user doesn't cancel we have to handle that situation. We can identify that by a return value after calling the JFileChooser.showOpenDialog() method or JFileChooser.showSaveDialog(). That is shown in the code below. 
int userChoice = fileChooser.showOpenDialog(FileChooserDemo.this);
    if (userChoice == JFileChooser.APPROVE_OPTION) {
        File file = fileChooser.getSelectedFile();
        //Open the file code goes here
    } else {
        //Do nothing user has press cancel
    }


Here is the code I'm using in my application to open and show a image. Note that some error handling are also included. Here I'm also using a file filter with the file chooser which I'm going to explain next.
//open the file choose and show the selected file
fileChooser = new JFileChooser();
//add filters to the file chooser - to only show the image files
fileChooser.addChoosableFileFilter(new ImageFilter());
fileChooser.setAcceptAllFileFilterUsed(false);
int userChoice = fileChooser.showOpenDialog(ImageLoader.this);
if( userChoice == JFileChooser.APPROVE_OPTION ){
  try{						          txtImagePath.setText(fileChooser.getSelectedFile().getAbsolutePath());
						BufferedImage img = ImageIO.read(new File(fileChooser.getSelectedFile().getAbsolutePath()));
						currentImg = img;
						//display the image using an image icon
						ImageIcon icon = new ImageIcon(img);
						lblImage.setIcon(icon);
						
  }catch(Exception e){ 							JOptionPane.showMessageDialog(ImageLoader.this, "Invalid file!");
 }
}else{
  JOptionPane.showMessageDialog(ImageLoader.this, "Please select a file!");
}


3. Howto use filters with a JFileChooser? 
 Did you notice the below code lines in the above code? Those are for some filtering mechanism. 
fileChooser.addChoosableFileFilter(new ImageFilter());
fileChooser.setAcceptAllFileFilterUsed(false);
The purpose of filtering is to filter out some of file extensions and show what we are interested, as it name implies "Filters" ;). Here I'm only going to show image files and folders. Using a filter is not a must. But it is a good practice to do so. Above first line initiate the filter and the second line disable the default settings of the JFileChooser. (note - I will host the the complete project  in Google code and provide the link to you later in a upcoming post). Please read the up to now section to get an overall idea what we had done up to now.

import java.io.File;
import javax.swing.filechooser.FileFilter;

public class ImageFilter extends FileFilter {

    //Accept all directories and all gif, jpg, or png files.
    public boolean accept(File f) {
        if (f.isDirectory()) {
            return true;
        }

        String extension = getExtension(f);
        if (extension != null) {
            if (extension.equals("gif") ||
                extension.equals("jpg") ||
                extension.equals("png")) {
                    return true;
            } else {
                return false;
            }
        }

        return false;
    }

    //The description of this filter
    public String getDescription() {
        return "Images";
    }
    
    //find the extension of the file name
    public String getExtension(File f) {
        String ext = null;
        String s = f.getName();
        int i = s.lastIndexOf('.');

        if (i > 0 &&  i < s.length() - 1) {
            ext = s.substring(i+1).toLowerCase();
        }
        return ext;
    }
}
Up to Now!
Up to now we talk about the things we need to open a image file into our application. How to read the file and how to browse for it etc. In my next post I will explain you how to manipulate the image we opened and etc. Before that I will Host the complete source code, then it will be very easy for you... Bye..!! :)) 

Tuesday, August 16, 2011

Your own Images to ASCII arts application - Part II (Design)

NEW!! Executable project is @ http://code.google.com/p/image-to-ascii/


OK!!! let's look at the design of our application, Image to ASCII converter. First I have to tell you that the application is very simple. Even I also thought it will be very difficult to implement such an application. I don't know how other people out there implemented this but when I think  I came up with a very simple solution. In a pictorial view my solution is like this.


How to convert raster to a ASCII art


The above image show how I plan the thing. First the user will have to point out the image. Then the image will get converted to a gray scale image. Then the second step is to do a multi level threshhold to the image.
In a multi level threshold we simply make set of color groups. As an example pixels which are having color value 200 to 255 will put in to a one group while color value 150 to 199 put in to another group. The multi level thresholding will be obvious when you look at the below image.


Multi level thresholding
After the multi level thresholding what I'm doing is assigning relevant ASCII character to each level as shown in the below figure. Selecting the correct ASCII character for a value is bit tricky. Therefore we have to put some character for a level and check weather it is relevant. As an example get the letter "M" when a set of Ms are together they represent back color.
Map ASCII characters to color levels


Now we talked about the algorithm for creating an ASCII image form a Raster image. Now it is a matter of implementing this algorithm using some language, which we are going to talk in my next post.. bye!  

Sunday, August 14, 2011

Your own Images to ASCII arts application - Part I (Introduction)

NEW!! Executable project is @ http://code.google.com/p/image-to-ascii/


Hi.. :) I talked a bit about ASCII arts from my previous posts. I also presented some amazing online applications which let us convert our images to ASCII arts. I thought of implementing my own application of that kind. Not for any special thing but for my interest and to share knowledge. I'm planing to build the application as a fully open source one and I will implement using java. Once the application development is done I  will host it somewhere for the use of every one.  


In a nut shell what I'm going to do is as follows. Turn Mona Lisa in to a writable format  ;)) .




























Here we will cover some of the fundamentals of Image processing and java programming.  Since I'm not using any special libraries it will be easy for you all. As my previous experiences I know configuring things is not happy at all. That is a one reason for not using any third party library. The other one is since this is an application where it covers the basics it is good to work in a lower level. Be with me. We are going to change the history of ASCII arts :D :D :D....