硬件平台: S3C2440 + 4.3寸TFT(480x272)
旋转算法:
void RotateImage(HDC hdc,int x,int y,HIMG hImg,int angle)
{
S32 radians;
S32 cos_a,sin_a,cos_ay,sin_ay;
S32 point1x,point1y,point2x,point2y,point3x,point3y;
S32 minx,miny,maxx,maxy;
S32 xx,yy,xx0,yy0,xx1,yy1,cx,cy,src_dx,src_dy,dst_dx,dst_dy;
GUI_COLOR color;
IMAGE *img;
DC *pdc;
///////////
//算法优化思路:小数除法->整数除法->乘法->加法
if(hdc==0) return;
pdc =HDC2DC(hdc);
if(hImg==0) return;
img=(void*)hImg;
src_dx =img->Width;
src_dy =img->Height;
angle %=360;
//计算外接矩形坐标
radians =(2*PI*angle)/360.0;
cos_a =COS(radians)*65536.0;
sin_a =SIN(radians)*65536.0;
point1x =(-src_dy*sin_a)>>16;
point1y =(src_dy*cos_a)>>16;
point2x =(src_dx*cos_a-src_dy*sin_a)>>16;
point2y =(src_dy*cos_a+src_dx*sin_a)>>16;
point3x =(src_dx*cos_a)>>16;
point3y =(src_dx*sin_a)>>16;
minx =MIN(0,MIN(point1x,MIN(point2x,point3x)));
miny =MIN(0,MIN(point1y,MIN(point2y,point3y)));
maxx =MAX(point1x,MAX(point2x,point3x));
maxy =MAX(point1y,MAX(point2y,point3y));
if(angle>90&&angle<180)
{
dst_dx=(int)CEIL(-minx);
}
else
{
dst_dx=(int)CEIL(maxx-minx);
}
if(angle>180&&angle<270)
{
dst_dy=(int)CEIL(-miny);
}
else
{
dst_dy=(int)CEIL(maxy-miny);
}
cx =(dst_dx>>1); //目标位置中心点的x偏移
cy =(dst_dy>>1); //目标位置中心点的y偏移
cos_ay =(miny*cos_a)>>16;
sin_ay =(miny*sin_a)>>16;
////////////
if(((IMAGE*)hImg)->Bpp==32)
{
//ARGB 8888格式(带Alpha通道)
for(yy=0;yy<dst_dy;yy++)
{
cos_ay =((yy+miny)*cos_a)>>16;
sin_ay =((yy+miny)*sin_a)>>16;
////
yy0 =y+yy-cy;
if(yy0<0) continue;
if(yy0>pdc->ymax) return;
for(xx=0;xx<dst_dx;xx++)
{
////
xx1 =((((xx+minx)*cos_a)>>16)+sin_ay); //计算坐标
yy1 =(cos_ay-(((xx+minx)*sin_a)>>16));
////
xx0 =x+xx-cx;
if(xx1>=0&&xx1<src_dx&&yy1>=0&&yy1<src_dy&&xx0>0&&xx0<pdc->xmax)
{
color =img->Data[yy1*img->Width+xx1];
pdc->PutPixel(pdc,xx0,yy0,AlphaBlendColor(color,GetPixel(hdc,xx0,yy0),img->AlphaData[yy1*img->Width+xx1]));
}
}
}
}
else
{
//其它格式(不带Alpha通道)
for(yy=0;yy<dst_dy;yy++)
{
cos_ay =((yy+miny)*cos_a)>>16;
sin_ay =((yy+miny)*sin_a)>>16;
////
yy0 =y+yy-cy;
if(yy0<0) continue;
if(yy0>pdc->ymax) return;
for(xx=0;xx<dst_dx;xx++)
{
////
xx1 =((((xx+minx)*cos_a)>>16)+sin_ay); //计算坐标
yy1 =(cos_ay-(((xx+minx)*sin_a)>>16));
////
xx0 =x+xx-cx;
if(xx1>=0&&xx1<src_dx&&yy1>=0&&yy1<src_dy&&xx0>0&&xx0<pdc->xmax)
{
pdc->PutPixel(pdc,xx0,yy0,img->Data[yy1*img->Width+xx1]);
}
}
}
}
////
}
测试程序:
void TestRotateImage(void)
{
U32 hfile,himg,angle,frame,width,height;
char key,str_buf[64];
U8 *buf;
HDC hdc;
COORD x,y;
////
hdc=CreateDC(0,0,ScrWidth(),ScrHeight()-40); //创建设备上下文
angle=0;
while(1)
{
hfile=FILE_INVALID;
while(hfile==FILE_INVALID)
{
DbgUart_Printf("Enter Bmp File Name:\n");
if(DbgUart_Gets(str_buf,64)) //输入目标文件名
{
hfile=FileOpen(str_buf,"rw");
}
else
{
ReleaseDC(hdc);
return;
}
}
////
DbgUart_Printf("File Size =%d Byte\n",GetFileSize(hfile));
buf=MemAlloc(GetFileSize(hfile));
FileRead(buf,GetFileSize(hfile),hfile);
FileClose(hfile);
////
himg=BmpToImage(buf); //Bmp解码
MemFree(buf);
width =((IMAGE*)himg)->Width;
height =((IMAGE*)himg)->Height;
DbgUart_Printf("Image Width=%d,Height=%d\n",width,height);
ThreadLock(); //关线程调度(不关中断)
x=ScrWidth()>>1;
y=ScrHeight()>>1;
while(1)
{
int i;
char str_buf[32];
////
i =0;
angle =0;
frame =0;
SetSysTime(0); //设置系统时间
while(i<10)
{
RotateImage(hdc,x,y,himg,angle);
angle+=5; //角度每次增加5度
frame++; //帧计数
if(angle>=360)
{
angle=0;
i++;
}
////
key=0;
if(DbgUart_Getch(&key))
{
if(key==0x1b) goto ret;
}
}
////
i=GetSysTime();
StrPrintf(str_buf,"RotateImage 测试(%d*%d):Tick数=%d,时间=%d秒,帧数=%d,平均:%d帧/秒",width,height,i,i/TicksPerSec(),frame,(frame*TicksPerSec())/i);
Label(HDC_SCREEN,0,ScrHeight()-40,ScrWidth(),40,RGB(200,0,0),RGB(200,200,200),RGB(0,0,0),LEFT,str_buf);
}
}
ret:
ThreadUnlock(); //恢复线程调度
ReleaseImage(himg); //释放资源
ReleaseDC(hdc);
}