以下是我自己写的一个关于位图旋转缩放的函数,已经通过测试直接复制就可以用
参数:rad 角度
nID 位图ID
CDC:CClientDC
本函数的优点是直接操作位图数据,在内存中计算后重新生成位图,效率是比较高的,如果哪位图高人有更好的方法请拿出来与大家分享
int MyBitmap::RotateBitmap(double rad, unsigned int nID,CDC *pDC)
{
CDC thisDC;
thisDC.CreateCompatibleDC(pDC);//创建与屏幕兼容的DC
CBitmap bmp;
if (!bmp.LoadBitmap(nID))
return -1 ;
int Count,Count2;
BITMAP bm1;
bmp.GetBitmap(&bm1);
int tempc;
int xo,yo;//用于记录图形的中心点
double rad1=rad/(180/Pi);//旋转角度转换成弧度
tempc=bm1.bmWidth*bm1.bmWidth+bm1.bmHeight*bm1.bmHeight;
Count = bm1.bmWidthBytes* bm1.bmHeight;//得到buf大小
Count2=tempc*4;//由于一个像素点4个字节所以将它*4
tempc=int(sqrt((double)tempc));//得到要创建的位图的宽度,为原来位图对角线的宽度
DWORD *Cl=new DWORD[Count];
DWORD *Cl2=new DWORD[Count2];
bmp.GetBitmapBits(Count,Cl);//将像素传入数组
bmp.DeleteObject();
xo=yo=tempc/2;//算出中心坐标
int x1,y1;
int x2=bm1.bmWidth/2;
int y2=bm1.bmHeight/2;
int x3=0,y3=0;
double pi=2*Pi;
//半径变量//每取样一周半径增0.7.如果加1,会影响旋转的精度,会产生失真
//增量越大,失真越大.笔者实验得到0.7比较合理,如果太小,在旋转大位图时会影响速度
for (float r=1;r<=xo;r+=0.7){
//角度增量,/R是为了随着取样半径的增大减小失真
for (double a=0;a<pi;a+=0.7/r){
//计算出X1,Y1坐标
//即要取样的点
x1=int(r*cos(a));//x1=int(r*cos(a)/n)除以n就可以缩放了
y1=int(r*sin(a));//y1=int(r*sin(a)/n);
//如果取样的点已经超出了原图像边界,则跳过
if (y1>=y2||y1<-y2||x1>=x2||x1<-x2)
continue;
//算出旋转旋转后的坐标
x3=int(r*cos(a+rad1));
y3=int (r*sin(a+rad1));
//将取样的点的坐标的像素赋给旋转后的坐标
Cl2[(yo+y3)*tempc+xo+x3]=Cl[(y2+y1)*bm1.bmWidth+x2+x1];
}
}
//中点是不旋转的
Cl2[yo*tempc+xo]=Cl[y2*bm1.bmWidth+x2];
bmp.CreateCompatibleBitmap(pDC,tempc,tempc);//创建宽度为原图对角线长度的位图.
bmp.SetBitmapBits(Count2,Cl2);//将像素值写入位图
thisDC.SelectObject(&bmp);
bmp.DeleteObject();
pDC->BitBlt(0,0,tempc,tempc,&thisDC,0,0,SRCCOPY);
thisDC.DeleteDC();
delete [Count] Cl;
delete [Count2] Cl2;
return 0;
}