小弟正在用VC++写一个位图旋转的程序,但是看了它的理论后头都大了,书上是这样说的:
“设图像旋转前的中心坐标是(a,b),旋转后的中心坐标是(c,d)...”看到这里就很模糊了,书上
开始说的是让图像绕它的中心旋转,为什么它旋转后的中心坐标又不一样呢?应该都是(a,b)啊!而且,书上刚把图像从磁盘里读出来显示在屏幕上时,图像的左上角是和屏幕的左上角重合的。
而它旋转后图像没有被“遮住”一部分,而是向下和向右移动一点后完全显示出来的,请问
这样算是绕图像中心旋转吗?!谢谢!!
“设图像旋转前的中心坐标是(a,b),旋转后的中心坐标是(c,d)...”看到这里就很模糊了,书上
开始说的是让图像绕它的中心旋转,为什么它旋转后的中心坐标又不一样呢?应该都是(a,b)啊!而且,书上刚把图像从磁盘里读出来显示在屏幕上时,图像的左上角是和屏幕的左上角重合的。
而它旋转后图像没有被“遮住”一部分,而是向下和向右移动一点后完全显示出来的,请问
这样算是绕图像中心旋转吗?!谢谢!!
---------------------------------------------------------------------------*/
void CSafeDC::Rotate(int iDegree)
{
if ((iDegree % 360) == 0){
return;
}
CBitmap *pBitmap = GetCurrentBitmap();
BITMAP bitmap;
if (pBitmap->GetBitmap(&bitmap) == 0) {
TRACE("get BITMAP error!\n");
return ;
}
int iBitCount = GetDeviceCaps(/*this->GetSafeHdc(),*/ BITSPIXEL)/8;
int iTotalByte = bitmap.bmWidth * bitmap.bmHeight * iBitCount;
BYTE *pSrcByte = new BYTE[iTotalByte];
BYTE *pNewByte = new BYTE[iTotalByte];
if (pSrcByte == NULL) {
AfxMessageBox("allocate memry fail!");
return ;
}
memset(pSrcByte, 0, sizeof(BYTE)*iTotalByte);
memset(pNewByte, 0, sizeof(BYTE)*iTotalByte);
// 取得前景位图数据
int iGetCount = pBitmap->GetBitmapBits(iTotalByte, pSrcByte);
TRACE("get :%d\n", iGetCount);
int ibmHeight = bitmap.bmHeight;
int ibmWidth = bitmap.bmWidth;
int iHalfHeight = ibmHeight/2;
int iHalfWidth = ibmWidth/2;
float x2=0.0;
float y2=0.0;
for(int i = 0; i < ibmHeight; i++)
{
for(int j = 0; j < ibmWidth; j++)
{
// i,j为目标,找到他要取的数据点
float x1 = j - iHalfWidth; // 转为数学座标系
float y1 = iHalfHeight - i; // 转为数学座标系
TurnDegree(iDegree, x1, y1, x2, y2);
int iX2 = x2 + iHalfWidth/* + 0.5*/; // 转为屏幕坐标
int iY2 = iHalfHeight - y2/* + 0.5*/; // 转为屏幕坐标
if (iX2 >= 0 && iX2 < ibmWidth && iY2 >=0 && iY2 < ibmHeight ) { int iIndexTarge = (i * ibmWidth + j) * iBitCount;
int iIndexGet = (iY2 * ibmWidth + iX2) * iBitCount;
for(int k = 0; k < iBitCount; k++)
{
pNewByte[iIndexTarge + k] = pSrcByte[iIndexGet + k];
}
//SetPixel(y1,x1, RGB(255,255,255));
} }
} int iReturn = pBitmap->SetBitmapBits(iTotalByte, pNewByte);
if (NULL != pSrcByte) {
delete []pSrcByte;
pSrcByte = NULL;
}
if (NULL != pNewByte) {
delete []pNewByte;
pNewByte = NULL;
}
return;
}/*----------------------------------------------------------------------------- 功 能:旋转坐标计算 参数说明:iDegree 为要转的度数
x1,y1 为 要转的坐标
x2,y2为转之后的坐标 返 回 值: 说 明: 2006-10-27 16:22:35
---------------------------------------------------------------------------*/
void CSafeDC::TurnDegree(int iDegree, float x1, float y1, float &x2, float &y2)
{
if(fabs(x1) < 0.0001 && fabs(y1) < 0.0001)
{
x2 = 0;
y2 = 0;
return;
}
float r = sqrt( x1 * x1 + y1 * y1);
if(fabs(y1) < 0.0001)
{
float dDegree = iDegree * PI / 180 ;
float dCaluDegree = 0.0;
if(x1 > 0)
{
dCaluDegree = dDegree;
}
else
{
dCaluDegree = PI + dDegree;
}
x2 = r * cos(dCaluDegree);
y2 = r * sin(dCaluDegree);
}
else
{
float dDegree = iDegree * PI / 180 ;
float dCaluDegree = y1/fabs(y1) * acos(x1 / r) + ( (1-y1/fabs(y1)) ) * PI + dDegree;
x2 = r * cos(dCaluDegree);
y2 = r * sin(dCaluDegree);
}
}
这几天我有点忙,还没来得及做3个坐标的。
非常感谢你!!