//FILE: BMPEdit24.cpp
//Implementation of the image editor BMPImage class







#define   FILECHECK       19778        //Integer marks file as BITMAP

#include <fstream.h>			//for file I/O
#include <stdio.h>				//for standard input/output
//#include "ImgEditJob_ids.h"		//for image editing function IDs
#include "BMPEdit24.h"			//declarations for BMPImage class
//#include "CMainWindow.h"		//declarations for CMainWindow class
#include <afxwin.h>				//Application Frameworks Header




/* My two special functions I added to Jake's code to */
/* give it a little more functionality for my program */
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

/*************************************************************/
/*  Author: Alex Slusarek                                    */
/*                                                           */
/*  Function:  returns colorref value of pixel in BMPImage   */
/*                                                           */
/*  Input:  two int values, the coordinates of the pixel     */
/*                                                           */
/*  Output:  returns colorref value of pixel at (x,y)        */
/*************************************************************/
COLORREF BMPImage::BMPGetColor(int x, int y)
{
	// get colorref value from ScanLineIndex[][] in BMPImage class
	COLORREF temp = COLORREF(ScanLineIndex[x][y]);

	// return value acquired
	return (temp);

}  //BMPGetColor

//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////

/*************************************************************/
/*  Author: Alex Slusarek                                    */
/*                                                           */
/*  Function:  sets up specific values in BMPImage class to  */
/*             prepare it for a file save                    */
/*                                                           */
/*  Input:  two int values, the dimensions of the picture    */
/*                                                           */
/*  Output:  returns nothing, changes width and height of    */
/*           BMPImage class                                  */
/*************************************************************/
void BMPImage::BMPFileSetUp(long width, long height)
{

	// change width, height and image size to reflect new picture
	ihWidth = width;
	ihHeight = height;
	ihSizeImage = width * height;

	// nothing to return
	return;

}  //BMPFileSetUp

//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////















/**********************************************************************

  Member functions for BMPImage class

**********************************************************************/

BMPImage::BMPImage(){		//constructor

	

	
	


}

BMPImage::~BMPImage(){		//destructor

	
}




int  BMPImage::BMPRead(char ImgFile[80]){
/**********************************************************************
	This function reads data from a 24-bit RGB bitmap file and stores it
	in a BMPImage object.

    Input:	Filename of bitmap file

    Output: Image data to file header and image data structures 
	
	Return:	0 == File read successful
			-1 == Error opening File
			-2 == File is NOT a bitmap
			-3 == File is NOT 24-bit RGB
			-4 == image data is COMPRESSED

			Image data is read into the BMPImage bitmap data structures
			Any errors in reading the file, as indicated by the return 
			data, are handled by the caller of BMPRead()

***********************************************************************/

	fstream df;	 // filestream variable
	int i, j;    // index variables....
	BYTE pixel_r, pixel_g, pixel_b; //RGB color component variables
	
	

	


	//open file.....
	df.open(ImgFile, ios::in | ios::binary);  
	
	//if file cannot be opened
	if (!df) {

		


		return -1;
	}

	//File is opened. Start reading data

	//Read the file header....

	df.read( (char *)&fhType, sizeof(short));
	df.read( (char *)&fhSize, sizeof(DWORD));
	df.read( (char *)&fhReserved1, sizeof(short));
	df.read( (char *)&fhReserved2, sizeof(short));
    df.read( (char *)&fhOffBits, sizeof(DWORD));
	

	//Check for valid file type
	if (fhType != FILECHECK){

		

		return -2;
	}

	//Read the info header....

	df.read( (char *)&ihSize, sizeof(DWORD));
	df.read( (char *)&ihWidth, sizeof(LONG));
	df.read( (char *)&ihHeight, sizeof(LONG));
	df.read( (char *)&ihPlanes, sizeof(WORD));
	df.read( (char *)&ihBitCount, sizeof(WORD));
	df.read( (char *)&ihCompression, sizeof(DWORD));
	df.read( (char *)&ihSizeImage, sizeof(DWORD));
	df.read( (char *)&ihXPelsPerMeter, sizeof(LONG));
	df.read( (char *)&ihYPelsPerMeter, sizeof(LONG));
	df.read( (char *)&ihClrUsed, sizeof(DWORD));
	df.read( (char *)&ihClrImportant, sizeof(DWORD));
	

	//Make sure bitmap is 24-bit RGB and NOT compressed.....

	if (ihBitCount != 24){

		return -3;
	}

	if (ihCompression > 0){

		return -4;

	}



	


	//Set the size of the image pixel array based upon the height and width
	//of the bitmap
	
	ScanLineIndex.SetSize(ihHeight);
	for( i=0; i<ihHeight; i++){

		ScanLineIndex[i].SetSize(ihWidth);
	}


	
	//Read the actual image data into the pixel array.

	
	for( i=0; i<ihHeight; i++){
		
		for( j=0; j<ihWidth; j++){

			if(df.eof()){
				break;
			}
			
			df.read(&pixel_b, sizeof(BYTE));			
			df.read(&pixel_g, sizeof(BYTE));
			df.read(&pixel_r, sizeof(BYTE));


			//store each pixel as COLORREF, to save space
			ScanLineIndex[i][j] = RGB(pixel_r, pixel_g, pixel_b);
		

			
		}
	}

	
	
	OrigWidth = ihWidth;
	OrigHeight = ihHeight;  //save original dimensions of image


	//close the file
	df.close();

	

	

	
	return 0;    // File read successfully
}


void BMPImage::BMPWrite(char outputfile[80], CDC * dc){
/**********************************************************************
	This function writes data from a BMPImage object to a specified file

	Parameters: char outputfile[80] -- string containing the filename to
									   write to
				CDC * dc -- Windows DC from which to get the pixels

    
	Input:	Image data (raw pixels and header variables) from a BMPImage
			object.

    Output: Binary data to file

	Return: None

			

***********************************************************************/

	fstream outf;         // output file stream
	int i, j;             // index integers for 'for' loops
	BYTE pixel_r, pixel_g, pixel_b; //RGB color component variables

	COLORREF cref;		  //Windows COLORREF integer
	

	//AfxGetMainWnd()->MessageBox("1");
		
	     
    // open the file for writing
    
    outf.open(outputfile, ios::out | ios::binary);


	//If error opening file....
	if(!outf){

		AfxGetMainWnd()->MessageBox( "Cannot open file for writing", 
			"File Error", MB_OK);

		return;
	}

	//AfxGetMainWnd()->MessageBox("2");

	//write the fileheader of the image...
	
	outf.write((char *)&fhType, sizeof(short));
	outf.write((char *)&fhSize, sizeof(DWORD));
	outf.write( (char *)&fhReserved1, sizeof(short));
	outf.write( (char *)&fhReserved2, sizeof(short));
    outf.write( (char *)&fhOffBits, sizeof(DWORD));

	//AfxGetMainWnd()->MessageBox("3");

	// write the info header of the image....

	outf.write( (char *)&ihSize, sizeof(DWORD));
	outf.write( (char *)&ihWidth, sizeof(LONG));
	outf.write( (char *)&ihHeight, sizeof(LONG));
	outf.write( (char *)&ihPlanes, sizeof(WORD));
	outf.write( (char *)&ihBitCount, sizeof(WORD));
	outf.write( (char *)&ihCompression, sizeof(DWORD));
	outf.write( (char *)&ihSizeImage, sizeof(DWORD));
	outf.write( (char *)&ihXPelsPerMeter, sizeof(LONG));
	outf.write( (char *)&ihYPelsPerMeter, sizeof(LONG));
	outf.write( (char *)&ihClrUsed, sizeof(DWORD));
	outf.write( (char *)&ihClrImportant, sizeof(DWORD));


	//AfxGetMainWnd()->MessageBox("4");

	//write the bitmap pixel data....

	for( i=ihHeight; i>0; i--){
		//AfxGetMainWnd()->MessageBox("5");
		for( j=0; j<ihWidth; j++){

			cref = dc->GetPixel(j, i); //Get current image data from temp_dc

			//extract color component data from cref
			pixel_r = GetRValue(cref);
			pixel_g = GetGValue(cref);
			pixel_b = GetBValue(cref);

			
			//Write each pixel component in succession.
			//Order must be b-g-r!!!! (as per Windows Bitmap structure)
			outf.write((char *)&pixel_b, sizeof(BYTE));
			outf.write((char *)&pixel_g, sizeof(BYTE));
			outf.write((char *)&pixel_r, sizeof(BYTE));

		
			
		}

	}

	//AfxGetMainWnd()->MessageBox("6");

	outf.close();  //close the file

	EDIT_FUNCTION = -1;  //reset flag
	//AfxGetMainWnd()->MessageBox("7");	 

	return;

}

void BMPImage::BMPRedraw(CDC * dc){
/**********************************************************************
	This function draws image pixels onto the specified Windows Device
	Context using pixel data contained in the temporary DC (temp_dc). 
	This function is typically called whenever image data is altered, or
	when a window must be refreshed.

	Parameters: CDC * dc -- pointer to DC on which to draw the image

	Input:  pixels stored on the device contex in memory temp_dc

	Output: Pixels are drawn on the specified DC pointed to by CDC * dc

	Return: None.
***********************************************************************/

	

	int i, j;
	int xStartAt, yStartAt;			// coordinates at which to start plotting the bitmap
	

	// Find the coordinates at which to start plotting the bitmap

	xStartAt = BMPGetStartX(ihWidth);//abs((ihWidth/2) - xCenter);
	yStartAt = BMPGetStartY(ihHeight);//(ihHeight/2) + yCenter;


	// Copy the pixel data from temp_dc to dc
	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			dc->SetPixel(j+xStartAt, yStartAt-i, temp_dc->GetPixel(j, i));


		}
	}

	EDIT_FUNCTION = -1;	//reset flag to neutral value

	return;

}

	



void BMPImage::BMPDraw(CDC * dc){
/**********************************************************************
	This function draws image pixels onto the specified Windows Device
	Context using pixel data contained in a BMPImage object's ScanLineArray. 
	This function is typically used for initial drawings and for restoring
	an image to its original appearance

	Parameters: CDC * dc -- pointer to the DC on which to draw the image

	Input:  pixel data in the form of type COLORREF from ScanLineIndex

	Output: Pixels are drawn on the specified DC pointed to by CDC * dc

	Return: None.
***********************************************************************/

	int        xStartAt, yStartAt;

	// Find the coordinates at which to start plotting the bitmap
	
	ihWidth = OrigWidth;
	ihHeight = OrigHeight; //Reset height and width to original values

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	// Draw bitmap image 
	// NOTE: starting at bottom of bitmap	

	
	CBitmap  bmp;	//An empty Windows bitmap
	
	bmp.CreateCompatibleBitmap(dc, ihWidth, ihHeight); //create bitmap compatible with DC
	temp_dc->SelectObject(&bmp);  //place empty bitmap on DC

	//Draw pixels on dc and temp_dc
	for (int i = (ihHeight-1); i > 0; i--){
		for(int j = 0; j<ihWidth; j++){


	
			dc->SetPixel(j+xStartAt, yStartAt-i, ScanLineIndex[i][j]);
			temp_dc->SetPixel(j, i, ScanLineIndex[i][j]);

			
		}
		
	
	}

	EDIT_FUNCTION = -1;       // reset flag to neutral value


	
	return;



}


void BMPImage::BMPCopyDC(CDC * s_dc, CDC * d_dc) {
/**********************************************************************
	This function copies the pixels from one DC to another DC. The source
	and destination DC's must have empty CBitmap objects of equal
	dimensions selected into them.

	Parameters: CDC * s_dc -- Source DC
				CDC * d_dc -- Destination DC

	Input:  Pixels from s_dc

	Output: Pixels are drawn on d_dc

	Return: None.
***********************************************************************/

	int i, j;	//index variables

	//Copy the pixels from the source to the destination

	for (i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			d_dc->SetPixel(j,i, s_dc->GetPixel(j,i));

		}

	}

	return;

}

void BMPImage::BMPBrightnessUp(CDC * dc) {
/**********************************************************************
	This function increaes the color component values of each pixel in
	order to increase the brightness of an image.

	Parameters: CDC * dc -- pointer to Windows device context

	Input:  Pixels from temp_dc

	Output: Pixels are drawn on DC pointed to by CDC * dc

	Return: None.
***********************************************************************/


	int i, j;							//index variables	
	int        xStartAt, yStartAt;	   //start coordinates for drawing image
	BYTE pixel_r, pixel_g, pixel_b;    //RGB color components
	COLORREF   cref;					//Long integer containing RGB data
	

	// Find the coordinates at which to start
			
	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	

	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);  //get pixel from current image
			
			
			pixel_b = GetBValue(cref);  //extract RGB components
			pixel_g = GetGValue(cref);
			pixel_r = GetRValue(cref);

			//scale pixel components upward, if ther is no danger of wrapping the
			//integers

			if (pixel_r < 245)
				pixel_r += 10;
			if (pixel_g < 245) 
				pixel_g += 10;
			if (pixel_b < 245) 
				pixel_b += 10;

			//redraw the pixel on the temp_dc and dc (back to screen)

			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);


		}
	}

	
	
	EDIT_FUNCTION = -1; //reset flag to neutral value
	return;

}


void BMPImage::BMPBrightnessDown(CDC * dc) {
/**********************************************************************
	This function decreaes the color component values of each pixel in
	order to increase the brightness of an image.

	Parameters: CDC * dc -- pointer to Windows device context

	Input:  Pixels from temp_dc

	Output: Pixels are drawn on DC pointed to by CDC * dc and back to 
			temp_dc

	Return: None.
***********************************************************************/


	int i, j;							//index variables
	COLORREF   cref;					//Long integer containing RGB data
	BYTE pixel_r, pixel_g, pixel_b;     //RGB color components
	int        xStartAt, yStartAt;		//Start coordinates for drawing image

	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);



	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);   //get pixel from current image
			
			
			pixel_b = GetBValue(cref);  //extract RGB components
			pixel_g = GetGValue(cref);
			pixel_r = GetRValue(cref);

			//scale pixel components downward, if ther is no danger of wrapping the
			//integers

			if (pixel_r >= 10)
				pixel_r -= 10;
			if (pixel_g >= 10) 
				pixel_g -= 10;
			if (pixel_b >= 10) 
				pixel_b -= 10;

			//redraw the pixel on the temp_dc and dc (back to screen)

			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);


			
		}
	}

		
	EDIT_FUNCTION = -1;  //reset flag to neutral value
	return;

}

void BMPImage::BMPGrayScale(CDC * dc){
/***************************************************************************
	Converts the pixel data in ScanLineIndex to the gray scale (Black & White)
	by averaging each pixel's RGB values, and replacing the RGB values with
	the average.  

	Parameters: CDC * dc -- pointer to Windows device context

	Input:  Pixels from temp_dc

	Output: Pixels are drawn on DC pointed to by CDC * dc and back to 
			temp_dc

	Return: None.

	
***************************************************************************/

	int i, j;						//index variables
	int RGBsum;						//sum of RGB components
	int avgresult;					//result of average 
	COLORREF   cref;				//Long integer containing RGB data
	BYTE pixel_r, pixel_g, pixel_b;	//RGB color components
	int        xStartAt, yStartAt;	//Starting coordinates for drawing the image in the Main Window

	// Find the coordinates at which to start plotting image....
	
	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);



	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);  //get pixel from current image
			
			
			pixel_b = GetBValue(cref);  //extract RGB components
			pixel_g = GetGValue(cref);
			pixel_r = GetRValue(cref);



			//compute average component value for this pixel
			RGBsum = (pixel_r + pixel_g + pixel_b );
			avgresult = RGBsum / 3;

			//assign each RGB component the average
			pixel_r = avgresult;
			pixel_g = avgresult;
			pixel_b = avgresult;

			//redraw the pixel on the temp_dc and dc (back to screen)

			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);


		}

	}

	EDIT_FUNCTION = -1;  //reset flag to neutral value

	return;

}

void BMPImage::BMPNegative(CDC * dc){
/*****************************************************************************
	Alters the pixel data in the current image so that the image appears as a 
	negative of the original.

	Parameters: CDC * dc -- pointer to Windows device context

	Input:  Pixels from temp_dc

	Output: Pixels are drawn on DC pointed to by CDC * dc and back to 
			temp_dc

	Return: None.
*****************************************************************************/

	int i, j;						//index variables
	COLORREF   cref;				//Long integer containing RGB data
	BYTE pixel_r, pixel_g, pixel_b;	//RGB color component values
	int        xStartAt, yStartAt;	//Start coordinates for drawing image in Main Window
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);


	for (i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);  //get pixel from current image
			
			
			pixel_b = GetBValue(cref);  //extract RGB components
			pixel_g = GetGValue(cref);
			pixel_r = GetRValue(cref);

			//invert each pixel component
			pixel_r = 255 - pixel_r;
			pixel_b = 255 - pixel_b;
			pixel_g = 255 - pixel_g;

			//redraw the pixel on temp_dc, and the main window DC (CDC * dc)
			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);

		}
	}

	
	EDIT_FUNCTION = -1; //reset flag to neutral value

	return;
}


void BMPImage::BMPContrastUp(CDC * dc){
/**************************************************************************
	This function alters the pixel data in ScanLineIndex so that the contrast 
	of the image is increased.
	
	Parameters: CDC * dc -- pointer to Windows device context

	Input:  Pixels from temp_dc

	Output: Pixels are drawn on DC pointed to by CDC * dc and back to 
			temp_dc

	Return: None.
**************************************************************************/

	int i, j;					//index variables
	double luminance;			//luminance value for ONE pixel
	double avg_luminance = 0;	//average luminance for all pixels
	COLORREF   cref;			//Long integer containing RGB data
	int xStartAt, yStartAt;		//Start coordinates for drawing image in Main Window
	BYTE pixel_r, pixel_g, pixel_b; //RGB color component values
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	// Compute mean luminance value for all pixels
	// luminance = .30r + .59g + .11b

	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);

			pixel_r = GetRValue(cref);
			pixel_g = GetBValue(cref);
			pixel_b = GetBValue(cref);

			luminance = (.30 * pixel_r) + (.59 * pixel_g) +
				(.11 * pixel_b);

			avg_luminance = avg_luminance + luminance;

		}

	}
	
	//calculate the average
	avg_luminance = avg_luminance / (ihHeight*ihWidth);

	
	//now adjust
	for (i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);		

			pixel_r = GetRValue(cref);
			pixel_g = GetBValue(cref);
			pixel_b = GetBValue(cref);

			luminance = (.30 * pixel_r) + (.59 * pixel_g) +
				(.11 * pixel_b);

			if (luminance < avg_luminance){

				if (pixel_r >= 10)
					pixel_r -= 10;
				if (pixel_g >= 10) 
					pixel_g -= 10;
				if (pixel_b >= 10) 
					pixel_b -= 10;
			}

			if (luminance > avg_luminance){

				if (pixel_r < 245)
					pixel_r += 10;
				if (pixel_g < 245) 
					pixel_g += 10;
				if (pixel_b < 245) 
					pixel_b += 10;

			}

			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);

		}
				

	}

	

	EDIT_FUNCTION = -1;

	return;

}





void BMPImage::BMPContrastDown(CDC * dc){
/**************************************************************************
** Alters the pixel data in ScanLineIndex so that the contrast of the image
** is increased.
**************************************************************************/

	int i, j;
	double luminance;   //luminance value for ONE pixel
	double avg_luminance = 0;
	COLORREF   cref;
	BYTE pixel_r, pixel_b, pixel_g;
	int        xStartAt, yStartAt;
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	// Compute mean luminance value for all pixels
	// luminance = .30r + .59g + .11b

	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);

			pixel_r = GetRValue(cref);
			pixel_g = GetBValue(cref);
			pixel_b = GetBValue(cref);

			luminance = (.30 * pixel_r) + (.59 * pixel_g) +
				(.11 * pixel_b);

			avg_luminance = avg_luminance + luminance;

		}

	}

	avg_luminance = avg_luminance / (ihHeight*ihWidth);

	

	for (i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j,i);

			pixel_r = GetRValue(cref);
			pixel_g = GetBValue(cref);
			pixel_b = GetBValue(cref);

			luminance = (.30 * pixel_r) + (.59 * pixel_g) +
				(.11 * pixel_b);

			if (luminance < avg_luminance) {

				if (pixel_r < 245)
					pixel_r += 10;
				if (pixel_g < 245) 
					pixel_g += 10;
				if (pixel_b < 245) 
					pixel_b += 10;

			}

			if (luminance > avg_luminance) {

				if (pixel_r >= 10)
					pixel_r -= 10;
				if (pixel_g >= 10) 
					pixel_g -= 10;
				if (pixel_b >= 10) 
					pixel_b -= 10;

			}

			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);

				
		}

	}

	

	EDIT_FUNCTION = -1;

	return;

}

/**********************************************************************

  TINT CONTROL FUNCTIONS  

  NOTE: The following six functions are nearly identical in operation,
  except they alter different color components (Red,green or blue).

  These functions increase or decrease a given color component to change
  the appearance of the image so that the given color is more or less
  pronounced in the image.

  Parameters:  CDC * dc Pointer to a Windows Device Context

  Input:  Pixels from temp_dc

  Output: Altered pixels redrawn to dc (window's dc) and temp_dc (mem.)

  Return: None

**********************************************************************/

void BMPImage::BMPRedTintUp(CDC * dc){

	int i,j;		//index variables
	COLORREF   cref;//Long integer containing RGB data
	BYTE pixel_r, pixel_g, pixel_b; //RGB color component values
	int xStartAt, yStartAt; //Start coordinates for drawing image in a window
	
	// Find the coordinates at which to start
	// Used for redrawing image on Main Window's DC

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	for (i=0; i<ihHeight; i++){
		for (j=0; j<ihWidth; j++){

			//get pixel from temp_dc
			cref = temp_dc->GetPixel(j, i); 
			
			//extract RGB values
			pixel_r = GetRValue(cref);
			pixel_g = GetGValue(cref);
			pixel_b = GetBValue(cref);

			//increase red component value
			if (pixel_r < 245)
				pixel_r += 10;

			//redraw pixel to temp_dc and Main Window
			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);

		}
	}

	


	EDIT_FUNCTION = -1;  //reset flag to neutral value

	return;

}

void BMPImage::BMPRedTintDown(CDC * dc){

	////////////////////////////////////////////////
	//NOTE: REFER TO FIRST TINT CONTROL FUNCTION FOR
	//INLINE DOCUMENTATION (COMMENTS)
	//THIS FUNCTION IS IDENTICAL IN PROCEDURE TO THE FIRST

	int i, j;
	COLORREF   cref;
	BYTE pixel_r, pixel_g, pixel_b;
	int        xStartAt, yStartAt;
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	for (i=0; i<ihHeight; i++){
		for (j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);
			
			
			
			pixel_r = GetRValue(cref);
			pixel_b = GetBValue(cref);
			pixel_g = GetGValue(cref);

			// decrease red component value
			if (pixel_r >= 10)
				pixel_r -= 10;
			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);

		}
	}

	

	
	

	EDIT_FUNCTION = -1;

	return;
}

void BMPImage::BMPGreenTintUp(CDC * dc){

	////////////////////////////////////////////////
	//NOTE: REFER TO FIRST TINT CONTROL FUNCTION FOR
	//INLINE DOCUMENTATION (COMMENTS)
	//THIS FUNCTION IS IDENTICAL IN PROCEDURE TO THE FIRST

	int i, j;
	COLORREF   cref;
	BYTE pixel_r, pixel_g, pixel_b;
	int        xStartAt, yStartAt;
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	for (i=0; i<ihHeight; i++){
		for (j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);
			
			
			pixel_r = GetRValue(cref);
			pixel_b = GetBValue(cref);
			pixel_g = GetGValue(cref);

			//increase green component value
			if (pixel_g <= 245)
				pixel_g += 10;

			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);


		}
	}

	

	EDIT_FUNCTION = -1;

	return;

}

void BMPImage::BMPGreenTintDown(CDC * dc){

	////////////////////////////////////////////////
	//NOTE: REFER TO FIRST TINT CONTROL FUNCTION FOR
	//INLINE DOCUMENTATION (COMMENTS)
	//THIS FUNCTION IS IDENTICAL IN PROCEDURE TO THE FIRST

	int i, j;

	COLORREF   cref;
	BYTE pixel_r, pixel_b, pixel_g;
	int        xStartAt, yStartAt;
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	for (i=0; i<ihHeight; i++){
		for (j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);
			
			
			pixel_r = GetRValue(cref);
			pixel_b = GetBValue(cref);
			pixel_g = GetGValue(cref);

			//decrease green component value
			if (pixel_g >= 10)
				pixel_g -= 10;
			
			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);


		}
	}

	
	
	EDIT_FUNCTION = -1;

	return;

}

void BMPImage::BMPBlueTintUp(CDC * dc){

	////////////////////////////////////////////////
	//NOTE: REFER TO FIRST TINT CONTROL FUNCTION FOR
	//INLINE DOCUMENTATION (COMMENTS)
	//THIS FUNCTION IS IDENTICAL IN PROCEDURE TO THE FIRST

	int i, j;
	COLORREF   cref;
	BYTE pixel_r, pixel_g, pixel_b;
	int        xStartAt, yStartAt;
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	for (i=0; i<ihHeight; i++){
		for (j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);			
			
			pixel_r = GetRValue(cref);
			pixel_g = GetGValue(cref);
			pixel_b = GetBValue(cref);

			//increae blue color component value
			if (pixel_b <= 245)
				pixel_b += 10;
			
			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);


		}
	}

	
	
	EDIT_FUNCTION = -1;

	return;

}


void BMPImage::BMPBlueTintDown(CDC * dc){

	////////////////////////////////////////////////
	//NOTE: REFER TO FIRST TINT CONTROL FUNCTION FOR
	//INLINE DOCUMENTATION (COMMENTS)
	//THIS FUNCTION IS IDENTICAL IN PROCEDURE TO THE FIRST

	int i, j;
	COLORREF   cref;
	BYTE pixel_r, pixel_g, pixel_b;
	int xStartAt, yStartAt;
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	for (i=0; i<ihHeight; i++){
		for (j=0; j<ihWidth; j++){

			cref = temp_dc->GetPixel(j, i);			
			
			pixel_r = GetRValue(cref);
			pixel_g = GetGValue(cref);
			pixel_b = GetBValue(cref);

			//decrease blue color component value
			if (pixel_b >= 10)
				pixel_b -= 10;
			
			cref = RGB(pixel_r, pixel_g, pixel_b);
			dc->SetPixel(j+xStartAt, yStartAt-i, cref);
			temp_dc->SetPixel(j, i, cref);

		}
	}

	

	

	EDIT_FUNCTION = -1;

	return;

}

	
void BMPImage::BMPRotate90(CDC * dc){
/**********************************************************************
	This function moves the pixels of an image and redraws them in such
	a fashion that the redrawn image is rotated 90 degrees to the left

	Parameters:  CDC * dc -- Pointer to Windows Device Context 
	
	Input:  Image pixels from temp_dc

	Output: Draws rotated image on temp_dc, Main Window's DC

	Return: None

**********************************************************************/

	int i, j;					//index variables
	LONG Rwidth, Rheight, Temp; //New height and width of bitmap, a temp variable
	CDC * old_img_dc;			//DC to store the original image
	CBitmap OldBitmap, NewBitmap;// CBitmap objects to transfer image between DC's

	

	COLORREF   cref;			//Long integer containing RGB data
	int xStartAt, yStartAt;		//Start coordinates for image drawing
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	//Create dc, make it compatible with temp_dc
	old_img_dc = new CDC;

	old_img_dc->CreateCompatibleDC(temp_dc);

	//Create new CBitmap, make it compatible with temp_dc dimensions

	OldBitmap.CreateCompatibleBitmap(temp_dc, ihWidth, ihHeight);

	//transfer the blank image into old_img_dc
	old_img_dc->SelectObject(&OldBitmap);

	//copy image from temp_dc to old_img_dc
	BMPCopyDC(temp_dc, old_img_dc);

	
	//Create new bitmap with dimensions of rotated DC and select it
	//into temp_dc
	
	NewBitmap.CreateCompatibleBitmap(temp_dc, ihHeight, ihWidth);

	temp_dc->SelectObject(&NewBitmap);
			
	




	Rwidth = 0;
	Rheight = 0;
	for(i=0; i<ihWidth; i++){
		for(j=ihHeight-1; j>0; j--){


			//get pixel from original image and
			//draw it in its rotated coordinates
			cref = old_img_dc->GetPixel(i,j);			
			
			
			temp_dc->SetPixel(Rheight, Rwidth, cref);
						
			Rheight++;

		}

		Rheight = 0;

		Rwidth++;

	}

	//swap image's dimensions to reflect rotation

	Temp = ihWidth;
	ihWidth = ihHeight;
	ihHeight = Temp;

	
		
	
	AfxGetMainWnd()->Invalidate(TRUE);       //Force repaint of rotated image.....	

	EDIT_FUNCTION = -1; //reset flag to neutral value.

	return;

}


	






void BMPImage::BMPMirror(CDC * dc){
/**********************************************************************
	This function reverses the position of each pixel so that the image
	gets inverted, or mirrored, horizontally.

	Parameters: CDC * dc -- pointer to Windows DC

	Input: pixels from temp_dc

	Output: mirror image drawn on temp_dc and the Main Window DC

	Return: NONE
**********************************************************************/

	int i, j;				//index variables
	COLORREF   cref, cref2; //LONG integers that hold RGB data
	int xStartAt, yStartAt; //Start coordinates for image drawing
	
	// Find the coordinates at which to start

	xStartAt = BMPGetStartX(ihWidth);
	yStartAt = BMPGetStartY(ihHeight);

	
	// create mirrored image.....

	for (i=0; i<ihHeight; i++){
		for (j=0; j<(ihWidth/2); j++){
			
			//Get two pixels from temp_dc at opposite ends of the 
			//scan line.
			cref = temp_dc->GetPixel(j, i);
			cref2 = temp_dc->GetPixel((ihWidth-(j+1)), i);
			
			//redraw the pixels opposite of their original coordinates
			dc->SetPixel(j+xStartAt, yStartAt-i, cref2);
			temp_dc->SetPixel(j, i, cref2);
			dc->SetPixel((ihWidth-(j+1)+xStartAt), yStartAt-i, cref);
			temp_dc->SetPixel((ihWidth-(j+1)), i, cref);
		}

	}

	
	EDIT_FUNCTION = -1; //reset flag to neutral value

	return;

}

void BMPImage::BMPZoomIn(CDC * dc){
/**********************************************************************
	This function magnifies an image by 10%

	Parameters: CDC * dc -- pointer to Windows DC

	Input: pixels from temp_dc (copied to another temp)

	Output: magnified image drawn on temp_dc and the Main Window DC

	Return: NONE
**********************************************************************/

	int i, j;								//index variables
	int new_x, new_y;						//new positions of pixels on magnified image
	int XWidth, XHeight;					// expanded width and height of zoomed in bitmap
	CBitmap OldBitmap, NewBitmap;			// CBitmap objects to hold image data
	CDC * old_img_dc;						// DC to hold image data temporarily
	
	
	

	

	
	//First calculate width and height of magnified image
	XWidth = (int)(ihWidth+ihWidth*.1);
	XHeight = (int)(ihHeight + ihHeight*.1);  

	
	// Create new DC to hold old image, transfer old image to that DC
	old_img_dc = new CDC;

	old_img_dc->CreateCompatibleDC(temp_dc);

	OldBitmap.CreateCompatibleBitmap(temp_dc, ihWidth, ihHeight);


	old_img_dc->SelectObject(&OldBitmap);

	BMPCopyDC(temp_dc, old_img_dc);


	NewBitmap.CreateCompatibleBitmap(temp_dc, XWidth, XHeight);

	temp_dc->SelectObject(&NewBitmap);
	


	

	new_x=0;  //x-pos on magnified image
	new_y=0;  //y-pos on magnified image	
	

	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			
			temp_dc->SetPixel(new_x, new_y, old_img_dc->GetPixel(j,i));
			
			if(j%10 == 0){ //every 10th pixel gets drawn twice

				new_x++;
				
				temp_dc->SetPixel(new_x, new_y, old_img_dc->GetPixel(j,i));
				
			}

			new_x++;

		}
		new_x = 0;

		if (i%10 == 0){//every 10th scanline gets drawn twice
			
			new_y++;

			for(j=0; j<ihWidth; j++){

			
			temp_dc->SetPixel(new_x, new_y, old_img_dc->GetPixel(j,i));
			
			if(j%10 == 0){//every 10th pixel gets drawn twice

				new_x++;
				
				temp_dc->SetPixel(new_x, new_y, old_img_dc->GetPixel(j,i));
				
			}

			new_x++;

		}
		new_x = 0;

		}

		new_y++;
	



		
	}

	ihWidth = XWidth;
	ihHeight = XHeight;  //set Bitmap width and height values to new values


	EDIT_FUNCTION = -1;  //reset flag to neutral value
	AfxGetMainWnd()->Invalidate(TRUE); //force redraw of window			

	return;

}


void BMPImage::BMPZoomOut(CDC * dc){
/**********************************************************************
	This function reduces an image by 10%

	Parameters: CDC * dc -- pointer to Windows DC

	Input: pixels from temp_dc (copied to another temp)

	Output: reduced image drawn on temp_dc and the Main Window DC

	Return: NONE
**********************************************************************/

	int i, j;								//index variables
	int new_x, new_y;						//new postions of pixels on reduced image
	int XWidth, XHeight;					//new width and height of reduced bitmap
	CBitmap OldBitmap, NewBitmap;			//CBitmap objects to hold image data
	CDC * old_img_dc;						//DC to temporarily hold image


	//Find height and width of reduced bitmap

	XWidth = (int)(ihWidth-ihWidth*.1);
	XHeight = (int)(ihHeight - ihHeight*.1);

	
	//Create new DC to hold old image and move image into it
	old_img_dc = new CDC;

	old_img_dc->CreateCompatibleDC(temp_dc);

	OldBitmap.CreateCompatibleBitmap(temp_dc, ihWidth, ihHeight);


	old_img_dc->SelectObject(&OldBitmap);

	BMPCopyDC(temp_dc, old_img_dc);


	NewBitmap.CreateCompatibleBitmap(temp_dc, XWidth, XHeight);

	temp_dc->SelectObject(&NewBitmap);
	


	

	new_x=0;
	new_y=0;
	

	for(i=0; i<ihHeight; i++){
		for(j=0; j<ihWidth; j++){

			
			temp_dc->SetPixel(j, i, old_img_dc->GetPixel(new_x,new_y));
			
			if(j%10 == 0){//Skip every 10th pixel

				new_x++;
				
			}

			new_x++;

		}
		new_x = 0;

		if (i%10 == 0){//Skip every 10th scan line
			
			new_y++;

		}
			

		new_y++;
	



		
	}

	AfxGetMainWnd()->Invalidate(TRUE); //Repaint window, draw image....

	ihWidth = XWidth;     //update bitmap dimensions
	ihHeight = XHeight;


	EDIT_FUNCTION = -1;   // set flag to neutral value
	
	return;

}




	

/********************************************************************************
********* NON-EDITING Functions --- These methods do not edit the image, but
********* retrieve data, calculate important values, etc.....********************
********************************************************************************/

LONG BMPImage::GetBMPWidth(){
	// Returns bitmap width

	return ihWidth;

}

LONG BMPImage::GetBMPHeight(){
	//returns bitmap height.

	return ihHeight;

}

int BMPImage::BMPGetStartX(LONG xwidth){
/**********************************************************************************************
******** Uses info from the Main Window to calculate the appropriate x-axis starting position
******** at which to plot the image.......*****************************************************/

	RECT       rr;                          // RECT object to hold Main Window data
	int        xmax;
	int        xCenter;			            // Center x-coordinate for CMainWindow
	


	// Find the CENTER coordinates of the Main Window....

	AfxGetMainWnd()->GetClientRect(&rr); // get Main Window data

    xmax = rr.right;
    xCenter = xmax / 2;
	

	// Find the x-coordinate at which to start plotting the bitmap
	
	
	return (abs((xwidth/2) - xCenter)); // return the answer.....

}

int BMPImage::BMPGetStartY(LONG yheight){
/**********************************************************************************************
******** Uses info from the Main Window to calculate the appropriate y-axis starting position
******** at which to plot the image.......*****************************************************/

	RECT       rr;                          // RECT object to hold Main Window data
	int        ymax;
	int        yCenter;						// Center y-coordinate for CMainWindow
	
	// Find the CENTER coordinates of the Main Window....

	AfxGetMainWnd()->GetClientRect(&rr); // get Main Window data

    ymax = rr.bottom;

	yCenter = ymax / 2;

	// Find the y-coordinate at which to start plotting the bitmap
	
	

	return ((ihHeight/2) + yCenter);

}

		
	


/////////BMPEdit24.cpp