怎样把这个函数做成void Rotate(HBID hDib)…………在线等,问题解决就结!………有点棘手!

shuilongyin_00 2010-02-02 11:02:54

//MyDIPView.cpp文件中的相关代码……
#define PI 3.14159
//角度到弧度转化的宏
#define RADIAN(angle) ((angle)*PI/180.0)

/*************************************************************************
*
* 函数名称:
* 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;
}

还需要提供什么请提出来,以便我继续补充…… 帮助我解决问题者再开贴每人相送100分。
在线等…… 半小时关注一次
...全文
220 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
sjdev 2010-02-02
  • 打赏
  • 举报
回复
灰度处理无非就就是得到数据,然后对每个数据处理。

而旋转,是得到数据copy给lpNewDibBits,然后处理,你处理之后的lpNewDibBits再copy回去不就可以了吗?

这样有什么问题吗?
shuilongyin_00 2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 sjdev 的回复:]
参看灰度处理。

内容虽然不一样,部分代码原理是一样的。

你旋转之后的数据,和进行灰度处理后的数据,可看做一个东西。

然后,灰度处理数据给了一个新的hBitmap,你可以把它设置给源hDib.
[/Quote]
灰度处理的我有,但和这函数差别有点大!所以我就晕了……

/****************************************************************
* 函数名称:
* Convert256toGray()
*
* 参数:
* HDIB hDIB -图像的句柄
*
* 返回值:
* 无
*
* 功能:
* 将256色位图转化为灰度图
*
***************************************************************/

void Convert256toGray(HDIB hDIB)
{
LPSTR lpDIB;

// 由DIB句柄得到DIB指针并锁定DIB
lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDIB);

// 指向DIB象素数据区的指针
LPSTR lpDIBBits;

// 指向DIB象素的指针
BYTE * lpSrc;

// 图像宽度
LONG lWidth;
// 图像高度
LONG lHeight;

// 图像每行的字节数
LONG lLineBytes;

// 指向BITMAPINFO结构的指针(Win3.0)
LPBITMAPINFO lpbmi;

// 指向BITMAPCOREINFO结构的指针
LPBITMAPCOREINFO lpbmc;

// 获取指向BITMAPINFO结构的指针(Win3.0)
lpbmi = (LPBITMAPINFO)lpDIB;

// 获取指向BITMAPCOREINFO结构的指针
lpbmc = (LPBITMAPCOREINFO)lpDIB;

// 灰度映射表
BYTE bMap[256];

// 计算灰度映射表(保存各个颜色的灰度值),并更新DIB调色板
int i,j;
for (i = 0; i < 256; i ++)
{
// 计算该颜色对应的灰度值
bMap[i] = (BYTE)(0.299 * lpbmi->bmiColors[i].rgbRed +

0.587 * lpbmi->bmiColors[i].rgbGreen +

0.114 * lpbmi->bmiColors[i].rgbBlue + 0.5);
// 更新DIB调色板红色分量
lpbmi->bmiColors[i].rgbRed = i;

// 更新DIB调色板绿色分量
lpbmi->bmiColors[i].rgbGreen = i;

// 更新DIB调色板蓝色分量
lpbmi->bmiColors[i].rgbBlue = i;

// 更新DIB调色板保留位
lpbmi->bmiColors[i].rgbReserved = 0;

}
// 找到DIB图像象素起始位置
lpDIBBits = ::FindDIBBits(lpDIB);

// 获取图像宽度
lWidth = ::DIBWidth(lpDIB);

// 获取图像高度
lHeight = ::DIBHeight(lpDIB);

// 计算图像每行的字节数
lLineBytes = WIDTHBYTES(lWidth * 8);

// 更换每个象素的颜色索引(即按照灰度映射表换成灰度值)

//逐行扫描
for(i = 0; i < lHeight; i++)
{

//逐列扫描
for(j = 0; j < lWidth; j++)
{
// 指向DIB第i行,第j个象素的指针
lpSrc = (unsigned char*)lpDIBBits + lLineBytes * (lHeight - 1 - i) + j;

// 变换
*lpSrc = bMap[*lpSrc];
}
}

//解除锁定
::GlobalUnlock ((HGLOBAL)hDIB);
}
sjdev 2010-02-02
  • 打赏
  • 举报
回复
参看灰度处理

内容虽然不一样,部分代码原理是一样的。

你旋转之后的数据,和进行灰度处理后的数据,可看做一个东西。

然后,灰度处理数据给了一个新的hBitmap,你可以把它设置给源hDib.
shuilongyin_00 2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 sjdev 的回复:]
你的意思是直接在原dib上进行修改,并且不需要指定角度对吗?

得到新的dib后,SetDIBits,加到原dib上不就可以了吗?
[/Quote]
能给一个简单的代码参考下吗!谢谢……
现在有点病急乱投医的感觉!希望有参考代码,帮助理清思路!
shuilongyin_00 2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 fm810 的回复:]
原函数接口是HGLOBAL WINAPI RotateDIB(LPSTR lpDIB, int iRotateAngle),新函数接口是void Rotate(HBID hDib,那角度信息iRotateAngle难道不需要了吗?
[/Quote]
谢谢,做为第一个回答感谢100!,请在 [感谢贴]感谢fm810第一个回答问题……100 帖回复领取

我想的是把角度信息直接做到void Rotate(HBID hDib)中……
sjdev 2010-02-02
  • 打赏
  • 举报
回复
你的意思是直接在原dib上进行修改,并且不需要指定角度对吗?

得到新的dib后,SetDIBits,加到原dib上不就可以了吗?
shuilongyin_00 2010-02-02
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 sjdev 的回复:]
问题解决了吗?
[/Quote]
快了,接等着明天再开机看下!还不行的话就再来麻烦兄弟您了!
fm810 2010-02-02
  • 打赏
  • 举报
回复
原函数接口是HGLOBAL WINAPI RotateDIB(LPSTR lpDIB, int iRotateAngle),新函数接口是void Rotate(HBID hDib,那角度信息iRotateAngle难道不需要了吗?
sjdev 2010-02-02
  • 打赏
  • 举报
回复
问题解决了吗?
会飞的老鱼 2010-02-02
  • 打赏
  • 举报
回复
我原来也做过位图旋转这方面的尝试,但没坚持下去,只做了90度和180度的处理,而没有做任意角度的处理,现在看到shuilongyin_00(小破孩带枪拜访)兄的帖子,真是有幸! 收藏了,回去学习学习!
shuilongyin_00 2010-02-02
  • 打赏
  • 举报
回复
请sjdev到下面的帖子回复,方便送分! 已经移动到非技术区……
http://topic.csdn.net/u/20100202/11/6308e2df-df22-45f4-a8eb-c27713e109db.html?21619
fm810 2010-02-02
  • 打赏
  • 举报
回复
楼主,不知道这样可以否?

//MyDIPView.cpp文件中的相关代码……
#define PI 3.14159
//角度到弧度转化的宏
#define RADIAN(angle) ((angle)*PI/180.0)

/*************************************************************************
*
* 函数名称:
* RotateDIB()
*
* 参数:
* LPSTR lpDIB - 指向源DIB的指针
* int iRotateAngle - 旋转的角度(0-360度)
*
* 返回值:
* HGLOBAL - 旋转成功返回新DIB句柄,否则返回NULL。
*
* 说明:
* 该函数用来以图像中心为中心旋转DIB图像,返回新生成DIB的句柄。
* 调用该函数会自动扩大图像以显示所有的象素。函数中采用最邻近插
* 值算法进行插值。
*
************************************************************************/

// HGLOBAL WINAPI RotateDIB(LPSTR lpDIB, int iRotateAngle)
void Rotate(HDIB hDib)
{
// !!!从原hDib得到lpDIB
LPSTR lpDIB = (LPSTR) ::GlobalLock((HGLOBAL)hDib);

// !!!指定角度
int iRotateAngle = 30;

// 源图像的宽度和高度
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;
}

}

}

// !!!返回新的句柄
hDib = hDIB;

// 返回
// return hDIB;
}

19,468

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 图形处理/算法
社区管理员
  • 图形处理/算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧