/* Program simpleImage.java

 * This draws a bitmap with a square that has a cyan region at the top, 
 * magenta, bule and red regions in the middle, and a green region at the bottom.
 */
 
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.media.opengl.*;
import javax.media.opengl.glu.*;
import javax.media.opengl.awt.GLCanvas;
import com.jogamp.opengl.util.*;
import java.awt.*;
import javax.swing.*;
import java.awt.event.*;
import java.nio.ByteBuffer;

import javax.swing.event.*;



public class SimpleImage implements GLEventListener, ActionListener, ChangeListener {
	
	public static void main(String[] args) {
		new SimpleImage();
	}
	
	private int INITIAL_WIDTH=800;
	private int INITIAL_HEIGHT=800;
	private float XSCALE=10f;
	private float YSCALE=10f;
	private JButton quitButton;
	private GLCanvas canvas;
	private GL2 gl;
	private GLU glu;
	private int N = 600; // size of bitmap
	private int M = 600; // size of bitmap
	private byte RED[] = {127, 0, 0};
	private byte BLUE[] = {0, 0, 127};
	private byte GREEN[] = {0, 127, 0};
	private byte CYAN[] = {0, 127, 127};
	private byte MAGENTA[] = {127, 0, 127};
	private byte buffer[];
	
	public  SimpleImage() {
			GLProfile glp=GLProfile.getDefault();
			GLCapabilities caps = new GLCapabilities(glp);
			canvas = new GLCanvas(caps);
			canvas.addGLEventListener(this);

			JFrame frame = new JFrame("SIMPLE IMAGE");
			frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE );
			frame.setSize(INITIAL_WIDTH, INITIAL_HEIGHT);
			frame.setLayout(new BorderLayout());
			frame.setVisible(true);
			
			JPanel north = new JPanel( new FlowLayout());
			
			quitButton = new JButton( "Quit");
			quitButton.addActionListener(this);
			north.add(quitButton);

			JPanel center = new JPanel(new GridLayout(1,1));
			center.add(canvas);
		
			frame.add(north,  BorderLayout.NORTH);
			frame.add(center, BorderLayout.CENTER);

			FPSAnimator animator = new FPSAnimator(canvas, 60);
			animator.start(); 	
	}
	
	public void actionPerformed(ActionEvent event) {
			if (event.getSource() == quitButton)
				System.exit(0);
	}
	
	public void stateChanged(ChangeEvent e) {
	}


	public void display(GLAutoDrawable drawable) {
		update();
		render();
	}

	private void update() {
	}
	
	private void render() {
		gl.glClear(GL2.GL_COLOR_BUFFER_BIT);
		gl.glRasterPos2i((INITIAL_WIDTH-M)/2, (INITIAL_HEIGHT-N)/2);
		gl.glDrawPixels(M,  N,  GL2.GL_RGB, GL2.GL_BYTE, ByteBuffer.wrap(buffer));
	}
	
	void copy3( byte dest[], int row, int col, byte source[]) {
			int index = row*M*3+col*3;
			dest[index]=source[0];
			dest[index+1]=source[1];
			dest[index+2]=source[2];
	}
	
	public void dispose(GLAutoDrawable drawable) {
		// put the cleanup code here
		
	}

	public void init(GLAutoDrawable drawable) {
		gl = drawable.getGL().getGL2();
		glu = new GLU();
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluOrtho2D(0f, INITIAL_WIDTH, 0f, INITIAL_HEIGHT);
		gl.glClearColor(1,  1, 0, 1);
		gl.glPixelStorei(GL2.GL_PACK_ALIGNMENT, 1);
		gl.glPixelStorei(GL2.GL_UNPACK_ALIGNMENT, 1);
		gl.glPixelStorei(GL2.GL_UNPACK_SKIP_PIXELS, 0);
		gl.glPixelStorei(GL2.GL_UNPACK_SKIP_ROWS, 0);

		buffer = new byte[N*M*3];
		// The buffer has N rows and M columns
		// Note that the buffer is installed upside down;
		// this is why we copy pixels from row i in the image to
		// row N-i-1 of the buffer.
		for (int row = 0; row < N/3; row++)
				for (int col = 0; col < M; col++) {
					copy3(buffer, N-row-1, col, CYAN);  // To draw the buffer from the top down, put pixel (i, j) at row N-i-1 of the 
				}
		for (int row = N/3; row < 2*N/3; row++) {
			for (int col = 0; col < M/3; col++) {
				copy3(buffer, N-row-1, col, MAGENTA);
			}
			for (int col = M/3; col < 2*M/3; col++) {
				copy3(buffer, N-row-1, col, BLUE);
			}
			for (int col = 2*M/3; col < M; col++)
				copy3(buffer, N-row-1, col, RED);
		}
		for (int row = 2*N/3; row < N; row++)
			for (int col = 0; col < M; col++)
				copy3(buffer, N-row-1, col, GREEN);
	}

	public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
		// this is called when the window is resized
		gl.glMatrixMode(GL2.GL_PROJECTION);
		gl.glLoadIdentity();
		glu.gluOrtho2D(0f, width, 0f, height);

	}
	
}
