import java.awt.*;
import java.awt.image.*;

class Raster implements ImageObserver {
    protected int width, height;
    protected int pixel[];

    ///////////////////////// Constructors //////////////////////

    /**
     *  This constructor which takes no arguments
     *  allows for future extension.
     */
    public Raster() {
    }

    /**
     *  This constructor creates an uninitialized
     *  Raster Object of a given size (w x h).
     */
    public Raster(int w, int h) {
      width = w;
      height = h;
      pixel = new int[w*h];
    }

    /**
     *  This constructor creates an Raster initialized
     *  with the contents of an image.
     */
    public Raster(Image img)
    {
        try {
	  while (img.getWidth(this) < 0 || img.getHeight(this) < 0) {
              Thread.sleep((long) 100);
	  }
	  width = img.getWidth(this);
	  height = img.getHeight(this);
          pixel = new int[width*height];
          PixelGrabber  grabber = new PixelGrabber(img,0,0,width,height,pixel,0,width);
          grabber.grabPixels();
        } catch (InterruptedException e) {
          width = 0;
          height = 0;
          pixel = null;
          return;
        }
    }

    public boolean imageUpdate(Image img, int flags, int x, int y, int w, int h)
    {
        if ((flags & WIDTH) != 0) width = w;
        if ((flags & HEIGHT) != 0) height = h;
        return ((width >= 0) && (height >= 0));
    }


    ////////////////////////// Methods //////////////////////////

    /**
     *  Returns the number of pixels in the Raster
     */
    public int getSize( ) {
      return pixel.length;
    }

    /**
     *  Returns the number of pixels in the Raster
     */
    public int getWidth( ) {
      return width;
    }

    /**
     *  Returns the number of pixels in the Raster
     */
    public int getHeight( ) {
      return height;
    }

    public int[] getPixelBuffer( ) {
      return pixel;
    }

    /**
     * The following helper routine
     * test that x and y are valid
     */
    private final boolean invalid(int x, int y) {
      return ((x < 0) || (x >= width) || (y < 0) || (y >= height));
    }

    /**
     *  Fills a Raster with a solid color
     */
    public void fill(int argb) {
      int s = pixel.length;
      for (int i = 0; i < s; i++)
        pixel[i] = argb;
    }

    public void fill(Color c) {
      fill(c.getRGB());
    }

    /**
     *  Converts Rasters to Images
     */
    public Image toImage(Component root) {
      return root.createImage(new MemoryImageSource(width, height, pixel, 0, width));
    }

    /**
     *  Gets a pixel from a Raster
     */
    public int getPixel(int x, int y) {
      if (invalid(x, y))
        return 0;
      else
        return pixel[y*width+x];
    }

    /**
     *  Gets a color from a Raster
     */
    public Color getColor(int x, int y) {
      return new Color(getPixel(x,y));
    }

    /**
     *  Sets a pixel to a given value
     */
    public boolean setPixel(int pix, int x, int y) {
      if (invalid(x, y)) {
        return false;
      } else {
        pixel[y*width+x] = pix;
        return true;
      }
    }

    /**
     *  Sets a pixel to a given color
     */
    public boolean setColor(Color c, int x, int y) {
      return setPixel(c.getRGB(), x, y);
    }
}
