Key Ideas
[Part 9 of 11]


There are four key ideas in this part:

  1. The first is that in order to draw something reliably on the screen, you need to override the paint method of the object you are trying to draw on. This usually means extending the class (though see below for an example using an anonymous inner class). You call repaint to manually run this method, though the JVM will also call it when needed. In paint you can use a variety of drawing methods.

    import java.awt.*;

    public class PanelGUI extends Frame {

       public PanelGUI() {
          setSize(300,300);
          setVisible(true);
          repaint();
       }

       public void paint (Graphics g) {
          g.drawString("Hello World", 50, 50);
       }

       public static void main (String args[]) {
          new PanelGUI();
       }
    }

  2. The second is that images are stored in java.awt.Image class objects, and that in order to get data from an image, you need a PixelGrabber. These have a grabPixels method to grab the pixels as a 1D array of packed ints:

    int pixels[] = new int [width * height];
    PixelGrabber pg = new PixelGrabber(image,0,0,width,height,pixels,0,width);
    try {
       pg.grabPixels();
    } catch (InterruptedException ie) {
       ie.printStackTrace();
    }

  3. The third is that java.awt.Color class objects can be used to turn packed ints into unpacked ints, and back again:

    for (int i = 0; i < pixels.length; i++) {
       Color pixel = new Color(pixels[i]);
       int red = pixel.getRed();
       int green = pixel.getGreen();
       int blue = pixel.getBlue();
       pixel = new Color(red,green,blue);
       pixels[i] = pixel.getRGB();
    }

  4. Lastly, we can use a MemoryImageSource object to turn 1D packed int data into an image:

    MemoryImageSource memImage = new MemoryImageSource(width,height,pixels,0,width);
    Image newImage = createImage(memImage);


Here's some code which uses these ideas. Note that there's some new bits in here that you can follow up in the docs, in particular the use of the javax.imageio.ImageIO to read and write image files in standard formats. You can also use:

Image image = Toolkit.getDefaultToolkit().getImage(file.getPath());
MediaTracker mTracker = new MediaTracker(new Panel());
mTracker.addImage(image,1);
try {
   mTracker.waitForID(1);
} catch (InterruptedException ie) {
   ie.printStackTrace();
}

to do this, but ImageIO is much better set up for doing it easily.

Note also the use of an anonymous inner class to override the Canvas object's paint method, so we don't need another extended class to do this. For small bits of code (where our code won't get too confused) this is appropriate.

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.imageio.*;
import java.util.*;
import java.awt.image.*;

public class ImageProcessor extends Frame {

   private Canvas c = new Canvas();
   private Image image = null;

   public ImageProcessor(String args[]) {

      // Read an image file.

      File in = new File(args[0]);
      if ((args[0] == null) || (!in.exists())) {
         System.out.println("No input file");
         System.exit(0);
      }

      try {
         image = ImageIO.read(in);
      } catch (IOException io) {
         io.printStackTrace();
      }

      // Grab the pixels.

      int width = image.getWidth(null);
      int height = image.getHeight(null);

      setSize(width,height);

      int pixels[] = new int [width * height];
      PixelGrabber pg = new PixelGrabber(image,0,0,width,height,pixels,0,width);
      try {
         pg.grabPixels();
      } catch (InterruptedException ie) {
         ie.printStackTrace();
      }

      // Process the pixels.

      for (int i = 0; i < pixels.length; i++) {
         Color pixel = new Color(pixels[i]);
         int red = pixel.getRed();
         pixel = new Color(red,red,red);
         pixels[i] = pixel.getRGB();
      }

      // Recreate the image.

      MemoryImageSource memImage = new MemoryImageSource(width,height,pixels,0,width);
      image = createImage(memImage);

      // Write it out.

      File out = new File(args[1]);
      BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
      bufferedImage.getGraphics().drawImage(image, 0, 0 , null);

      if (args[1] != null) {
         String path = out.getPath();
         try {
            ImageIO.write(bufferedImage, path.substring(path.lastIndexOf(".") + 1), out);
         } catch (IOException e) {
            e.printStackTrace();
         }
      }

      // Display it.

      Canvas c = new Canvas () {
         public void paint(Graphics cg) {
            cg.drawImage(image, 0, 0, this);
         }
      };

      add(c);

      addWindowListener(new WindowAdapter(){
         public void windowClosing(WindowEvent e){
            System.exit(0);
         }
      });

      setVisible(true);
      repaint();

   }

   public static void main (String args[]) {
      new ImageProcessor(args);
   }
}