import java.awt.image.*;

import java.awt.*;

import java.applet.*;

import java.awt.event.*; 





final class MyGifPixelGrabber implements ImageObserver

{

  private Image m_image=null;   // pointer to original image

  private Object m_pixels=null; // either array of ints or bytes

  private int m_iNumOfColors=0;  

  private int m_iWidth, m_iHeight;

  private ColorModel m_colorModel=null;



  public boolean isIndexed()

  {

	if (m_colorModel==null)

	  return false;

    return ((m_colorModel instanceof IndexColorModel));

  }

  

  MyGifPixelGrabber(Image img)

  {

    m_image=img;

  }



  public int getNumOfColors()

  {

    return m_iNumOfColors;

  }



  public void destroy()

  {

    m_image=null;

    m_pixels=null;

  }



  public void grabPixels()

  {

    m_iWidth=m_image.getWidth(this);

    m_iHeight=m_image.getHeight(this); 

    PixelGrabber pixelGrabber=new PixelGrabber(m_image, 0,0, 

      m_iWidth, m_iHeight, false);  



    try

    {

      pixelGrabber.grabPixels();

    }

    catch (Exception e)

    {

      System.out.println("PixelGrabber exception"); 

    }

    m_pixels=(Object)pixelGrabber.getPixels();

    // get the palette of the image

    m_colorModel=pixelGrabber.getColorModel();

    if (!(m_colorModel instanceof IndexColorModel))

    {

      // not an indexed file (ie: not a gif file)

    }

    else
    {

      m_iNumOfColors=((IndexColorModel)m_colorModel).getMapSize();

    }

  }



  // you'd need to cast the return values, which will be an array of bytes

  // or an array of ints.  if the file is a gif file, it will return an 

  // array of bytes, if jpg, you will get an array of ints

  public Object getPixels()

  {

    return m_pixels; 

  }



  public int getWidth()

  {

    return m_iWidth;

  }



  public int getHeight()

  {

    return m_iHeight;

  }

  

  public ColorModel getColorModel()

  {

	  return m_colorModel;

  }

  

  public int getRed(int pixel)

  {

    if ((m_colorModel instanceof IndexColorModel))	  

		return ((IndexColorModel)m_colorModel).getRed(pixel);

	else

		return ((DirectColorModel)m_colorModel).getRed(pixel);

  }



  public int getGreen(int pixel)

  {

    if ((m_colorModel instanceof IndexColorModel))	  

		return ((IndexColorModel)m_colorModel).getGreen(pixel);

	else

		return ((DirectColorModel)m_colorModel).getGreen(pixel);

  }

  

  public int getBlue(int pixel)

  {

    if ((m_colorModel instanceof IndexColorModel))	  

		return ((IndexColorModel)m_colorModel).getBlue(pixel);

	else

		return ((DirectColorModel)m_colorModel).getBlue(pixel);

  }

  

  public int getRGB(int pixel)

  {

    if ((m_colorModel instanceof IndexColorModel))	  

		return ((IndexColorModel)m_colorModel).getRGB(pixel);

	else

		return pixel;

  }

  

  // we need this method just because we're extending ImageObserver.

  public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height) 

  {

    return true;	  

  }  

}





class MyFrame extends Frame

{

  MyFrame()

  {

    super("PixelData");

  }



  public boolean handleEvent(Event e)

  {

    if (e.id==Event.WINDOW_DESTROY)

    {

      dispose();

      return false;

    }

    return super.handleEvent(e);

  }

}



public class TestImagePixels extends Applet implements Runnable, MouseListener

{

  Image m_image=null;

  Object m_pixelData=null;

  private String m_imageFilename;

  private Thread m_thread=null;

  private String m_message=null;

  private MyGifPixelGrabber m_gifPixelGrabber=null;

  

  public void start()

  {

	  m_thread=new Thread(this);

	  m_thread.start();

  }

  

  public void stop()

  {

  }



  public void init()

  {

	m_imageFilename=getParameter("img");

    // load image and make sure it's loaded before continuing.

    // (this is not a good way to do image loading, it's just for

    // illustration purpose.  on a real application, you might 

    // create a separate thread to load the image so that it won't

    // tie up the applet)

    m_image=getImage(getCodeBase(), m_imageFilename);

    MediaTracker mediaTracker=new MediaTracker(this);

    mediaTracker.addImage(m_image, 0);

    try

    {

      mediaTracker.waitForID(0);	

    }

    catch (InterruptedException e)

    {

    }

    mediaTracker.removeImage(m_image);

    m_gifPixelGrabber=new MyGifPixelGrabber (m_image);

    m_gifPixelGrabber.grabPixels();

	m_pixelData=m_gifPixelGrabber.getPixels();

	MyFrame f=new MyFrame();

	f.resize(200,300);

	TextArea textArea=new TextArea();

	textArea.setFont(new Font("Courier", 12,12));

    textArea.append(m_imageFilename+"\n");

	textArea.append("Width="+m_gifPixelGrabber.getWidth()+"\n");

	textArea.append("Height="+m_gifPixelGrabber.getHeight()+"\n");	

	if (m_gifPixelGrabber.isIndexed())	

		textArea.append("NumOfColors="+m_gifPixelGrabber.getNumOfColors()+"\n");		

	f.add("Center", textArea);

	f.show();

	if (m_gifPixelGrabber.isIndexed())	

	{

		byte[] pixelData=(byte[])m_pixelData;

		for (int i=0; m_gifPixelGrabber.isIndexed() && i<m_gifPixelGrabber.getHeight(); i++)

		{

			String s="";

			for (int j=0; j<m_gifPixelGrabber.getWidth(); j++)

		    {

				if ((int)pixelData[i*m_gifPixelGrabber.getWidth()+j]!=0)

				  s+=(int)pixelData[i*m_gifPixelGrabber.getWidth()+j];

				else

				  s+=" ";

			}

			textArea.appendText(s+"\n");

		}

	}

  }



  public void run()

  {

	addMouseListener(this);

	while (true)

	{

		try

		{

		  repaint();

		  Thread.sleep(100);

		}

		catch (InterruptedException e)

		{

		}		

	}

  }

  

  public void update(Graphics g)

  {

	g.setColor(Color.gray);

	g.fillRect(0,0, size().width, size().height);

    if (m_image!=null)

      g.drawImage(m_image,0,0, this);

	g.setColor(Color.black);

	g.drawString(m_message, 10,120);

	

  }

  

  public void mouseClicked(MouseEvent evt)

  {

	if (evt.getX()< m_image.getWidth(this) && evt.getY()<m_image.getHeight(this) )

	{

		if (m_gifPixelGrabber.isIndexed())

		{

			byte[] pixelData=(byte[])m_pixelData;			

			int pixel=(int)pixelData[evt.getY()*m_image.getWidth(this)+evt.getX()];

			m_message="idx="+pixel+" R="+m_gifPixelGrabber.getRed(pixel)+" G="+m_gifPixelGrabber.getGreen(pixel)+" B="+m_gifPixelGrabber.getBlue(pixel);

			

		}

		else

		{

			DirectColorModel dcm=(DirectColorModel)m_gifPixelGrabber.getColorModel();

			int[] pixelData=(int[])m_pixelData;						

			int pixel=(int)pixelData[evt.getY()*m_image.getWidth(this)+evt.getX()];

			m_message="pixel R="+dcm.getRed(pixel)+" G="+dcm.getGreen(pixel)+" B="+dcm.getBlue(pixel);

		}

	}

	update(getGraphics());

  }

  

  public void mouseEntered(MouseEvent evt){};

  public void mouseExited(MouseEvent evt){};

  public void mousePressed(MouseEvent evt){};  

  public void mouseReleased(MouseEvent evt){};

}
