Saket Soni


back to home


/* This Program takes a bmp file as input from the command prompt
 * and then shows an interface using OpenGL library to sharpen or
 * blurr the image.
 */

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

/* For reading the bmp-file header
 */
struct HEADER
{
   unsigned char type[2];                   /* Magic identifier            */
   unsigned int size;                       /* File size in bytes          */
   unsigned short int reserved1, reserved2;
   unsigned int offset;                     /* Offset to image data, bytes */
};

/* For reading the bmp-file info header
 */
struct INFOHEADER
{
   unsigned int size;               /* Header size in bytes      */
   int width,height;                /* Width and height of image */
   unsigned short int planes;       /* Number of colour planes   */
   unsigned short int bits;         /* Bits per pixel            */
   unsigned int compression;        /* Compression type          */
   unsigned int imagesize;          /* Image size in bytes       */
   int xresolution,yresolution;     /* Pixels per meter          */
   unsigned int ncolours;           /* Number of colours         */
   unsigned int importantcolours;   /* Important colours         */
};


/* Variable Declarations specifing the properties of the main
 * window.
 */
unsigned int windowWidth = 1000;
unsigned int windowHeight = 700;

unsigned int windowXPos = (1024-windowWidth)/2;
unsigned int windowYPos = (768-windowHeight)/2;

unsigned int orgImgXPos = 20;
unsigned int orgImgYPos = 40;

unsigned int outImgXPos = 0;
unsigned int outImgYPos = 40;

typedef unsigned char HISTOGRAM [256][3];

unsigned char * orgMatrix;
unsigned int orgWidth, orgHeight;
HISTOGRAM orgHistogram;

unsigned char * outMatrix;
HISTOGRAM outHistogram;

unsigned int buttonXPos = 0;
unsigned int buttonXRPos = 0;

unsigned int buttonWidth = 0;
unsigned int buttonHeight = 0;

unsigned int sharpenYPos = 40;
unsigned int sharpenYBPos = 0;
unsigned int blurrYPos = 0;
unsigned int blurrYBPos = 0;
unsigned int resetYPos = 0;
unsigned int resetYBPos = 0;
unsigned int exitYPos = 0;
unsigned int exitYBPos = 0;
unsigned int highPassYPos = 0;
unsigned int highPassYBPos = 0;
unsigned int distanceBetweenButtons = 15;

unsigned char * sharpenP, * sharpenUP, * sharpen;
unsigned char * blurrP, * blurrUP, * blurr;
unsigned char * resetP, * resetUP, * reset;
unsigned char * exitP, * exitUP, * exitB;
unsigned char * highP, * highUP, * high;


/* Function for reading a bmp file.
 */
void readTheBmpFile ( char * str, unsigned char *& matrix,
			 unsigned int &width, unsigned int &height )
{
	assert ( matrix == NULL );
	unsigned int linePadding;
	unsigned int bytesPerPixel;
	HEADER fileHeader;
	INFOHEADER fileInfo;

	int fd = _open ( str, O_RDONLY );
	assert ( fd != -1 );

	cout << "Reading the file : " << str << endl;

	// reading the File Header ...
	_read ( fd, &fileHeader.type, 2 );
	_read ( fd, &fileHeader.size, 4 );
	_read ( fd, &fileHeader.reserved1, 2 );
	_read ( fd, &fileHeader.reserved2, 2 );
	_read ( fd, &fileHeader.offset, 4 );
	cout << "File Header : " << endl
		 << "  type : " << fileHeader.type[0] << fileHeader.type[1]
		 << " (BMP identification)" << endl
		 << "  size : " << fileHeader.size << " (file size)" << endl
		 << "  res1 : " << fileHeader.reserved1 << endl
		 << "  res2 : " << fileHeader.reserved2 << endl
		 << "  offs : " << fileHeader.offset 
		 << " (offset of pixel data)" << endl;

	// reading the File Infomation Header ...
	_read ( fd, &fileInfo.size, 4 );
	_read ( fd, &fileInfo.width, 4 );	width = fileInfo.width;
	_read ( fd, &fileInfo.height, 4 );	height = fileInfo.height;
	_read ( fd, &fileInfo.planes, 2 );
	_read ( fd, &fileInfo.bits, 2 );
	_read ( fd, &fileInfo.compression, 4 );
	_read ( fd, &fileInfo.imagesize, 4 );
	_read ( fd, &fileInfo.xresolution, 4 );
	_read ( fd, &fileInfo.yresolution, 4 );
	_read ( fd, &fileInfo.ncolours, 4 );
	_read ( fd, &fileInfo.importantcolours, 4 );
	cout << "File Info : " << endl
		 << "  size   : " << fileInfo.size 
		 << " (size of file info header)" << endl
		 << "  width  : " << fileInfo.width << endl
		 << "  height : " << fileInfo.height << endl
		 << "  planes : " << fileInfo.planes 
		 << " (no. of color planes)" << endl
		 << "  bits   : " << fileInfo.bits << " (bits per pixel)" 
		 << endl
		 << "  compression : " << fileInfo.compression << endl
		 << "  imagesize   : " << fileInfo.imagesize 
		 << " (bytes of pixel data)" << endl
		 << "  xresolution : " << fileInfo.xresolution 
		 << " (pixels per meter)" << endl
		 << "  yresolution : " << fileInfo.yresolution 
		 << " (pixels per meter)" << endl
		 << "  ncolours    : " << fileInfo.ncolours << endl
		 << "  importantcolours : " << fileInfo.importantcolours 
		 << endl;

	linePadding = ( 4 - ( fileInfo.width * fileInfo.bits/8 ) % 4 ) % 4 ;
	cout << "  linePadding : " << linePadding << endl;

	assert ( fileInfo.compression == 0 && fileInfo.planes == 1 );
	assert ( fileInfo.ncolours == 0 );
	assert ( fileInfo.bits == 24 );
	bytesPerPixel = fileInfo.bits/8 ;
	assert ( bytesPerPixel == 3 );

	// allocating memory for orignal image matrix ...
	matrix    = new unsigned 
		 char [ fileInfo.width * fileInfo.height * bytesPerPixel ];
	assert ( matrix != NULL );

	// reading the Image Data ...
	int linewidth = fileInfo.width*bytesPerPixel;
	for ( int h = 0 ; h < fileInfo.height ; h++ )
	{
		_read ( fd, matrix + linewidth * h, linewidth );
		_lseek ( fd, linePadding, SEEK_CUR );
	}

	_close ( fd );
}

/* For making copies of the image matrix.
 */
void copyImageMatrix ( unsigned char * srcMatrix, unsigned char *& destMatrix,
		 unsigned int width, unsigned int height )
{
	assert ( srcMatrix != NULL );
	assert ( destMatrix == NULL );
	destMatrix = new unsigned char [ width * height * 3 ];
	assert ( destMatrix != NULL );
	
	unsigned char * src = http://www.geocities.com/saket_soni1980/assign/mts3/srcMatrix;
	unsigned char * dst = destMatrix;
	for ( unsigned int w = 0 ; w < width ; w++ )
	for ( unsigned int h = 0 ; h < height ; h++ )
	for ( int c = 0 ; c < 3 ; c++ )
		*dst++ = *src++;
}

/* For building the histogram of an image.
 */
void buildHistogram ( unsigned char * srcMatrix, HISTOGRAM histo,
		 unsigned int width, unsigned int height )
{
	assert ( histo != NULL );

	// initializing the histogram ...
	for ( int k = 0 ; k < 256 ; k++ )
		histo[k][0] = histo[k][1] = histo[k][2] = unsigned char (0) ;

	// building the histogram ...
	unsigned char * tempOrg  = srcMatrix;
	for ( unsigned int i = 0 ; i < height ; i++ )
	for ( unsigned int j = 0 ; j < width ; j++ )
	{
		unsigned char b = *tempOrg++;
		unsigned char g = *tempOrg++;
		unsigned char r = *tempOrg++;
		histo[b][0]++;
		histo[g][1]++;
		histo[r][2]++;
	}
}

/* Function to display the main window and its contents.
 */
void display(void)
{
	// clear all pixels ...
	glClear (GL_COLOR_BUFFER_BIT);

	int yDisp = windowHeight - orgHeight - orgImgYPos ;
	int xDisp = orgImgXPos ; 
	unsigned char * temp = orgMatrix;
	glBegin ( GL_POINTS );
	for ( unsigned int i = 0 ; i < orgHeight ; i++ )
	for ( unsigned int j = 0 ; j < orgWidth ; j++ )
	{

		double b = *temp++ / 255.0;
		double g = *temp++ / 255.0;
		double r = *temp++ / 255.0;
		glColor3f ( r, g, b );
		glVertex2f ( j + xDisp, i + yDisp );
	}

	yDisp = windowHeight - orgHeight - outImgYPos;
	xDisp = outImgXPos;
	temp = outMatrix;
	for ( i = 0 ; i < orgHeight ; i++ )
	for ( unsigned int j = 0 ; j < orgWidth ; j++ )
	{
		double b = *temp++ / 255.0;
		double g = *temp++ / 255.0;
		double r = *temp++ / 255.0;
		glColor3f ( r, g, b );
		glVertex2f ( j + xDisp, i + yDisp );
	}

	yDisp = windowHeight - buttonHeight - sharpenYPos;
	xDisp = buttonXPos;
	temp = sharpen;
	for ( i = 0 ; i < buttonHeight ; i++ )
	for ( unsigned int j = 0 ; j < buttonWidth ; j++ )
	{
		double b = *temp++ / 255.0;
		double g = *temp++ / 255.0;
		double r = *temp++ / 255.0;
		glColor3f ( r, g, b );
		glVertex2f ( j + xDisp, i + yDisp );
	}

	yDisp = windowHeight - buttonHeight - blurrYPos;
	xDisp = buttonXPos;
	temp = blurr;
	for ( i = 0 ; i < buttonHeight ; i++ )
	for ( unsigned int j = 0 ; j < buttonWidth ; j++ )
	{
		double b = *temp++ / 255.0;
		double g = *temp++ / 255.0;
		double r = *temp++ / 255.0;
		glColor3f ( r, g, b );
		glVertex2f ( j + xDisp, i + yDisp );
	}

	yDisp = windowHeight - buttonHeight - resetYPos;
	xDisp = buttonXPos;
	temp = reset;
	for ( i = 0 ; i < buttonHeight ; i++ )
	for ( unsigned int j = 0 ; j < buttonWidth ; j++ )
	{
		double b = *temp++ / 255.0;
		double g = *temp++ / 255.0;
		double r = *temp++ / 255.0;
		glColor3f ( r, g, b );
		glVertex2f ( j + xDisp, i + yDisp );
	}

	yDisp = windowHeight - buttonHeight - exitYPos;
	xDisp = buttonXPos;
	temp = exitB;
	for ( i = 0 ; i < buttonHeight ; i++ )
	for ( unsigned int j = 0 ; j < buttonWidth ; j++ )
	{
		double b = *temp++ / 255.0;
		double g = *temp++ / 255.0;
		double r = *temp++ / 255.0;
		glColor3f ( r, g, b );
		glVertex2f ( j + xDisp, i + yDisp );
	}

	yDisp = windowHeight - buttonHeight - highPassYPos;
	xDisp = buttonXPos;
	temp = high;
	for ( i = 0 ; i < buttonHeight ; i++ )
	for ( unsigned int j = 0 ; j < buttonWidth ; j++ )
	{
		double b = *temp++ / 255.0;
		double g = *temp++ / 255.0;
		double r = *temp++ / 255.0;
		glColor3f ( r, g, b );
		glVertex2f ( j + xDisp, i + yDisp );
	}

	glEnd();

	// start processing buffered OpenGL routines ...
	glFlush ();
}

/* Function to blurr the image.
 */
void blurrImage ( unsigned char *& matrix, unsigned int width,
		 unsigned int height, unsigned int count = 1 )
{
	unsigned char * tempMatrix = new unsigned char [ width * height * 3 ];
	assert ( tempMatrix != NULL );
	for ( unsigned int k = 0 ; k < count ; k++ )
	{
		for ( unsigned int y = 0 ; y < height ; y++ )
		for ( unsigned int x = 0 ; x < width  ; x++ )
		for ( int c = 0 ; c < 3 ; c++ )
		{
	* ( tempMatrix + ( y * width + x ) * 3 + c )
	= ( * ( matrix + ( ((y-1)%height) * width + (x-1)%width ) * 3 + c ) +
	* ( matrix + ( y * width + (x-1)%width ) * 3 + c ) +
	* ( matrix + ( ((y+1)%height) * width + (x-1)%width ) * 3 + c ) +
	* ( matrix + ( ((y-1)%height) * width + x ) * 3 + c ) +
	* ( matrix + ( y * width + x ) * 3 + c ) +
	* ( matrix + ( ((y+1)%height) * width + x ) * 3 + c ) +
	* ( matrix + ( ((y-1)%height) * width + (x+1)%width ) * 3 + c ) +
	* ( matrix + ( y * width + (x+1)%width ) * 3 + c ) +
	* ( matrix + ( ((y+1)%height) * width + (x+1)%width ) * 3 + c )
	  ) / 9.0 ;
		}

		unsigned char * temp = tempMatrix;
		tempMatrix = matrix;
		matrix = temp;
	}
	delete[] tempMatrix;
}

/* Function for sharpening using high pass filtering.
 */
void highPass ( unsigned char *& matrix, unsigned int width,
		 unsigned int height, unsigned int count = 1 )
{
	double * tempMatrix = new double [ width * height * 3 ];
	assert ( tempMatrix != NULL );
	for ( unsigned int k = 0 ; k < count ; k++ )
	{
		double largest = -400, smallest = 400;
		for ( unsigned int x = 0 ; x < width  ; x++ )
		for ( unsigned int y = 0 ; y < height ; y++ )
		for ( int c = 0 ; c < 3 ; c++ )
		{
			
double t = ( * ( matrix + ( ((y-1)%height) * width + (x-1)%width ) * 3 + c ) +
	* ( matrix + ( y * width + (x-1)%width ) * 3 + c ) +
	* ( matrix + ( ((y+1)%height) * width + (x-1)%width ) * 3 + c ) +
	* ( matrix + ( ((y-1)%height) * width + x ) * 3 + c ) +
	- 9.8 * (*( matrix + ( y * width + x ) * 3 + c)) +
	* ( matrix + ( ((y+1)%height) * width + x ) * 3 + c ) +
	* ( matrix + ( ((y-1)%height) * width + (x+1)%width ) * 3 + c ) +
	* ( matrix + ( y * width + (x+1)%width ) * 3 + c ) +
	* ( matrix + ( ((y+1)%height) * width + (x+1)%width ) * 3 + c )
	) / -9.0 ;
			if ( t > largest )
				largest = t;
			else if ( t < smallest )
				smallest = t;
			* ( tempMatrix + ( y * width + x ) * 3 + c ) = t; 
		}
		double * src = http://www.geocities.com/saket_soni1980/assign/mts3/tempMatrix;
		unsigned char * dst = matrix;
		double scale = largest - smallest + 0.1;
		for ( unsigned int w = 0 ; w < width ; w++ )
		for ( unsigned int h = 0 ; h < height ; h++ )
		for ( int c = 0 ; c < 3 ; c++ )
			*dst++ = ( ( *src++ - smallest ) / scale * 256 );
	}
	delete[] tempMatrix;
}

/* Function for simple sharpening.
 */
void sharpenImage ( unsigned char *& matrix, unsigned int width,
		 unsigned int height, unsigned int count = 1 )
{
	double * tempMatrix = new double [ width * height * 3 ];
	assert ( tempMatrix != NULL );
	for ( unsigned int k = 0 ; k < count ; k++ )
	{
		double largest = -400, smallest = 400;
		for ( unsigned int x = 0 ; x < width  ; x++ )
		for ( unsigned int y = 0 ; y < height ; y++ )
		for ( int c = 0 ; c < 3 ; c++ )
		{
	double t1 = * ( matrix + ( y * width + (x+1)%width ) * 3 + c ) -
		* ( matrix + ( y * width + x ) * 3 + c );
	double t2 = * ( matrix + ( (y+1)%height * width + x ) * 3 + c ) -
		* ( matrix + ( y * width + x ) * 3 + c );
	double t  = * ( matrix + ( y * width + x ) * 3 + c ) + sqrt(t1*t1 
		+ t2*t2)/20; //(t1+t2)/2;
			if ( t > largest )
				largest = t;
			else if ( t < smallest )
				smallest = t;
			* ( tempMatrix + ( y * width + x ) * 3 + c ) = t;
		}
		double * src = http://www.geocities.com/saket_soni1980/assign/mts3/tempMatrix;
		unsigned char * dst = matrix;
		double scale = largest - smallest + 0.1;
		for ( unsigned int w = 0 ; w < width ; w++ )
		for ( unsigned int h = 0 ; h < height ; h++ )
		for ( int c = 0 ; c < 3 ; c++ )
			*dst++ = ( ( *src++ - smallest ) / scale * 256 );
	}
	delete[] tempMatrix;
}

/* Event Handlers ...
 */
void onReset ( void )
{
	unsigned char * src = http://www.geocities.com/saket_soni1980/assign/mts3/orgMatrix;
	unsigned char * dst = outMatrix;
	for ( unsigned int w = 0 ; w < orgWidth ; w++ )
	for ( unsigned int h = 0 ; h < orgHeight ; h++ )
	for ( int c = 0 ; c < 3 ; c++ )
		*dst++ = *src++;
}

void onBlurr ( void )
{
	blurrImage ( outMatrix, orgWidth, orgHeight );
}

void onHighPass ( void )
{
	highPass ( outMatrix, orgWidth, orgHeight );
}

void onSharpen ( void )
{
	sharpenImage ( outMatrix, orgWidth, orgHeight );
}

void keyboard ( unsigned char key, int x, int y )
{
	switch ( key )
	{
	case 's': case 'S':
		sharpen = sharpenP;
		display();
		onSharpen();
		sharpen = sharpenUP;
		display();
		break;
	case 'b': case 'B':
		blurr = blurrP;
		display();
		onBlurr();
		blurr = blurrUP;
		display();
		break;
	case 'r': case 'R':
		reset = resetP;
		display();
		onReset();
		reset = resetUP;
		display();
		break;
	case 'h': case 'H':
		high = highP;
		display();
		onHighPass();
		high = highUP;
		display();
		break;
	case 'x': case 'X': case 27:
		exitB = exitP;
		display();
		exitB = exitUP;
		display();
		exit(1);
	default:
		cout << "\aInvalid key pressed ! " << int ( key ) << endl;
	}
}


bool mouseInSharpen ( int x, int y )
{
	return ( signed (buttonXPos) <= x && signed(buttonXRPos) >= x && 
			 signed (sharpenYPos) <= y && signed(sharpenYBPos) >= y ) ?
		true : false;
}

bool mouseInBlurr ( int x, int y )
{
	return ( signed (buttonXPos) <= x && signed(buttonXRPos) >= x && 
		 signed (blurrYPos) <= y && signed(blurrYBPos) >= y ) ?
		true : false;
}

bool mouseInReset ( int x, int y )
{
	return ( signed (buttonXPos) <= x && signed(buttonXRPos) >= x && 
		 signed (resetYPos) <= y && signed(resetYBPos) >= y ) ?
		true : false;
}

bool mouseInExit ( int x, int y )
{
	return ( signed (buttonXPos) <= x && signed(buttonXRPos) >= x && 
		 signed (exitYPos) <= y && signed(exitYBPos) >= y ) ?
		true : false;
}

bool mouseInHighPass ( int x, int y )
{
	return ( signed (buttonXPos) <= x && signed(buttonXRPos) >= x && 
		 signed (highPassYPos) <= y && signed(highPassYBPos) >= y ) ?
		true : false;
}

void mouseClick ( int button, int state, int x, int y )
{
	switch ( button )
	{
	case GLUT_LEFT_BUTTON:
		switch ( state )
		{
		case GLUT_DOWN:
			if ( mouseInSharpen(x,y) )
			{
				sharpen = sharpenP;
				display();
				onSharpen();
				sharpen = sharpenUP;
				display();
			}
			else if ( mouseInBlurr(x,y) )
			{
				blurr = blurrP;
				display();
				onBlurr();
				blurr = blurrUP;
				display();
			}
			else if ( mouseInReset(x,y) )
			{
				reset = resetP;
				display();
				onReset();
				reset = resetUP;
				display();
			}
			else if ( mouseInHighPass(x,y) )
			{
				high = highP;
				display();
				onHighPass();
				high = highUP;
				display();
			}
			else if ( mouseInExit(x,y) )
			{
				exitB = exitP;
				display();
				exitB = exitUP;
				display();
				exit(1);
			}
			break;
		case GLUT_UP:
			break;
		}
		break;

	case GLUT_MIDDLE_BUTTON:

		break;

	case GLUT_RIGHT_BUTTON:

		break;
	}
}

/* For Initializing OpenGl system.
 */
void init (void)
{
	// select the clearing (background) color ...
	glClearColor (1.0, 1.0, 1.0, 0.0);

	// initialize viewing values ...
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D ( 0.0, windowWidth , 0.0, windowHeight );
}

/* For loading the button images.
 */
void loadButtons(void)
{
	readTheBmpFile ( "buttons\\sharpen up.bmp", sharpenUP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\sharpen p.bmp", sharpenP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\blurr up.bmp", blurrUP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\blurr p.bmp", blurrP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\reset up.bmp", resetUP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\reset p.bmp", resetP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\exit up.bmp", exitUP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\exit p.bmp", exitP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\high up.bmp", highUP, buttonWidth,
		 buttonHeight );
	readTheBmpFile ( "buttons\\high p.bmp", highP, buttonWidth,
		 buttonHeight );
	sharpen = sharpenUP;
	blurr = blurrUP;
	reset = resetUP;
	exitB = exitUP;
	high = highUP;
	buttonXPos = windowWidth/2 - buttonWidth/2;
	buttonXRPos = buttonXPos + buttonWidth;
	sharpenYBPos = sharpenYPos + buttonHeight;
	blurrYPos = sharpenYPos + buttonHeight + distanceBetweenButtons;
	blurrYBPos = blurrYPos + buttonHeight;
	resetYPos = blurrYPos +  buttonHeight + distanceBetweenButtons;
	resetYBPos = resetYPos + buttonHeight;
	exitYPos = resetYPos + buttonHeight + distanceBetweenButtons;
	exitYBPos = exitYPos + buttonHeight;
	highPassYPos = exitYPos + buttonHeight + distanceBetweenButtons;
	highPassYBPos = highPassYPos + buttonHeight;
}

/* For reading image from disk.
 */
void readImageDataFromDisk(char * str)
{
	// reading bmp file ...
	readTheBmpFile ( str, orgMatrix, orgWidth, orgHeight );
	outImgXPos = windowWidth - orgImgXPos - orgWidth;
	copyImageMatrix(orgMatrix,outMatrix,orgWidth, orgHeight);
}

/*
 * Declare initial window size, position, and display mode
 * (single buffer and RGBA). Open window with "hello"
 * in its title bar. Call initialization routines.
 * Register callback function to display graphics.
 * Enter main loop and process events.
 */
int main(int argc, char** argv)
{
	// reading buttons ...
	loadButtons();

	// reading bmp file ...
	readImageDataFromDisk(argv[1]);

	// opengl stuff ...
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize (windowWidth, windowHeight);
	glutInitWindowPosition (windowXPos, windowYPos);
	glutCreateWindow ("Multimedia Assignment 2 by Saket Soni (mtc0420)");
	init ();
	glutDisplayFunc(display);
	glutKeyboardFunc(keyboard);
	glutMouseFunc(mouseClick);
	glutMainLoop();

	// garbage collecting ...
	if ( orgMatrix )
		delete[] orgMatrix;
	if ( outMatrix )
		delete[] outMatrix;

	return 0; /* ISO C requires main to return int. */
}



back to home



Locations of visitors to this page 1