📄 imagegeometry.cpp
字号:
}
if(nHeight > (nScanHeight - y))
{
::AfxMessageBox("The height of the area you defined is not obtained!");
return FALSE;
}
m_dwOperation = IMAGE_GEOMETRY_ROTATE_CCW_90;
//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//指定区域第一行最后一列开始地址.
BYTE* pbySrcBase = lpbyBitsSrc32 + y * dwWidthBytes + 4 * (x + nWidth - 1);
//目的地地址
BYTE* pbyDst = lpbyBitsDst32;
for(int i = 0;i < nWidth;i++)
{
//从上向下按列获取数据
//逐渐向左移动
BYTE* pbySrc = pbySrcBase;
for(int j = 0;j < nHeight;j++)
{
BYTE* pbyCurrent = pbySrc;
*pbyDst++ = *pbyCurrent++;
*pbyDst++ = *pbyCurrent++;
*pbyDst++ = *pbyCurrent++;
pbyDst++;
pbySrc += dwWidthBytes;
}
pbySrcBase -= 4;
}
return TRUE;
}
BOOL CImageGeometry::Rotate180(LPBYTE lpbyBitsSrc32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight, LPBYTE lpbyBitsDst32)
{
//第一步, 进行参数合法性检测
ASSERT(lpbyBitsSrc32);
ASSERT(lpbyBitsDst32);
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
//请注意, 这时, 宽度和高度不得随意超过有效宽度和高度.
if(nWidth > (nScanWidth - x))
{
::AfxMessageBox("The width of the area you defined is not obtained!");
return FALSE;
}
if(nHeight > (nScanHeight - y))
{
::AfxMessageBox("The height of the area you defined is not obtained!");
return FALSE;
}
//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
m_dwOperation = IMAGE_GEOMETRY_ROTATE_180;
//指定区域最后一行最后一列开始地址.
BYTE* pbySrcBase = lpbyBitsSrc32 + (y + nHeight - 1) * dwWidthBytes + 4 * (x + nWidth - 1);
//目的地地址
BYTE* pbyDst = lpbyBitsDst32;
for(int i = 0;i < nHeight;i++)
{
//
//逐渐向左移动
BYTE* pbySrc = pbySrcBase;
for(int j = 0;j < nWidth;j++)
{
*pbyDst++ = *pbySrc++;
*pbyDst++ = *pbySrc++;
*pbyDst++ = *pbySrc++;
pbyDst++;
pbySrc -= 7;
/*
//下列代码是等价的.
BYTE* pbyCurrent = pbySrc;
*pbyDst++ = *pbyCurrent++;
*pbyDst++ = *pbyCurrent++;
*pbyDst++ = *pbyCurrent++;
pbyDst++;
pbySrc -= 4;
*/
}
pbySrcBase -= dwWidthBytes;
}
return TRUE;
}
//旋转..., -360, 0, 360, ...度
BOOL CImageGeometry::Rotate0(LPBYTE lpbyBitsSrc32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight, LPBYTE lpbyBitsDst32)
{
//第一步, 进行参数合法性检测
ASSERT(lpbyBitsSrc32);
ASSERT(lpbyBitsDst32);
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
//请注意, 这时, 宽度和高度不得随意超过有效宽度和高度.
if(nWidth > (nScanWidth - x))
{
::AfxMessageBox("The width of the area you defined is not obtained!");
return FALSE;
}
if(nHeight > (nScanHeight - y))
{
::AfxMessageBox("The height of the area you defined is not obtained!");
return FALSE;
}
m_dwOperation = IMAGE_GEOMETRY_ROTATE_0;
//行字节数(源图像)
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//行字节数(目标子图像)
DWORD dwWidtgBytesDst = (DWORD)nWidth * 4;
//指定区域第一行第一列开始地址.
BYTE* pbySrcBase = lpbyBitsSrc32 + y * dwWidthBytes + 4 * x;
//目的地地址
BYTE* pbyDst = lpbyBitsDst32;
for(int i = 0; i < nHeight; i++)
{
::CopyMemory(pbyDst, pbySrcBase, dwWidtgBytesDst);
pbySrcBase += dwWidthBytes;
pbyDst += dwWidtgBytesDst;
}
return TRUE;
}
//lpbyBitsSrc32----传递源像素值,
//x, y, nWidth, nHeight, 定义区域的宽度
//nScanWidth, nScanHeight, 扫描宽度和扫描高度
//lpbyBitsDst32----存放最后缩放后的结果
//fTheta ---- 旋转角度
//nWidthImgDst, nHeightDst旋转后的尺寸, 事实上它们可以通过nWidth, nHeight和fTheta计算出来.
BOOL CImageGeometry::Rotate(LPBYTE lpbyBitsSrc32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight, LPBYTE lpbyBitsDst32, float fTheta, int nWidthImgDst, int nHeightImgDst)
{
//第一步, 进行参数合法性检测
ASSERT(lpbyBitsSrc32);
ASSERT(lpbyBitsDst32);
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
//请注意, 这时, 宽度和高度不得随意超过有效宽度和高度.
if(nWidth > (nScanWidth - x))
{
::AfxMessageBox("The width of the area you defined is not obtained!");
return FALSE;
}
if(nHeight > (nScanHeight - y))
{
::AfxMessageBox("The height of the area you defined is not obtained!");
return FALSE;
}
m_dwOperation = IMAGE_GEOMETRY_ROTATE;
//将角度转化成弧度
float fRadTheta = (float)(fTheta * PIE / 180.0);
//计算其三角函数值
float fSinTheta = (float)sin(fRadTheta);
float fCosTheta = (float)cos(fRadTheta);
///////////////////////////////////////////////////////
//首先考查是否是旋转特殊的角度.
///////////////////////////////////////////////////////
if((nWidthImgDst == nHeight) && (nHeightImgDst == nWidth))
{
// ..., -270, 90, 450, ...,
if(fSinTheta > 0.99f)
return RotateCCW90(lpbyBitsSrc32, x, y, nWidth, nHeight, nScanWidth, nScanHeight, lpbyBitsDst32);
// ..., -450, -90, 270, ...,
else if(fSinTheta < -0.99f)
return RotateCW90(lpbyBitsSrc32, x, y, nWidth, nHeight, nScanWidth, nScanHeight, lpbyBitsDst32);
}
if((nWidthImgDst == nWidth) && (nHeightImgDst == nHeight))
{
// ..., -540, -180, 180, 540, ...,
if(fCosTheta < -0.99f)
return Rotate180(lpbyBitsSrc32, x, y, nWidth, nHeight, nScanWidth, nScanHeight, lpbyBitsDst32);
// ..., -360, 0, 360,
else if (fCosTheta > 0.99f)
return Rotate0(lpbyBitsSrc32, x, y, nWidth, nHeight, nScanWidth, nScanHeight, lpbyBitsDst32);
}
//////////////////////////////////////////////////
//处理非特殊角度
//////////////////////////////////////////////////
//绝对旋转中心, 相对于原图像坐标系统.
int nAbsCenterX = x + nWidth / 2;
int nAbsCenterY = y + nHeight / 2;
//相对旋转中心, 它们具有相同的x, y坐标.相对于目标图像
int nRelCenterX = nWidthImgDst / 2;
int nRelCenterY = nHeightImgDst / 2;
//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//目的地地址
BYTE* pbyDst = lpbyBitsDst32;
//开始计算
//按行进行扫描计算
for(int i = 0;i < nHeightImgDst;i++)//y
{
//右手直角坐标系下, 坐标值为 i 的纵坐标表示
int yy = nRelCenterY - i;
for(int j = 0; j < nWidthImgDst;j++)//x
{
//右手直角坐标系下, 坐标值为 j 的横坐标表示
int xx = j - nRelCenterX;
//进行反向变换, 旋转角度: -theta
float fXInverse = xx * fCosTheta + yy * fSinTheta;
float fYInverse = yy * fCosTheta - xx * fSinTheta;
//变成左手坐标系
fYInverse = -fYInverse;
fXInverse += nAbsCenterX;
fYInverse += nAbsCenterY;
//近邻坐标值
//
int nNearX = (int)fXInverse;
int nNearY = (int)fYInverse;
if((nNearX >= x) && (nNearX <= (x + nWidth - 1)) &&
(nNearY >= y) && (nNearY <= (y + nHeight - 1)))
{
//插值参数
float fu = fXInverse - nNearX;
float fv = fYInverse - nNearY;
//近邻点的地址
BYTE* pbySrc = lpbyBitsSrc32 + nNearY * dwWidthBytes + 4 * nNearX;
PIXELCOLORRGB rgb = Interpolate(pbySrc, nNearX, nNearY, fu, fv, nScanWidth, nScanHeight);
*pbyDst++ = rgb.blue;
*pbyDst++ = rgb.green;
*pbyDst++ = rgb.red;
pbyDst++;
}
else
pbyDst += 4;
}
}
return TRUE;
}
//水平镜象,但是镜象轴为 Y 轴
BOOL CImageGeometry::MirrorY(LPBYTE lpbyBitsSrc32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight, LPBYTE lpbyBitsDst32)
{
//第一步, 进行参数合法性检测
ASSERT(lpbyBitsSrc32);
ASSERT(lpbyBitsDst32);
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
//请注意, 这时, 宽度和高度不得随意超过有效宽度和高度.
if(nWidth > (nScanWidth - x))
{
::AfxMessageBox("The width of the area you defined is not obtained!");
return FALSE;
}
if(nHeight > (nScanHeight - y))
{
::AfxMessageBox("The height of the area you defined is not obtained!");
return FALSE;
}
m_dwOperation = IMAGE_GEOMETRY_MIRROR_Y;
//行字节数
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//指定区域最后一行最后一列开始地址.
BYTE* pbySrcBase = lpbyBitsSrc32 + y * dwWidthBytes + 4 * (x + nWidth - 1);
//目的地地址
BYTE* pbyDst = lpbyBitsDst32;
for(int i = 0;i < nHeight;i++)
{
//从上向下按列获取数据
//逐渐向左移动
BYTE* pbySrc = pbySrcBase;
for(int j = 0;j < nWidth;j++)
{
*pbyDst++ = *pbySrc++;
*pbyDst++ = *pbySrc++;
*pbyDst++ = *pbySrc++;
pbyDst++;
pbySrc -= 7;
}
pbySrcBase += dwWidthBytes;
}
return TRUE;
}
//垂直镜象,但是镜象轴为 X 轴
BOOL CImageGeometry::MirrorX(LPBYTE lpbyBitsSrc32, int x, int y, int nWidth, int nHeight, int nScanWidth, int nScanHeight, LPBYTE lpbyBitsDst32)
{
//第一步, 进行参数合法性检测
ASSERT(lpbyBitsSrc32);
ASSERT(lpbyBitsDst32);
if((x > (nScanWidth - 1)) || (y > (nScanHeight - 1))) return FALSE;
//有效区域的宽度和高度
//请注意, 这时, 宽度和高度不得随意超过有效宽度和高度.
if(nWidth > (nScanWidth - x))
{
::AfxMessageBox("The width of the area you defined is not obtained!");
return FALSE;
}
if(nHeight > (nScanHeight - y))
{
::AfxMessageBox("The height of the area you defined is not obtained!");
return FALSE;
}
m_dwOperation = IMAGE_GEOMETRY_MIRROR_X;
//行字节数(源图像)
DWORD dwWidthBytes = (DWORD)nScanWidth * 4;
//行字节数(目标子图像)
DWORD dwWidtgBytesDst = (DWORD)nWidth * 4;
//指定区域最后一行第一列开始地址.
BYTE* pbySrcBase = lpbyBitsSrc32 + (y + nHeight - 1) * dwWidthBytes + 4 * x;
//目的地地址
BYTE* pbyDst = lpbyBitsDst32;
for(int i = 0;i < nHeight;i++)
{
//从下向向按行获取数据
::CopyMemory(pbyDst, pbySrcBase, dwWidtgBytesDst);
pbyDst += dwWidtgBytesDst;
pbySrcBase -= dwWidthBytes;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -