/*
 * Test program for glpng
 * by Ben Wyatt ben@wyatt100.freeserve.co.uk
 * Featuring a shameless plug for my stunt course program
 * Available from the same site as glpng
 * http://www.wyatt100.freeserve.co.uk/download.htm
 *
 * Modified by slr 10/11/2005
 *		to use orthographic window
 *		to remove idle callback
 *		to remove double buffering
 *		added logic for displaying the image (i or I) or the histogram (h or H)
 *			but not the processing for the histogram - that's your job
 *		kludge: added routine for fixing display of image from texture
 *		added logic to draw one line in displayHisto so you could see how to draw a line.
 * Modified by slr 10/18/2005
 *		to brighten grayscale image
 *		to eliminate hard coded size values in draw pixels call (thanks m.erb)
 */

#include <gl/glpng.h>
#include <gl/glut.h>
#include <stdlib.h>

/*************************************************
  Change the following to reflect your png image.
  ***********************************************/
#define IMG_WIDTH 256	// image width
#define IMG_HEIGHT 256	// image height
#define MARGIN 50  /* black border size around image */
#define FILENAME "Stunt.png"


#define drawOneLine(x1,y1,x2,y2)  glBegin(GL_LINES);  \
   glVertex2f ((x1),(y1)); glVertex2f ((x2),(y2)); glEnd();

int angle = 0;
int action = 0; /* 0 for initial value, 1 for display image, and 2 for display histogram */
GLubyte *image;

void reversePixels(void) {
	GLubyte *holdImage, *saveHoldImage, *pixelPtr;
	int i, j;
	
	holdImage = (GLubyte *) (malloc (IMG_WIDTH * IMG_HEIGHT * 3 * sizeof(GLubyte)));
	if (holdImage == NULL) {
		puts("no holdImage allocated: program ending");
		exit(0);
	}
	else
		puts("holdImage allocated");
	saveHoldImage = holdImage;
	pixelPtr = image+(IMG_WIDTH*(IMG_HEIGHT-1)*3*sizeof(GLubyte));
	for (j=0; j<IMG_HEIGHT; j++){
		for (i=0; i<IMG_WIDTH; i++){
		*holdImage++ = *pixelPtr++; 
		*holdImage++ = *pixelPtr++; 
		*holdImage++ = *pixelPtr++; 
		}
		pixelPtr-=((IMG_WIDTH*2)*(3*sizeof(GLubyte))); //up two rows
	}
	free(image);
	image = saveHoldImage;
}
/***** GLUT callback functions *****/



void KeyPress(unsigned char key, int x, int y) {
	switch (key) {
		case 27: /*ESC*/ glutDestroyWindow(glutGetWindow()); exit(0); break;
		case 'i': /*i*/
		case 'I': /*I*/
			puts("display image\n"); 
			action = 0;
			glutPostRedisplay();
			break;
		
		case 'h': /*h*/
		case 'H': /*H*/ 
			puts("display histogram\n"); 
			action = 1;
			glutPostRedisplay();
			break;
	}
}

void displayHistogram(void) {
/***************************************
Put your code here to display the histogram.  The image is in the variable image.  I
 ***************************************/
	glColor3f (1.0, 1.0, 1.0);		//line color
	glLineWidth (2.0);				//line thickness in pixels
	drawOneLine (0, 200, 300, 300);	//draws a line from (x1,y1)=(0,200) to (x2,y2)=(300,300)
}

void displayImage(void) {
	glRasterPos2i(MARGIN, MARGIN);
	glDrawPixels(IMG_WIDTH, IMG_HEIGHT, GL_RGB, GL_UNSIGNED_BYTE, image);

}

void display(void) {
	glClearColor(0.0, 0.0, 0.0, 1.0);
    glClear(GL_COLOR_BUFFER_BIT);
	if (action == 0)
		displayImage();
	else if (action == 1)
		displayHistogram();
	glFlush();
}

void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei)w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluOrtho2D(0.0,(GLdouble) w, 0.0, (GLdouble) h);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   glutPostRedisplay();
}

/***** Main function *****/



void main() {
	pngInfo info;
	GLuint  texture;

	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize(IMG_WIDTH+2*MARGIN, IMG_HEIGHT+2*MARGIN);
	glutCreateWindow("starting point");

	#if 0 // Using pngLoad and setting texture parameters manually.
		glGenTextures(1, &texture);
		glBindTexture(GL_TEXTURE_2D, texture);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

		if (!pngLoad(FILENAME, PNG_NOMIPMAP, PNG_SOLID, &info)) {
			puts("Can't load file");
			exit(1);
		}
	#else // Using pngLoadAndBind to set texture parameters automatically.
		texture = pngBind(FILENAME, PNG_NOMIPMAP, PNG_ALPHA, &info, GL_CLAMP, GL_NEAREST, GL_NEAREST);

		if (texture == 0) {
			puts("Can't load file");
			exit(1);
		}
	#endif

	printf("Size=%i,%i Depth=%i Alpha=%i\n", info.Width, info.Height, info.Depth, info.Alpha);

	glBindTexture(GL_TEXTURE_2D, texture);
	image = (GLubyte *) (malloc (IMG_WIDTH * IMG_HEIGHT * 3 * sizeof(GLubyte)));
	if (image == NULL) {
		puts("no image allocated: program ending");
		exit(0);
	}
	else
		puts("image allocated");
	glGetTexImage(GL_TEXTURE_2D, 0, GL_RGB, GL_UNSIGNED_BYTE, image);
	
	reversePixels();
	
	glEnable(GL_CULL_FACE);
	glColor3f(1, 1, 1);

	glutKeyboardFunc(KeyPress);
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);

	glutMainLoop();
}
