Chinaunix首页 | 论坛 | 博客
  • 博客访问: 292661
  • 博文数量: 109
  • 博客积分: 2116
  • 博客等级: 大尉
  • 技术积分: 1062
  • 用 户 组: 普通用户
  • 注册时间: 2009-10-22 15:38
文章分类

全部博文(109)

文章存档

2013年(2)

2011年(16)

2010年(90)

2009年(1)

我的朋友

分类:

2010-08-14 09:08:54

/*************************************************************************
 *
 * 函数名称:
 *   RotateDIB()
 *
 * 参数:
 *   LPSTR lpDIB  - 指向源DIB的指针
 *   int iRotateAngle - 旋转的角度(0-360度)
 *
 * 返回值:
 *   HGLOBAL            - 旋转成功返回新DIB句柄,否则返回NULL。
 *
 * 说明:
 *   该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
 * 调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插
 * 值算法进行插值。
 *
 ************************************************************************/
HGLOBAL WINAPI RotateDIB(LPSTR lpDIB, int iRotateAngle)
{
 
 // 源图像的宽度和高度
 LONG lWidth;
 LONG lHeight;
 
 // 旋转后图像的宽度和高度
 LONG lNewWidth;
 LONG lNewHeight;
 
 // 图像每行的字节数
 LONG lLineBytes;
 
 // 旋转后图像的宽度(lNewWidth',必须是4的倍数)
 LONG lNewLineBytes;
 
 // 指向源图像的指针
 LPSTR lpDIBBits;
 
 // 指向源象素的指针
 LPSTR lpSrc;
 
 // 旋转后新DIB句柄
 HDIB hDIB;
 
 // 指向旋转图像对应象素的指针
 LPSTR lpDst;
 
 // 指向旋转图像的指针
 LPSTR lpNewDIB;
 LPSTR lpNewDIBBits;
 
 // 指向BITMAPINFO结构的指针(Win3.0)
 LPBITMAPINFOHEADER lpbmi;
 
 // 指向BITMAPCOREINFO结构的指针
 LPBITMAPCOREHEADER lpbmc;
 
 // 循环变量(象素在新DIB中的坐标)
 LONG i;
 LONG j;
 
 // 象素在源DIB中的坐标
 LONG i0;
 LONG j0;
 
 // 旋转角度(弧度)
 float fRotateAngle;
 
 // 旋转角度的正弦和余弦
 float fSina, fCosa;
 
 // 源图四个角的坐标(以图像中心为坐标系原点)
 float fSrcX1,fSrcY1,fSrcX2,fSrcY2,fSrcX3,fSrcY3,fSrcX4,fSrcY4;
 
 // 旋转后四个角的坐标(以图像中心为坐标系原点)
 float fDstX1,fDstY1,fDstX2,fDstY2,fDstX3,fDstY3,fDstX4,fDstY4;
 
 // 两个中间常量
 float f1,f2;
 
 // 找到源DIB图像象素起始位置
 lpDIBBits = ::FindDIBBits(lpDIB);
 
 // 获取图像的"宽度"(4的倍数)
 lWidth = ::DIBWidth(lpDIB);
 
 // 计算图像每行的字节数
 lLineBytes = WIDTHBYTES(lWidth * 8);
 
 // 获取图像的高度
 lHeight = ::DIBHeight(lpDIB);
 
 // 将旋转角度从度转换到弧度
 fRotateAngle = (float) RADIAN(iRotateAngle);
 
 // 计算旋转角度的正弦
 fSina = (float) sin((double)fRotateAngle);
 
 // 计算旋转角度的余弦
 fCosa = (float) cos((double)fRotateAngle);
 
 // 计算原图的四个角的坐标(以图像中心为坐标系原点)
 fSrcX1 = (float) (- (lWidth  - 1) / 2);
 fSrcY1 = (float) (  (lHeight - 1) / 2);
 fSrcX2 = (float) (  (lWidth  - 1) / 2);
 fSrcY2 = (float) (  (lHeight - 1) / 2);
 fSrcX3 = (float) (- (lWidth  - 1) / 2);
 fSrcY3 = (float) (- (lHeight - 1) / 2);
 fSrcX4 = (float) (  (lWidth  - 1) / 2);
 fSrcY4 = (float) (- (lHeight - 1) / 2);
 
 // 计算新图四个角的坐标(以图像中心为坐标系原点)
 fDstX1 =  fCosa * fSrcX1 + fSina * fSrcY1;
 fDstY1 = -fSina * fSrcX1 + fCosa * fSrcY1;
 fDstX2 =  fCosa * fSrcX2 + fSina * fSrcY2;
 fDstY2 = -fSina * fSrcX2 + fCosa * fSrcY2;
 fDstX3 =  fCosa * fSrcX3 + fSina * fSrcY3;
 fDstY3 = -fSina * fSrcX3 + fCosa * fSrcY3;
 fDstX4 =  fCosa * fSrcX4 + fSina * fSrcY4;
 fDstY4 = -fSina * fSrcX4 + fCosa * fSrcY4;
 
 // 计算旋转后的图像实际宽度
 lNewWidth  = (LONG) ( max( fabs(fDstX4 - fDstX1), fabs(fDstX3 - fDstX2) ) + 0.5);
 
 // 计算新图像每行的字节数
 lNewLineBytes = WIDTHBYTES(lNewWidth * 8);
 
 // 计算旋转后的图像高度
 lNewHeight = (LONG) ( max( fabs(fDstY4 - fDstY1), fabs(fDstY3 - fDstY2) )  + 0.5);
 
 // 两个常数,这样不用以后每次都计算了
 f1 = (float) (-0.5 * (lNewWidth - 1) * fCosa - 0.5 * (lNewHeight - 1) * fSina
  + 0.5 * (lWidth  - 1));
 f2 = (float) ( 0.5 * (lNewWidth - 1) * fSina - 0.5 * (lNewHeight - 1) * fCosa
  + 0.5 * (lHeight - 1));
 
 // 分配内存,以保存新DIB
 hDIB = (HDIB) ::GlobalAlloc(GHND, lNewLineBytes * lNewHeight + *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
 
 // 判断是否内存分配失败
 if (hDIB == NULL)
 {
  // 分配内存失败
  return NULL;
 }
 // 锁定内存
 lpNewDIB =  (char * )::GlobalLock((HGLOBAL) hDIB);
 
 // 复制DIB信息头和调色板
 memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + ::PaletteSize(lpDIB));
 
 // 找到新DIB象素起始位置
 lpNewDIBBits = ::FindDIBBits(lpNewDIB);
 
 // 获取指针
 lpbmi = (LPBITMAPINFOHEADER)lpNewDIB;
 lpbmc = (LPBITMAPCOREHEADER)lpNewDIB;
 // 更新DIB中图像的高度和宽度
 if (IS_WIN30_DIB(lpNewDIB))
 {
  // 对于Windows 3.0 DIB
  lpbmi->biWidth = lNewWidth;
  lpbmi->biHeight = lNewHeight;
 }
 else
 {
  // 对于其它格式的DIB
  lpbmc->bcWidth = (unsigned short) lNewWidth;
  lpbmc->bcHeight = (unsigned short) lNewHeight;
 }
 
 // 针对图像每行进行操作
 for(i = 0; i < lNewHeight; i++)
 {
  // 针对图像每列进行操作
  for(j = 0; j < lNewWidth; j++)
  {
   // 指向新DIB第i行,第j个象素的指针
   // 注意此处宽度和高度是新DIB的宽度和高度
   lpDst = (char *)lpNewDIBBits + lNewLineBytes * (lNewHeight - 1 - i) + j;
   
   // 计算该象素在源DIB中的坐标
   i0 = (LONG) (-((float) j) * fSina + ((float) i) * fCosa + f2 + 0.5);
   j0 = (LONG) ( ((float) j) * fCosa + ((float) i) * fSina + f1 + 0.5);
   
   // 判断是否在源图范围内
   if( (j0 >= 0) && (j0 < lWidth) && (i0 >= 0) && (i0 < lHeight))
   {
    // 指向源DIB第i0行,第j0个象素的指针
    lpSrc = (char *)lpDIBBits + lLineBytes * (lHeight - 1 - i0) + j0;
    
    // 复制象素
    *lpDst = *lpSrc;
   }
   else
   {
    // 对于源图中没有的象素,直接赋值为255
    * ((unsigned char*)lpDst) = 255;
   }
   
  }
  
 }
 
 // 返回
 return hDIB;
}
 
void CMyDIPView::OnMenuitem32778()
{
 // 图像旋转
 // 获取文档
 CMyDIPDoc* pDoc = GetDocument();
 
 // 指向DIB的指针
 LPSTR lpDIB;
 
 // 锁定DIB
 lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
 
 // 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的旋转,其它的可以类推)
 if (::DIBNumColors(lpDIB) != 256)
 {
  // 提示用户
  MessageBox("目前只支持256色位图的旋转!", "系统提示" , MB_ICONINFORMATION | MB_OK);
  // 解除锁定
  ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
  
  // 返回
  return;
 }
 
 // 旋转角度
 int iRotateAngle;
 
 iRotateAngle=15;
 
 // 创建新DIB
 HDIB hNewDIB = NULL;
 
 // 更改光标形状
 BeginWaitCursor();
 
 // 调用RotateDIB()函数旋转DIB
 hNewDIB = (HDIB) RotateDIB(lpDIB, iRotateAngle);
 
 // 判断旋转是否成功
 if (hNewDIB != NULL)
 {
  
  // 替换DIB,同时释放旧DIB对象
  pDoc->ReplaceHDIB(hNewDIB);
  // 更新DIB大小和调色板
  pDoc->InitDIBData();
  
  // 设置脏标记
  pDoc->SetModifiedFlag(TRUE);
  
  // 重新设置滚动视图大小
  SetScrollSizes(MM_TEXT, pDoc->GetDocSize());
  
  // 更新视图
  pDoc->UpdateAllViews(NULL);
 }
 else
 {
  // 提示用户
  MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
 }
 
 // 解除锁定
 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
 // 恢复光标
 EndWaitCursor();
}

void CMyDIPView::OnMenuitem32779()
{
 // 图像旋转
 // 获取文档
 CMyDIPDoc* pDoc = GetDocument();
 
 // 指向DIB的指针
 LPSTR lpDIB;
 
 // 锁定DIB
 lpDIB = (LPSTR) ::GlobalLock((HGLOBAL) pDoc->GetHDIB());
 
 // 判断是否是8-bpp位图(这里为了方便,只处理8-bpp位图的旋转,其它的可以类推)
 if (::DIBNumColors(lpDIB) != 256)
 {
  // 提示用户
  MessageBox("目前只支持256色位图的旋转!", "系统提示" , MB_ICONINFORMATION | MB_OK);
  // 解除锁定
  ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
  
  // 返回
  return;
 }
 
 // 旋转角度
 int iRotateAngle;
 
 iRotateAngle=-15;
 
 // 创建新DIB
 HDIB hNewDIB = NULL;
 
 // 更改光标形状
 BeginWaitCursor();
 
 // 调用RotateDIB()函数旋转DIB
 hNewDIB = (HDIB) RotateDIB(lpDIB, iRotateAngle);
 
 // 判断旋转是否成功
 if (hNewDIB != NULL)
 {
  
  // 替换DIB,同时释放旧DIB对象
  pDoc->ReplaceHDIB(hNewDIB);
  // 更新DIB大小和调色板
  pDoc->InitDIBData();
  
  // 设置脏标记
  pDoc->SetModifiedFlag(TRUE);
  
  // 重新设置滚动视图大小
  SetScrollSizes(MM_TEXT, pDoc->GetDocSize());
  
  // 更新视图
  pDoc->UpdateAllViews(NULL);
 }
 else
 {
  // 提示用户
  MessageBox("分配内存失败!", "系统提示" , MB_ICONINFORMATION | MB_OK);
 }
 
 // 解除锁定
 ::GlobalUnlock((HGLOBAL) pDoc->GetHDIB());
 // 恢复光标
 EndWaitCursor();
}
阅读(748) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~