高效率 图像任意角度旋转算法(用整数运算实现)

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 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=0&&yy10&&xx0xmax)
{

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=0&&yy10&&xx0xmax)
{

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);

}

/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/
/*============================================================================*/

/*============================================================================*/

相关文档
最新文档