高效率 图像任意角度旋转算法(用整数运算实现)
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include "GUI.h"
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
HIMG CreateImage(int dx,int dy,int bpp)
{
IMAGE *img;
////
img=MemAlloc(dx*dy*sizeof(GUI_COLOR));
if(img==0) return 0;
img->Bpp =bpp;
img->Width =dx;
img->Height =dy;
img->Data =MemAlloc(dx*dy*sizeof(GUI_COLOR));
if(img->Data==0)
{
MemFree(img);
return 0;
}
img->AlphaData =MemAlloc(dx*dy);
if(img->AlphaData==0)
{
MemFree(img->Data);
MemFree(img);
return 0;
}
DbgUart_Printf("CreateImage =%08XH\n",img);
return (HIMG)img;
}
/*============================================================================*/
void SetImagePixel(U32 hImg,int x,int y,GUI_COLOR color,U8 alpha)
{
S32 i;
IMAGE *img;
////
img=(void*)hImg;
i=y*img->Width+x;
if(i<0) return;
img->Data[i] =color;
img->AlphaData[i] =alpha;
}
U32 GetImagePixel(U32 hImg,int x,int y)
{
S32 i;
IMAGE *img;
////
img=(void*)hImg;
i=y*img->Width+x;
if(i<0) return 0xff000000;
return (img->AlphaData[i]<<24)|img->Data[i];
}
/*============================================================================*/
void DrawImage(HDC hdc,int x,int y,HIMG hImg)
{
int i,c,a,xx,yy,dx,dy;
IMAGE *img;
////
if(hImg==0) return;
img =(void*)hImg;
dx =img->Width;
dy =img->Height;
if(img->Bpp==32)
{
i=0;
for(yy=0;yy
for(xx=0;xx
c=img->Data[i];
c=AlphaBlendColor(c,GetPixel(hdc,x+xx,y+yy),img->AlphaData[i]);
PutPixel(hdc,x+xx,y+yy,c);
i++;
}
}
}
else
{
PutImage(hdc,x,y,dx,dy,img->Data);
}
}
/*============================================================================*/
void ReleaseImage(HIMG hImg)
{
IMAGE *img;
////
if(hImg==0) return;
img=(void*)hImg;
MemFree(img->Data);
MemFree(img->AlphaData);
MemFree(img);
}
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*=======================================================
=====================*/
/*============================================================================*/
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
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
////
xx1 =((((xx+minx)*cos_a)>>16)+sin_ay); //计算坐标
yy1 =(cos_ay-(((xx+minx)*sin_a)>>16));
////
xx0 =x+xx-cx;
if(xx1>=0&&xx1
{
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
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
////
xx1 =((((xx+minx)*cos_a)>>16)+sin_ay); //计算坐标
yy1 =(cos_ay-(((xx+minx)*sin_a)>>16));
////
xx0 =x+xx-cx;
if(xx1>=0&&xx1
{
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(h
img); //释放资源
ReleaseDC(hdc);
}
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/