分享
 
 
 

如何在vc++中旋转位图---任意角度

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

网上有很多关于位图旋转的资料,但是讲得很清楚的不多(我没有仔细查找).于是我也写了一个,希望能给向我这样的初学者一点帮助.

第一步,你必须知道位图即BMP格式的文件的结构.

位图(bmp)文件由以下几个部分组成:

1.BITMAPFILEHEADER,它的定义如下:

typedef struct tagBITMAPFILEHEADER {

WORD bfType; //必须为'BM'

DWORD bfSize; //文件大小

WORD bfReserved1; //必须为0

WORD bfReserved2; //必须为0

DWORD bfOffBits; //从ITMAPFILEHEADER到存放bmp数据的偏移量

} BITMAPFILEHEADER, *PBITMAPFILEHEADER;

2.BITMAPINFOHEADER,它的定义如下:

typedef struct tagBITMAPINFOHEADER{

DWORD biSize; //此结构的大小,可用sizeof(BITMAPINFOHEAER)得到

LONG biWidth; //位图宽度,以象素为单位

LONG biHeight; //位图高度,以象素为单位

WORD biPlanes; //必须为1

WORD biBitCount;//位图象素位数,可为0,1,4,8,24,32

DWORD biCompression;

DWORD biSizeImage; //(仅用于压缩)

LONG biXPelsPerMeter; //一米横向象素数

LONG biYPelsPerMeter; //一米纵向象素数

DWORD biClrUsed;// (非零用语短颜色表)

DWORD biClrImportant;

} BITMAPINFOHEADER, *PBITMAPINFOHEADER;

由于以上信息可以直接从MSDN上查到,所以只做简单介绍,你可以自己查看NSDN帮助,上面有很详细的介绍.

3.DIB位图像.这里放的是真正的位图数据.

知道了位图的存放格式,下面我们就可以很容易的把它读如内存.

第二步,读入bmp图像

LPCTSTR lpszFileName4="untitled.bmp"; //文件路径

CFile file; //用于读取BMP文件

BITMAPFILEHEADER bfhHeader;//bmp文件头

BITMAPINFOHEADER bmiHeader; //bmp格式头

LPBITMAPINFO lpBitmapInfo; //bmp格式具体信息

int bmpWidth=0; //图片宽度

int bmpHeight = 0; //图片高度

if(!file.Open(lpszFileName,CFile::modeRead))

return ; //打开文件

file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));//读取文件头

if(bfhHeader.bfType!=((WORD) ('M'<<8)|'B')) //判断是否是"BM"

return ;

if(bfhHeader.bfSize!=file.GetLength())

return ;

if (file.Read((LPSTR)&bmiHeader, sizeof(bmiHeader)) != sizeof(bmiHeader))

return ;

bmpHeight = bmiHeader.biHeight;//得到高度和宽度

bmpWidth = bmiHeader.biWidth;

file.SeekToBegin();

file.Read(&bfhHeader,sizeof(BITMAPFILEHEADER));

UINT uBmpInfoLen=(UINT) bfhHeader.bfOffBits-sizeof(BITMAPFILEHEADER);

lpBitmapInfo=(LPBITMAPINFO) new BYTE[uBmpInfoLen];

file.Read((LPVOID) lpBitmapInfo,uBmpInfoLen);

if((* (LPDWORD)(lpBitmapInfo))!=sizeof(BITMAPINFOHEADER))

return ;

DWORD dwBitlen=bfhHeader.bfSize - bfhHeader.bfOffBits;

LPVOID lpSrcBits=new BYTE[dwBitlen]; //将数据读入lpSrcBits数组

file.ReadHuge(lpSrcBits,dwBitlen);

file.Close(); //关闭文件

下面我们将图片显示在屏幕上:

第三步,显示图片

CClientDC hDC(this);

StretchDIBits(hDC,0,0,bmpWidth,bmpHeight,0,0,bmpWidth,bmpHeight,

lpSrcBits,lpBitmapInfo,DIB_RGB_COLORS,SRCCOPY);

第四步,将图片读入内存设备环境

HDC dcSrc;

HBITMAP bitmap;

dcSrc=CreateCompatibleDC(hDC);//得到一个内存设备环境

bitmap = CreateCompatibleBitmap(hDC,bmpWidth,bmpHeight);

SelectObject(dcSrc,bitmap);

BitBlt(dcSrc,0,0,bmpWidth,bmpHeight,hDC,0,0,SRCCOPY);//这一步很重要

第五步,实现位图旋转

我们假设旋转位图的函数原形如下:

void RotateBitmap(HDC dcSrc,int SrcWidth,int SrcHeight,double angle,HDC pDC);

/*参数解释如下://///////////////////////////////////////////////////////////////////////////

HDC dcSrc:要旋转的位图的内存设备环境,就是第四步创建的

int SrcWidth:要旋转位图的宽度

int SrcHeight:要旋转位图的高度

double angle:所要旋转的角度,以弧度为单位

HDC pDC:第三步得到的当前屏幕设备环境

*///////////////////////////////////////////////////////////////////////////////////////////////////////

//以下是函数实现细节

void RotateAnyAngle(HDC dcSrc,int SrcWidth,int SrcHeight,double angle)

{

double x1,x2,x3;

double y1,y2,y3;

double maxWidth,maxHeight,minWidth,minHeight;

double srcX,srcY;

double sinA,cosA;

double DstWidth;

double DstHeight;

HDC dcDst;//旋转后的内存设备环境

HBITMAP newBitmap;

sinA = sin(angle);

cosA = cos(angle);

x1 = -SrcHeight * sinA;

y1 = SrcHeight * cosA;

x2 = SrcWidth * cosA - SrcHeight * sinA;

y2 = SrcHeight * cosA + SrcWidth * sinA;

x3 = SrcWidth * cosA;

y3 = SrcWidth * sinA;

minWidth = x3>(x1>x2?x2:x1)?(x1>x2?x2:x1):x3;

minWidth = minWidth>0?0:minWidth;

minHeight = y3>(y1>y2?y2:y1)?(y1>y2?y2:y1):y3;

minHeight = minHeight>0?0:minHeight;

maxWidth = x3>(x1>x2?x1:x2)?x3:(x1>x2?x1:x2);

maxWidth = maxWidth>0?maxWidth:0;

maxHeight = y3>(y1>y2?y1:y2)?y3:(y1>y2?y1:y2);

maxHeight = maxHeight>0?maxHeight:0;

DstWidth = maxWidth - minWidth;

DstHeight = maxHeight - minHeight;

dcDst = CreateCompatibleDC(dcSrc);

newBitmap = CreateCompatibleBitmap(dcSrc,(int)DstWidth,(int)DstHeight);

SelectObject(dcDst,newBitmap);

for( int I = 0 ;I<DstHeight;I++)

{

for(int J = 0 ;J< DstWidth;J++)

{

srcX = (J + minWidth) * cosA + (I + minHeight) * sinA;

srcY = (I + minHeight) * cosA - (J + minWidth) * sinA;

if( (srcX >= 0) && (srcX <= SrcWidth) &&(srcY >= 0) && (srcY <= SrcHeight))

{

BitBlt(dcDst, J, I, 1, 1, dcSrc,(int)srcX, (int)srcY, SRCCOPY);

}

}

}

//显示旋转后的位图

BitBlt(hDC,200,200,(int)DstWidth,(int)DstHeight,dcDst,0,0,SRCCOPY);

DeleteObject(newBitmap);

DeleteDC(dcDst);

}

最后我们调用就可以了:

double angle = (45/180.0)*3.14159;//旋转45Degree,可为任意角度

RotateAnyAngle(dcSrc,bmpWidth,bmpHeight,angle,);

到这里就大功告成了.

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有