⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lens.cpp

📁 MFC 函数实用手册 MFC 函数实用手册
💻 CPP
字号:
/*************************************************************
 *	Author: RJLEE 2003.2.7									 *
 *		  一个放大镜扭曲图形的类							 *
 *															 *
 *	原理:一个透镜怎样扭曲图形,JAVA有类似的Applet,但这个类 *
 *  	  采用了跟JAVA不同的算法,这个类的算法原理是:		 *
 *			  建立一个直角坐标,原点表示透镜的中心,X轴表示  *
 *		  透镜从中心沿半径方向象素分布,Y轴表示透镜中心到扭  *
 *		  曲后从中心沿半径方向象素分布,这样的话直线 y = x  *
 *		  则表示平面镜,y = xa(x的a次方(a<1))曲线则是放大 *
 *		  镜,y = xa(x的a次方(a>1))曲线则是凹透镜。根据曲 *
 *		  线方程可以算出放大后位图某象素点对应源位图的象素点 *
 *************************************************************/
#include "StdAfx.h"
#include "Lens.h"
#include "math.h"

CLens::CLens(void)
{
	m_nRadii = 60;
	m_nDepth = 5;
	m_nBmpX = 0;
	m_nBmpY = 0;
}

CLens::~CLens(void)
{
}

CLens::CLens(HBITMAP hSrcBmp, HDC hDesDC)
{
	m_nRadii = 60;
	m_nDepth = 5;
	m_nBmpX = 0;
	m_nBmpY = 0;
	SelectDC(hDesDC);
	SelectBitmap(hSrcBmp);
}

bool CLens::SelectBitmap(HBITMAP hSrcBmp)
{
	m_hBmp = hSrcBmp;
	return true;
}

bool CLens::SelectBitmap(CBitmap* pSrcBmp)
{
	return SelectBitmap( (HBITMAP)(*pSrcBmp) );
}

bool CLens::SelectDC(HDC hDesDC)
{
	m_hDC = hDesDC;
	return true;
}

bool CLens::SelectDC(CDC* pDesDC)
{
	return SelectDC( pDesDC->GetSafeHdc() );
}

BOOL CLens::CopyBitmap(int x, int y)
{
	return BitBlt(m_hDC,x,y,nBmpW,nBmpH,hMemDC,0,0,SRCCOPY);
}

void CLens::Init()
{
	BITMAP bmp;
	GetObject(m_hBmp, sizeof(BITMAP), &bmp);
	nBmpW = bmp.bmWidth;
	nBmpH = bmp.bmHeight;
	nBytes = nBmpW * nBmpH * 2;
	nBufBytes = m_nRadii*m_nRadii*8;
	nBits = nBmpW * nBmpH;
	
	pData = (WORD*)malloc(nBytes);
	pDataBuf = (WORD*)malloc(nBufBytes);

	GetBitmapBits(m_hBmp, nBytes, pData);

	hMemDC = CreateCompatibleDC(NULL);
	SelectObject(hMemDC, m_hBmp);

	hBmpBuf = CreateCompatibleBitmap(m_hDC, 2*m_nRadii, 2*m_nRadii);
	hMemBufDC = CreateCompatibleDC(NULL);
	SelectObject(hMemBufDC, hBmpBuf);

	Rates = (double*)malloc(m_nRadii*sizeof(double));
	for(int i=1;i<m_nRadii;i++)
	{
		Rates[i] = m_nRadii*pow( /**/((double)i/(double)m_nRadii)/**/,(double)m_nDepth/10 ) / i;
	}
	Rates[0] = 1;
}

#define Distance(x1,y1,x2,y2) sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1))

void CLens::Refraction(int x, int y, int oldx, int oldy)
{
	// 透镜矩形区域的左上角和右下角坐标
	int x1 = x - m_nRadii;
	int y1 = y - m_nRadii;
	int x2 = x + m_nRadii;
	int y2 = y + m_nRadii;

	if(x1<0){x1=0;x2=2*m_nRadii;}
	if(y1<0){y1=0;y2=2*m_nRadii;}
	if(x2>nBmpW){x2=nBmpW;x1=nBmpW-2*m_nRadii;}
	if(y2>nBmpH){y2=nBmpH;y1=nBmpH-2*m_nRadii;}
	
	//////////////////////////////////////////////////////
	// 重绘旧区域
	int ox1 = oldx - m_nRadii;
	int oy1 = oldy - m_nRadii;
	int ox2 = oldx + m_nRadii;
	int oy2 = oldy + m_nRadii;

	if(ox1<0){ox1=0;ox2=2*m_nRadii;}
	if(oy1<0){oy1=0;oy2=2*m_nRadii;}
	if(ox2>nBmpW){ox2=nBmpW;ox1=nBmpW-2*m_nRadii;}
	if(oy2>nBmpH){oy2=nBmpH;oy1=nBmpH-2*m_nRadii;}
	if(oldx != -1 || oldy != -1) 
	{
		// 新旧区域无交集
		if( abs(ox1 - x1) >= 2*m_nRadii || abs(oy1 - y1) >= 2*m_nRadii)
			BitBlt(m_hDC,ox1,oy1,m_nRadii*2,m_nRadii*2,hMemDC,ox1,oy1,SRCCOPY);
		else
		{
			// 新旧区域相交
			if( oy1 < y1 )
			{
				BitBlt(m_hDC, ox1, oy1, m_nRadii*2, y1 - oy1,
						hMemDC, ox1, oy1, SRCCOPY);
				if( ox1 < x1 )
					BitBlt(m_hDC, ox1, y1, (x1 - ox1), (oy2 - y1),
						hMemDC, ox1, y1, SRCCOPY);
				else
					BitBlt(m_hDC, x2, y1, (ox2 - x2), (oy2 - y1),
						hMemDC, x2, y1, SRCCOPY);
			}
			else
			{
				BitBlt(m_hDC, ox1, y2, m_nRadii*2, oy2 - y2,
						hMemDC, ox1, y2, SRCCOPY);
				if( ox1 < x1 )
					BitBlt(m_hDC,ox1, oy1, (x1 - ox1), (y2 - oy1),
							hMemDC,ox1, oy1, SRCCOPY);
				else
					BitBlt(m_hDC,x2, oy1, (ox2 - x2), (y2 - oy1),
							hMemDC,x2, oy1, SRCCOPY);
			}
		}
	}
	//////////////////////////////////////////////////////

	//////////////////////////////////////////////////////
	// 为透镜部分的位图创建一个临时的数据缓冲区
	int cx,cy;
	int newx,newy;
	for(int k=y1;k<y2;k++)
		for(int j=x1;j<x2;j++)
		{
			cx = j - x1;
			cy = k - y1;
			if(Distance(j,k,(x1+x2)/2,(y1+y2)/2)>=m_nRadii/* || j < 0 || j > nBmpW || k < 0 || k > nBmpH */) 
				//pDataBuf[(k-y1)*m_nRadii*2+(j-x1)] = 0xffff;
				pDataBuf[cy*m_nRadii*2+cx] = pData[xy2Index(j,k+1)];
			else
			{
				//pDataBuf[cy*m_nRadii*2+cx] = 0xffff; 
				double a = Rates[(int)(Distance(cx,cy,m_nRadii,m_nRadii))];
				newx = (int)(m_nRadii * (1- 1/a) + cx / a);
				newx += x1;
				newy = (int)(m_nRadii * (1- 1/a) + cy / a);
				newy += (y1 + 1);
				pDataBuf[cy*m_nRadii*2+cx] = pData[xy2Index(newx,newy)];
			}
		}
	SetBitmapBits(hBmpBuf, nBufBytes, pDataBuf);
	LastX = x;LastY = y;
	BitBlt(m_hDC,x1,y1,m_nRadii*2,m_nRadii*2,hMemBufDC,0,0,SRCCOPY);
}

long CLens::xy2Index(int x, int y)
{
	return (nBmpW * (y - 1) + x);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -