/* 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. */
}