⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 geotrans.cpp

📁 其中包括图像压缩的基本编码方法如Huffman编码算术编码JPEG 2000H.261压缩编码标准小波变换编码运动估计算法视频图象采集的VC实现等.
💻 CPP
字号:
// ************************************************************************
//  文件名:GeoTrans.cpp
//
//  图像几何变换函数库:
//
//  ZoomDIB()				- 缩放位图
//	Rotate()				- 旋转位图
//	Rectinication()			- 空间较正图像
//
// ************************************************************************

#include "stdafx.h"
#include "DIP_System.h"
#include "GeoTrans.h"
#include "SpaceFilter.h"
#include "math.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CGeoTrans

CGeoTrans::CGeoTrans()
{
}

CGeoTrans::~CGeoTrans()
{
}


BEGIN_MESSAGE_MAP(CGeoTrans, CWnd)
	//{{AFX_MSG_MAP(CGeoTrans)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CGeoTrans message handlers


/*************************************************************************
 *
 * 函数名称:
 *   ZoomDIB()
 *
 * 参数:
 *   HDIB	hDIB		- 待处理的DIB
 *   float	fZoomRatio	- 缩放比率
 *
 * 返回值:
 *   HDIB			    - 缩放后的DIB
 *
 * 说明:
 *   该函数用来缩放DIB图像,返回处理后的DIB
 *
 ************************************************************************/

HDIB CGeoTrans::ZoomDIB(HDIB hDIB, float fZoomRatio)
{
	// 源图像的宽度和高度
	LONG	lWidth;
	LONG	lHeight;
	
	// 缩放后图像的宽度和高度
	LONG	lNewWidth;
	LONG	lNewHeight;
	
	// 指向源图像的指针
	LPBYTE	lpDIBBits;

	// 指向DIB的指针
	LPBYTE lpDIB;

	// 缩放后新DIB句柄
	HDIB	hNewDIB;
	
	// 指向缩放图像对应象素的指针
	LPBYTE	lpDst;
	
	// 指向缩放图像的指针
	LPBYTE	lpNewDIB;
	LPBYTE	lpNewDIBBits;
	
	// 指向BITMAPINFO结构的指针(Win3.0)
	LPBITMAPINFOHEADER lpbmi;
	
	// 指向BITMAPCOREINFO结构的指针
	LPBITMAPCOREHEADER lpbmc;
	
	// 循环变量(象素在新DIB中的坐标)
	LONG	i;
	LONG	j;
	
	// 象素在源DIB中的坐标
	LONG	i0;
	LONG	j0;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到源DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是24-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 24)
	{
		// 提示用户
		MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return NULL;
	}

	// 更改光标形状
	BeginWaitCursor();

	// 获取图像的宽度
	lWidth = m_clsDIB.DIBWidth(lpDIB);
	 
	// 获取图像的高度
	lHeight = m_clsDIB.DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 24);

	// 计算缩放后的图像实际宽度
	// 此处直接加0.5是由于强制类型转换时不四舍五入,而是直接截去小数部分
	lNewWidth = (LONG) (lWidth * fZoomRatio + 0.5);
	
	// 计算缩放后的图像高度
	lNewHeight = (LONG) (lHeight * fZoomRatio + 0.5);
	
	// 计算图像每行的字节数
	LONG lNewLineBytes = WIDTHBYTES(lNewWidth * 24);

	// 分配内存,以保存新DIB
	hNewDIB = (HDIB) ::GlobalAlloc(GHND, lNewHeight * lNewLineBytes
				+ *(LPDWORD)lpDIB + m_clsDIB.PaletteSize(lpDIB));
	
	// 判断是否内存分配失败
	if (hNewDIB == NULL)
	{
		// 分配内存失败
		return NULL;
	}
	
	// 锁定内存
	lpNewDIB =  (LPBYTE)::GlobalLock((HGLOBAL) hNewDIB);
	
	// 复制DIB信息头和调色板
	memcpy(lpNewDIB, lpDIB, *(LPDWORD)lpDIB + m_clsDIB.PaletteSize(lpDIB));
	
	// 找到新DIB象素起始位置
	lpNewDIBBits = m_clsDIB.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 < lNewLineBytes; j++)
		{
			// 计算该象素在源DIB中的坐标
			i0 = (LONG) (i / fZoomRatio);
			j0 = (LONG) (j / (fZoomRatio * 3));
			
			// 对应缩放前象素的红色分量
			unsigned char R = *((unsigned char *)lpDIBBits + lLineBytes * i0 + 3 * j0);
			// 复制象素
			*((unsigned char *)lpNewDIBBits + lNewLineBytes * i + j) = R;
		
			// 源、目的图像移到G分量
			lpDst++;	j++;

			// 对应缩放前象素的绿色分量
			unsigned char G = *((unsigned char *)lpDIBBits + lLineBytes * i0 + 3 * j0 +1);
			// 复制象素
			*((unsigned char *)lpNewDIBBits + lNewLineBytes * i + j) = G;

			// 源、目的图像移到B分量
			lpDst++;	j++;

			// 对应缩放前象素的蓝色分量
			unsigned char B = *((unsigned char *)lpDIBBits + lLineBytes * i0 + 3 * j0 +2);
			// 复制象素
			*((unsigned char *)lpNewDIBBits + lNewLineBytes * i + j) = B;
		}		
	}

	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);

	// 恢复光标
	EndWaitCursor();
	
	// 返回
	return hNewDIB;
}


/*************************************************************************
 *
 * 函数名称:
 *   Rotate()
 *
 * 参数:
 *   HDIB	hDIB		- 待处理的DIB
 *   int	nAngle		- 缩放比率
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数用来旋转DIB图像
 *
 ************************************************************************/

void CGeoTrans::Rotate(HDIB hDIB, float fAngle)
{
	#define PI 3.14159	

	// 循环变量
	LONG i0;
	LONG j0;
	LONG i1;
	LONG j1;

	// 指向DIB的指针
	LPBYTE lpDIB;
	
	// 指向DIB象素指针
	LPBYTE lpDIBBits;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是24-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 24)
	{
		// 提示用户
		MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	// DIB的宽度
	LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
	
	// DIB的高度
	LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 24);

	// 旋转角度的弧度
	fAngle = (float)(fAngle * PI / 180);

	// 角度的正余弦
	float fSinAngle = (float)sin(fAngle);
	float fCosAngle = (float)cos(fAngle);

	// 不能用char,也不能用::strcpy()
	unsigned char* m_temp;
	m_temp=new unsigned char [lLineBytes * lHeight];

	// 复制空白数据到中间缓存
	for (i0 = 0; i0 < lLineBytes * lHeight; i0++)
		m_temp[i0] = 255;

	// 对各像素进行旋转处理
	for (i0 = 0; i0 < lHeight; i0 ++)
	{
		for (j0 = 0; j0 < lWidth; j0 ++)
		{
			// 计算旋转后的坐标位置
			j1 = (LONG)((j0 - lWidth / 2) * fCosAngle + (lHeight / 2 - i0) * fSinAngle + lWidth / 2 + 0.5);
			i1 = (LONG)((j0 - lWidth / 2) * fSinAngle - (lHeight / 2 - i0) * fCosAngle + lHeight / 2 + 0.5);

			// 将原始象素复制到目标位置
			if (i1 >= 0 && i1 < lHeight && j1 >= 0 && j1 < lWidth)
			{
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3);
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3 + 1] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3 + 1);
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3 + 2] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3 + 2);
			}
		}
	}
	
	// 回存处理结果到DIB
	for(i0 = 0; i0 < lLineBytes * lHeight; i0++)
		*(lpDIBBits + i0) = m_temp[i0];

	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);

	// 释放内存
	delete[] m_temp;
	
	// 恢复光标
	EndWaitCursor();
}


/*************************************************************************
 *
 * 函数名称:
 *   Rectinication()
 *
 * 参数:
 *   HDIB	hDIB		- 待处理的DIB
 *   int	nAngle		- 面倾斜角度
 *
 * 返回值:
 *   void			    - 无返回值
 *
 * 说明:
 *   该函数用来在空间矫正DIB图像
 *
 ************************************************************************/

void CGeoTrans::Rectinication(HDIB hDIB, float fAngle)
{
	#define PI 3.14159	

	// 循环变量
	LONG i0;
	LONG j0;
	LONG i1;
	LONG j1;

	// 指向DIB的指针
	LPBYTE lpDIB;
	
	// 指向DIB象素指针
	LPBYTE lpDIBBits;
	
	// 锁定DIB
	lpDIB = (LPBYTE) ::GlobalLock((HGLOBAL) hDIB);

	// 找到DIB图像象素起始位置
	lpDIBBits = m_clsDIB.FindDIBBits(lpDIB);
	
	// 判断是否是24-bpp位图
	if (m_clsDIB.DIBBitCount(lpDIB) != 24)
	{
		// 提示用户
		MessageBox("请先将其转换为24位色位图,再进行处理!", "系统提示" , MB_ICONINFORMATION | MB_OK);
		
		// 解除锁定
		::GlobalUnlock((HGLOBAL) hDIB);
		
		// 返回
		return;
	}
	
	// 更改光标形状
	BeginWaitCursor();
	
	// DIB的宽度
	LONG lWidth = m_clsDIB.DIBWidth(lpDIB);
	
	// DIB的高度
	LONG lHeight = m_clsDIB.DIBHeight(lpDIB);
	
	// 计算图像每行的字节数
	LONG lLineBytes = WIDTHBYTES(lWidth * 24);

	// 旋转角度的弧度
	fAngle = (float)(fAngle * PI / 180);

	// 角度的正余弦
	float fSinAngle = (float)sin(fAngle);
	float fCosAngle = (float)cos(fAngle);
	float fTgAngle = fSinAngle / fCosAngle;

	// 不能用char,也不能用::strcpy()
	unsigned char* m_temp;
	m_temp = new unsigned char [lLineBytes * lHeight];

	// 复制空白数据到中间缓存
	for (i0 = 0; i0 < lLineBytes * lHeight; i0++)
		m_temp[i0] = 255;

	// 先对X方向进行矫正处理
	for (i0 = 0; i0 < lHeight; i0 ++)
	{
		for (j0 = 0; j0 < lWidth; j0 ++)
		{
			// 计算校直后的坐标位置
			j1 = (LONG)(lWidth - (lWidth - j0) / fCosAngle + 0.5f);
			i1 = i0;			

			// 将原始象素复制到目标位置
			if (i1 >= 0 && i1 < lHeight && j1 >= 0 && j1 < lWidth)
			{
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3);
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3 + 1] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3 + 1);
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3 + 2] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3 + 2);
			}
		}
	}

	// 回存处理结果到DIB
	for(i0 = 0; i0 < lLineBytes * lHeight; i0++)
		*(lpDIBBits + i0) = m_temp[i0];

	// 调用中值滤波进行平滑处理
	CSpaceFilter clsSpaceFilter;
	clsSpaceFilter.MedianFilter(hDIB);

	// 再对y方向进行矫正处理
	for (i0 = 0; i0 < lHeight; i0 ++)
	{
		for (j0 = 0; j0 < lWidth; j0 ++)
		{
			// 计算校直后的坐标位置
			j1 = j0;
			if (i0 < lHeight / 2)
				i1 = (LONG)(i0 - (lHeight / 2 - i0) * fSinAngle * (lWidth - j1) / lWidth  + 0.5f);
			else
				i1 = (LONG)(i0 + (i0 - lHeight / 2) * fSinAngle * (lWidth - j1) / lWidth + 0.5f);

			// 将原始象素复制到目标位置
			if (i1 >= 0 && i1 < lHeight && j1 >= 0 && j1 < lWidth)
			{
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3);
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3 + 1] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3 + 1);
				m_temp[lLineBytes * (lHeight - i1 - 1) + j1 * 3 + 2] = *((unsigned char *)lpDIBBits + lLineBytes * (lHeight - i0 - 1) + j0 * 3 + 2);
			}
		}
	}

	// 回存处理结果到DIB
	for(i0 = 0; i0 < lLineBytes * lHeight; i0++)
		*(lpDIBBits + i0) = m_temp[i0];

	// 调用中值滤波进行平滑处理
	clsSpaceFilter.MedianFilter(hDIB);

	// 解除锁定
	::GlobalUnlock((HGLOBAL) hDIB);

	// 释放内存
	delete[] m_temp;
	
	// 恢复光标
	EndWaitCursor();
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -