Thursday, 14 May 2015

Converting Images to Arrays (PixelGrabber) in Java

  If you're going to process images, you often want to work with the pixel data as an array. The AWT provides a class, java.awt.image.PixelGrabber, to do just that. This class has two creator methods, plus some other useful methods.
new PixelGrabber(Image img, int x, int y, int width, int height, int[] pixels, int offset, int linewidth)
Takes the region of the image defined by x, y, height, and width and puts it into the pixel's array with the specified offset and line width.
new PixelGrabber(ImageProducer img, int x, int y, int width, int height, int[] pixels, int offset, int linewidth)
Takes the region of the image produced by the image producer defined by x, y, height, and width and puts it into the pixel's array with the specified offset and line width.
boolean, grabPixels()
Throws InterruptedException if it's interrupted. It takes the image data and puts it into the pixel array. This is a synchronized method.
int, status()
Returns the status of getting the pixels from an image. The return value uses the same flag constants as the ImageObserver class. This is a synchronized method.

The applet in Listing 17.36 reads in a GIF file, fills in an array with the pixel values, applies an averaging filter to the data (which uses information about each pixel's neighbors), and then converts the pixel array back to an image.

Listing 17.36. A filter that uses data from a pixel's local area.
import java.awt.image.*;
import java.awt.*;
import java.applet.Applet;


public class pixel_grabber extends Applet implements Runnable 
{
    Image working;
    Thread the_thread;
    MediaTracker the_tracker;
    int pixels[];
    int max_x, max_y;
    Image the_picture;
    Image the_modified_picture;
    boolean done_flag;

    public void start() {
        if (the_thread == null) {
            the_thread = new Thread(this);
            the_thread.start(); 
        }
    }
    public void stop() {
        the_thread.stop(); 
    }

    public void run() {
        while (true) { 
            repaint(); 
            try {
                the_thread.sleep(3000); 
            } catch(InterruptedException e) {};
            //when the original image is loaded transform it. 
            //The use of the flag
            //makes sure you only transform the image once
            if(the_tracker.checkID(0,true) & !(done_flag)) {
                transform_image(); 
                done_flag = true;
            } 
        }
    }

    public void init()
    {
        done_flag = false; 
        max_x = 64;
        max_y = 64;
        the_tracker = new MediaTracker(this);
        //set up the pixel array that we're going to 
        //fill with data from the image
        pixels = new int[max_x * max_y];
        the_picture = getImage(getDocumentBase(),"test.gif");
        the_tracker.addImage(the_picture,0); 

    }
    public void transform_image() {
        PixelGrabber pg; 
        int x,y;
        double sum, temp; 
        //set up the PixelGrabber to capture the full image, unscaled
        pg = new PixelGrabber(the_picture, 0,0,max_x,max_y,pixels,0,max_y);
        //fill the pixel's array with the image data
        try {
            pg.grabPixels(); 
        } catch(InterruptedException e) {};
        //just to show something happened apply an averaging filter. 
        //This is designed to
        //work with grayscale images because it assumes all of the 
        //color components are
        //equal. It takes the Blue component of a pixel and its 
        //four neighbors, averages them,
        //and then sets the pixel color to that average
        for (x=3;x<(max_x - 3);x++) {
            for (y=3;y<(max_y - 3);y++) {
                temp = pixels[x + y * max_y] & 0x000000FF;
                sum = 0.2 * temp;
                temp = pixels[(x - 1) + y * max_y] & 0x000000FF;
                sum = sum + 0.2 * temp;
                temp = pixels[(x+1) + y * max_y] & 0x000000FF;
                sum = sum + 0.2 * temp;
                temp = pixels[x + (y - 1) * max_y] & 0x000000FF;
                sum = sum + 0.2 * temp;
                temp = pixels[x + (y + 1) * max_y] & 0x000000FF;
                sum = sum + 0.2 * temp;
                int gray = (int)Math.round(sum);
                Color c = new Color(gray,gray,gray);
                pixels[x + y * max_y] = c.getRGB() ;
            } 
        }
        //here we use MemoryImageSource to convert the pixel array into an Image
        the_modified_picture = createImage(new
                              MemoryImageSource(max_x,max_y,pixels,0,max_y));
        the_tracker.addImage(the_modified_picture,1); 
    }
    public void paint(Graphics g)
    {
        //if the image is done display it, otherwise let 
        //the user know what's going on
        if(the_tracker.checkID(0,true) ) {
            g.drawImage(the_picture,0,0,this); 
            if( the_tracker.checkID(1,true)) {
                g.drawImage(the_modified_picture, 64,64,this);
            } 
        } else {
            g.drawString("please wait",50,50);
        }
    }
}

No comments:

Post a Comment