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

原创 2004年02月26日 10:03:00

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

   第一步,你必须知道位图即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,);

     到这里就大功告成了.

图像旋转任意角度

void Roade(Mat &src, double angle)//angle 角度值,当其为正值时进行逆时针旋转;当其为负值时,顺时针旋转 { Mat dst;//输出图像 int len...
  • u010417185
  • u010417185
  • 2016年11月13日 10:27
  • 540

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

网上有很多关于位图旋转的资料,但是讲得很清楚的不多(我没有仔细查找).于是我也写了一个,希望能给向我这样的初学者一点帮助.第一步,你必须知道位图即BMP格式的文件的结构.位图(bmp)文件由以下几个部...
  • ShowLong
  • ShowLong
  • 2006年05月22日 11:47
  • 1394

用GDI+加载图片,旋转CDC

http://download.csdn.net/download/chicaidecaiji/10179048
  • chicaidecaiji
  • chicaidecaiji
  • 2017年12月29日 00:46
  • 75

DIB(设备无关位图)旋转任意角度算法(单色位图)

网上很多位图旋转的程序,但是一般都是8位、24位、32位位图的旋转,这些大于8位的位图每个像素都可以用整个字节表示,所以用char数组很容易实现对应像素复制。但是要对单色位图进行旋转的话,就涉及到按位...
  • wangwenjing90
  • wangwenjing90
  • 2013年04月18日 10:09
  • 2355

MFC下图形任意角度旋转.

图形的旋转公式: x1   =   (x - xcenter) *  cosθ - (y - ycenter)  * sinθ + xcenter;  y1   =   (x - xcenter)...
  • ityezi_admin
  • ityezi_admin
  • 2014年07月04日 18:04
  • 1003

c++实现图像旋转任意角度

图形图像处理-之-任意角度的高质量的快速的图像旋转 上篇 纯软件的任意角度的快速旋转                                 HouSisong@GMail.com   20...
  • wonengguwozai
  • wonengguwozai
  • 2016年07月27日 20:21
  • 5799

使用GDI+ 绘制可旋转的PNG

如果要绘制半透明的图片,请使用.png格式(用photoshop即可轻松制作并处理)一、首先介绍Graphics的两个函数,RotateTransform:将整个坐标系逆时针旋转一定角度Transla...
  • yann2
  • yann2
  • 2010年10月18日 10:45
  • 1756

altium designer 让元件旋转任意角度

打开Altium Designer(AD)软件并打开一个PCB工程,为了更加清晰的演示已经把多于的层隐藏了,同时也增加了一些辅助线。 选择要旋转的整个...
  • kebu12345678
  • kebu12345678
  • 2017年10月27日 10:00
  • 443

opencv实现图像任意角度旋转的算法解析及代码实现

实现图片的旋转
  • Vivid_Song
  • Vivid_Song
  • 2015年11月20日 15:00
  • 1719

如何让PCB中的元器件以任意角度旋转?

在使用Altium Designer等绘图工具绘制电路图时,有时候需要把元件按不特定的角度放置(不是90度的倍数),有时需要旋转45度,有时需要旋转10度,那如何实现呢?   在Altium菜单栏中,...
  • ldcung
  • ldcung
  • 2014年02月19日 22:21
  • 4995
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:如何在vc++中旋转位图---任意角度
举报原因:
原因补充:

(最多只允许输入30个字)