📄 lens.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 + -