www.pudn.com > CDX.rar > GradientRender.cpp


// GradientRender.cpp: implementation of the CGradientRender class. 
// 
////////////////////////////////////////////////////////////////////// 
 
#include "stdafx.h" 
#include "GradientRender.h" 
#include "math.h" 
 
#ifdef _DEBUG 
#undef THIS_FILE 
static char THIS_FILE[]=__FILE__; 
#define new DEBUG_NEW 
#endif 
 
////////////////////////////////////////////////////////////////////// 
// Construction/Destruction 
////////////////////////////////////////////////////////////////////// 
 
CGradientRender::CGradientRender() 
{ 
	m_Data = NULL; 
} 
 
CGradientRender::~CGradientRender() 
{ 
	if ( m_Data != NULL ) 
		delete m_Data; 
} 
 
void CGradientRender::DrawGradient( HDC hDC, RECT& rect, COLORREF startColor, COLORREF endColor, GradientType gradientType, TransformationType transformationType) 
{ 
	int i, j, y, x1, y1; 
	double r, d, n1; 
 
	// Calculate image size 
	int width = rect.right - rect.left; 
	int height = rect.bottom - rect.top; 
	int size = height * width * 4; 
	double radius = sqrt( pow(height / 2,2) + pow(width / 2,2) ); 
	double k = double(rect.bottom - rect.top) / double(rect.right - rect.left); 
 
	if ( gradientType == GRADIENT_BDIAGONAL ) 
		k = double(rect.bottom - rect.top) / double(rect.left - rect.right); 
 
	if ( ( gradientType == GRADIENT_FDIAGONAL ) || ( gradientType == GRADIENT_BDIAGONAL ) ) 
		gradientType = GRADIENT_DIAGONAL; 
	 
	double n = 0.0; 
	double k1 = -1 / k; 
 
	// Create data buffer 
	m_Data = new unsigned char[size]; 
	 
	// Create gradient 
	for ( i = 0; i < height; i++ ) 
	{ 
		for ( j = 0; j < width; j++ ) 
		{ 
			switch (gradientType) 
			{ 
				// Horizontal gradient 
				case GRADIENT_HORIZONTAL: 
				{ 
					m_Data[i * width * 4 + j * 4] =		(unsigned char)(((double) j / (double)width) * GetBValue(endColor) + (1 - (double) j / (double)width) * GetBValue(startColor)); 
					m_Data[i * width * 4 + j * 4 + 1] = (unsigned char)(((double) j / (double)width) * GetGValue(endColor) + (1 - (double) j / (double)width) * GetGValue(startColor)); 
					m_Data[i * width * 4 + j * 4 + 2] = (unsigned char)(((double) j / (double)width) * GetRValue(endColor) + (1 - (double) j / (double)width) * GetRValue(startColor)); 
				} 
				break; 
 
				// Vertical gradient 
				case GRADIENT_VERTICAL: 
				{ 
					m_Data[i * width * 4 + j * 4] = (unsigned char)(((double) i / (double) height) * GetBValue(endColor) + (1 - (double)i / (double)height) * GetBValue(startColor)); 
					m_Data[i * width * 4 + j * 4 + 1] = (unsigned char)(((double) i / (double) height) * GetGValue(endColor) + (1 - (double)i / (double)height) * GetGValue(startColor)); 
					m_Data[i * width * 4 + j * 4 + 2] = (unsigned char)(((double) i / (double) height) * GetRValue(endColor) + (1 - (double)i / (double)height) * GetRValue(startColor)); 
				} 
				break; 
 
				//  Radial gradient 
				case GRADIENT_RADIAL: 
				{ 
					r = sqrt( pow(double(i - height / 2) / radius,2) + pow(double(j - width / 2) / radius,2) ); 
				 
					if ( r <= 1.0 ) 
					{ 
						m_Data[i * width * 4 + j * 4] = (unsigned char)(r * GetBValue(endColor) + (1 - r) * GetBValue(startColor)); 
						m_Data[i * width * 4 + j * 4 + 1] = (unsigned char)(r * GetGValue(endColor) + (1 - r) * GetGValue(startColor)); 
						m_Data[i * width * 4 + j * 4 + 2] = (unsigned char)(r * GetRValue(endColor) + (1 - r) * GetRValue(startColor)); 
					} 
					else 
					{ 
						m_Data[i * width * 4 + j * 4] = GetBValue(endColor); 
						m_Data[i * width * 4 + j * 4 + 1] = GetGValue(endColor); 
						m_Data[i * width * 4 + j * 4 + 2] = GetRValue(endColor); 
					} 
				} 
				break; 
 
				//  Diagonal gradient 
				case GRADIENT_DIAGONAL: 
				{ 
					y = int(k * (j - width / 2) + n); 
					n1 = int((i - height / 2)  -  k1 * (j - width / 2)); 
					x1 = int((n1 - n) / (k - k1)); 
					y1 = int(k1 * x1 + n1); 
					d = sqrt( pow((j - width / 2) - x1,2) + pow((i - height / 2) - y1,2) )  /  (2 * radius); 
				 
					if ( (i - height / 2) > y ) 
					{ 
						m_Data[i * width * 4 + j * 4] = (unsigned char)((0.5 - d) * GetBValue(endColor) + (0.5 + d) * GetBValue(startColor)); 
						m_Data[i * width * 4 + j * 4 + 1] = (unsigned char)((0.5 - d) * GetGValue(endColor) + (0.5 + d) * GetGValue(startColor)); 
						m_Data[i * width * 4 + j * 4 + 2] = (unsigned char)((0.5 - d) * GetRValue(endColor) + (0.5 + d) * GetRValue(startColor)); 
					} 
					else 
					{ 
						m_Data[i * width * 4 + j * 4] = (unsigned char)((0.5 - d) * GetBValue(startColor) + (0.5 + d) * GetBValue(endColor)); 
						m_Data[i * width * 4 + j * 4 + 1] = (unsigned char)((0.5 - d) * GetGValue(startColor) + (0.5 + d) * GetGValue(endColor)); 
						m_Data[i * width * 4 + j * 4 + 2] = (unsigned char)((0.5 - d) * GetRValue(startColor) + (0.5 + d) * GetRValue(endColor)); 
					} 
				} 
				break; 
			} 
		} 
	} 
 
	if ( transformationType != TRANSFORMATION_NONE ) 
		ApplyTransformation( width, height, transformationType ); 
 
	// Create temporary bitmap 
	HBITMAP hBitmap = (HBITMAP)CreateBitmap( width, height, 1, 32, m_Data ); 
 
	// Create temporary device context 
	HDC hMemDC = CreateCompatibleDC(hDC); 
	HBITMAP hOldBitmap = (HBITMAP)SelectObject( hMemDC, hBitmap ); 
 
	// Blit gradient bitmap 
	BitBlt( hDC, rect.left, rect.top, width, height, hMemDC, 0, 0, SRCCOPY ); 
 
	// Free memory 
	SelectObject( hMemDC, hOldBitmap ); 
	DeleteDC(hMemDC); 
	DeleteObject(hBitmap); 
	delete m_Data; 
	m_Data = NULL; 
} 
 
void CGradientRender::ApplyTransformation(int width, int height, TransformationType transformationType) 
{ 
	int X, Y; 
	double r, fi; 
	double R = sqrt( pow(width / 4,2) + pow(height / 4,2) ); 
	double FI = atan( double(height) / double(width) ); 
 
	int size = height * width * 4; 
	unsigned char* newBuffer = new unsigned char[size]; 
	memcpy( newBuffer, m_Data, size ); 
 
	for ( int i  =0; i < height; i++ ) 
	{ 
		for ( int j = 0; j < width; j++ ) 
		{ 
			switch (transformationType) 
			{ 
				case TRANSFORMATION_CHARICATURE: 
				{ 
					fi = atan(double(i - height / 2) / double(j - width / 2)); 
					r = sqrt( pow((i - height / 2),2)  +  pow((j - width / 2),2) ); 
					X = int(sqrt(r * R * 2) * cos(fi)); 
					Y = int(fabs(sqrt(r * R * 2) * sin(fi))); 
					 
					newBuffer[i * width * 4  +  j * 4] = m_Data[Y * width * 4  +  X * 4]; 
					newBuffer[i * width * 4  +  j * 4 + 1] = m_Data[Y * width * 4  +  X * 4 + 1]; 
					newBuffer[i * width * 4  +  j * 4 + 2] = m_Data[Y * width * 4  +  X * 4 + 2]; 
				} 
				break; 
 
				case TRANSFORMATION_FISHEYE: 
				{ 
					fi = atan(double(i - height / 2) / double(j - width / 2)); 
					r = sqrt( pow((i - height / 2),2)  +  pow((j - width / 2),2) ); 
					X = int((pow(r,2) / R) * cos(fi)); 
					Y = int(fabs((pow(r,2) / R) * sin(fi))) % height; 
					 
					newBuffer[i * width * 4  +  j * 4] = m_Data[Y * width * 4  +  X * 4]; 
					newBuffer[i * width * 4  +  j * 4 + 1] = m_Data[Y * width * 4  +  X * 4 + 1]; 
					newBuffer[i * width * 4  +  j * 4 + 2] = m_Data[Y * width * 4  +  X * 4 + 2]; 
				} 
				break; 
 
				case TRANSFORMATION_SWIRLED: 
				{ 
					fi = atan(double(i - height / 2) / double(j - width / 2)); 
					r = sqrt( pow((i - height / 2),2)  +  pow((j - width / 2),2) ); 
					X = int(fabs(r * cos(fi + r / 8))); 
					Y = int(fabs(r * sin(fi + r / 8))); 
				 
					newBuffer[i * width * 4  +  j * 4] = m_Data[Y * width * 4  +  X * 4]; 
					newBuffer[i * width * 4  +  j * 4 + 1] = m_Data[Y * width * 4  +  X * 4 + 1]; 
					newBuffer[i * width * 4  +  j * 4 + 2] = m_Data[Y * width * 4  +  X * 4 + 2]; 
				} 
				break; 
 
				case TRANSFORMATION_CYLINDER: 
				{ 
					fi = atan(double(i - height / 2) / double(j - width / 2)); 
					r = sqrt( pow((i - height / 2),2)  +  pow((j - width / 2),2) ); 
					X = abs((j - width / 2)  +  int(fi + r / 10) % 32  -  8); 
					Y = i; 
					 
					newBuffer[i * width * 4  +  j * 4] = m_Data[Y * width * 4  +  X * 4]; 
					newBuffer[i * width * 4  +  j * 4 + 1] = m_Data[Y * width * 4  +  X * 4 + 1]; 
					newBuffer[i * width * 4  +  j * 4 + 2] = m_Data[Y * width * 4  +  X * 4 + 2]; 
				} 
				break; 
 
				case TRANSFORMATION_SHIFT: 
				{ 
					fi = atan(double(i - height / 2) / double(j - width / 2)); 
					r = sqrt( pow((i - height / 2),2)  +  pow((j - width / 2),2) ); 
					X = int(fabs(r * cos(fi))); 
					Y = int(fabs(r * sin(fi))); 
 
					newBuffer[i * width * 4  +  j * 4] = m_Data[Y * width * 4  +  X * 4]; 
					newBuffer[i * width * 4  +  j * 4 + 1] = m_Data[Y * width * 4  +  X * 4 + 1]; 
					newBuffer[i * width * 4  +  j * 4 + 2] = m_Data[Y * width * 4  +  X * 4 + 2]; 
				} 
				break; 
			} 
		} 
	} 
 
	memcpy( m_Data, newBuffer, size ); 
	delete newBuffer; 
}